This commit is contained in:
@@ -0,0 +1,224 @@
|
||||
# authentik
|
||||
|
||||
Kubernetes deployment source-of-truth repository for `authentik`.
|
||||
|
||||
This template is intended for applications deployed with ArgoCD through an
|
||||
`ApplicationSet`. It uses a `base/` plus `overlays/` layout, stores runtime
|
||||
secrets as SOPS-encrypted manifests, and includes a Gitea workflow that checks
|
||||
Kubernetes YAML syntax on every push and pull request. It also ships with a
|
||||
dormant bootstrap `ApplicationSet` that only becomes active after an explicit
|
||||
enable change and a promotion into `main`.
|
||||
|
||||
## Layout
|
||||
|
||||
```text
|
||||
.
|
||||
├── .gitea/
|
||||
│ ├── template
|
||||
│ └── workflows/validate.yaml
|
||||
├── .github/
|
||||
│ └── workflows/check-sops-sync.yml
|
||||
├── .sops.yaml
|
||||
├── bootstrap/
|
||||
│ ├── applicationset.yaml
|
||||
│ └── config.yaml
|
||||
├── manifest/
|
||||
│ ├── base/
|
||||
│ │ ├── deployment.yaml
|
||||
│ │ ├── kustomization.yaml
|
||||
│ │ ├── namespace.yaml
|
||||
│ │ └── service.yaml
|
||||
│ ├── components/
|
||||
│ │ └── example-component/
|
||||
│ └── overlays/
|
||||
│ └── production/
|
||||
│ ├── ingressroute.yaml
|
||||
│ ├── kustomization.yaml
|
||||
│ ├── secret-generator.yaml
|
||||
│ ├── secret.secret.yaml
|
||||
│ └── storage/
|
||||
│ ├── persistentvolumeclaim.yaml
|
||||
│ └── persistentvolume-nfs.yaml
|
||||
└── scripts/
|
||||
├── ci/check-sops-sync
|
||||
├── git-hooks/pre-commit
|
||||
├── install-git-hooks
|
||||
└── lib/
|
||||
├── sops-path-regexes
|
||||
└── sops-sync-lib
|
||||
```
|
||||
|
||||
## First edits
|
||||
|
||||
Update these files before the first deployment:
|
||||
|
||||
1. `manifest/base/deployment.yaml`
|
||||
Set the container image, ports, probes, resource requests, and any required
|
||||
environment variables.
|
||||
2. `manifest/overlays/production/ingressroute.yaml`
|
||||
Set the real hostname, entry point names, and middleware references if used.
|
||||
3. `manifest/overlays/production/storage/persistentvolumeclaim.yaml`
|
||||
Set the requested size, access mode, and storage class for the environment.
|
||||
4. `.sops.yaml`
|
||||
Replace the sample age recipient with the public key that ArgoCD should use
|
||||
for decryption.
|
||||
5. `manifest/overlays/production/secret.secret.yaml`
|
||||
Re-encrypt the placeholder secret values with your own data.
|
||||
|
||||
## Bootstrap activation model
|
||||
|
||||
This template is designed to start on an `init` branch. The intended flow is:
|
||||
|
||||
1. Create the repository from this template with `init` as the initial branch.
|
||||
2. Tailor the manifests, secrets, storage, and ingress on `init`.
|
||||
3. Keep `bootstrap/config.yaml` set to `enabled: false` while the repository is
|
||||
being prepared.
|
||||
4. Create `main` by merging `init` only when the repository is ready to be part
|
||||
of the delivery pipeline.
|
||||
5. Deliberately change `bootstrap/config.yaml` to `enabled: true` on `main` to
|
||||
allow the workflow to apply the bootstrap `ApplicationSet`.
|
||||
|
||||
The workflow behavior is:
|
||||
|
||||
- `bootstrap/applicationset.yaml` is ignored by validation while bootstrap is disabled
|
||||
- no cluster apply is attempted unless the workflow runs on `main`
|
||||
- cluster apply also requires the `KUBECONFIG_B64` Gitea secret
|
||||
|
||||
## Bootstrap files
|
||||
|
||||
- `bootstrap/config.yaml`
|
||||
Repository-local activation switch. Default is disabled.
|
||||
- `bootstrap/applicationset.yaml`
|
||||
ArgoCD `ApplicationSet` manifest template for this repository.
|
||||
|
||||
If the repository is created by copying files with plain Git instead of Gitea's
|
||||
template expansion, you must replace the `${REPO_NAME...}` placeholders in
|
||||
`bootstrap/applicationset.yaml` before enabling bootstrap.
|
||||
|
||||
## Storage model
|
||||
|
||||
Storage is overlay-owned, so each environment can request different backing
|
||||
storage without sharing claims across environments.
|
||||
|
||||
- `manifest/overlays/production/storage/persistentvolumeclaim.yaml`
|
||||
Default writable application storage. With the default `longhorn`
|
||||
`storageClassName`, Kubernetes dynamically provisions the backing PV when the
|
||||
claim is created.
|
||||
- `manifest/overlays/production/storage/persistentvolume-nfs.yaml`
|
||||
Optional static PV example for NFS-backed or pre-provisioned shared storage.
|
||||
This file is not referenced by default. Add it to the overlay kustomization
|
||||
only when you need a static PV.
|
||||
|
||||
The base deployment mounts the claim at `/data`.
|
||||
|
||||
If storage should be shared between multiple applications in different
|
||||
repositories, keep those applications in the same namespace and have a single
|
||||
repository own the PVC resource. The other repositories should reference the
|
||||
same claim name from their deployments instead of creating a duplicate PVC.
|
||||
|
||||
## Secret workflow
|
||||
|
||||
1. Generate an age key pair.
|
||||
2. Store the private key where ArgoCD / ksops can read it.
|
||||
3. Update `.sops.yaml` with the matching public recipient.
|
||||
4. Re-encrypt `manifest/overlays/production/secret.secret.yaml`.
|
||||
|
||||
Example:
|
||||
|
||||
```bash
|
||||
age-keygen -o age-key.txt
|
||||
sops --encrypt --in-place manifest/overlays/production/secret.secret.yaml
|
||||
```
|
||||
|
||||
## Repo-managed SOPS sync
|
||||
|
||||
This repo also supports sync-managed secrets using the naming convention:
|
||||
|
||||
```text
|
||||
foo.yaml -> foo.enc.yaml -> foo.enc.yaml.sync-hmac
|
||||
```
|
||||
|
||||
- `foo.yaml`
|
||||
Local plaintext source. Keep it gitignored and untracked.
|
||||
- `foo.enc.yaml`
|
||||
Tracked SOPS-encrypted file.
|
||||
- `foo.enc.yaml.sync-hmac`
|
||||
Tracked HMAC sidecar used to prove the encrypted file still matches the last
|
||||
synced plaintext content.
|
||||
|
||||
Requirements:
|
||||
|
||||
- `SOPS_SYNC_HMAC_KEY` must be set locally for hooks and in CI
|
||||
- `sops`, `openssl`, and either `yq` or `python3` with `PyYAML` must be available
|
||||
- CI also needs access to the repo's SOPS decryption mechanism, such as an age key
|
||||
|
||||
Generate a local HMAC key:
|
||||
|
||||
```bash
|
||||
openssl rand -hex 32
|
||||
```
|
||||
|
||||
Set it for the current shell session:
|
||||
|
||||
```bash
|
||||
export SOPS_SYNC_HMAC_KEY='<paste-generated-key-here>'
|
||||
```
|
||||
|
||||
Persist it in `zsh`:
|
||||
|
||||
```bash
|
||||
echo "export SOPS_SYNC_HMAC_KEY='<paste-generated-key-here>'" >> ~/.zshrc
|
||||
source ~/.zshrc
|
||||
```
|
||||
|
||||
Persist it in `bash`:
|
||||
|
||||
```bash
|
||||
echo "export SOPS_SYNC_HMAC_KEY='<paste-generated-key-here>'" >> ~/.bashrc
|
||||
source ~/.bashrc
|
||||
```
|
||||
|
||||
Verify it is set:
|
||||
|
||||
```bash
|
||||
printenv SOPS_SYNC_HMAC_KEY
|
||||
```
|
||||
|
||||
Install the local hook:
|
||||
|
||||
```bash
|
||||
scripts/install-git-hooks
|
||||
```
|
||||
|
||||
Local workflow:
|
||||
|
||||
1. Keep your plaintext secret local-only, for example `manifest/overlays/production/secret.yaml`.
|
||||
2. Stage either the plaintext file or its `.enc.yaml` twin.
|
||||
3. On pre-commit, the hook encrypts the plaintext if needed, updates the
|
||||
`.sync-hmac` sidecar, and stages both tracked files.
|
||||
|
||||
CI behavior:
|
||||
|
||||
- CI fails if a tracked `.enc.yaml` file is not valid SOPS content
|
||||
- CI fails if the `.sync-hmac` sidecar is missing
|
||||
- CI fails if decrypted plaintext no longer matches the tracked sidecar HMAC
|
||||
|
||||
Security tradeoffs:
|
||||
|
||||
- The sidecar is an HMAC, not a plain checksum, so the plaintext fingerprint is
|
||||
keyed and not directly reusable without `SOPS_SYNC_HMAC_KEY`
|
||||
- Anyone who can decrypt the repo secret files and also access the HMAC key can
|
||||
recompute sidecars, so protect both inputs appropriately
|
||||
- Plaintext local files must remain gitignored and never be committed
|
||||
|
||||
## ArgoCD ApplicationSet path
|
||||
|
||||
Point the generated ArgoCD `Application` at:
|
||||
|
||||
```text
|
||||
manifest/overlays/production
|
||||
```
|
||||
|
||||
If your `ApplicationSet` uses repository scanning, this repository is designed
|
||||
to be the single source of truth for one application, with ArgoCD rendering the
|
||||
selected overlay.
|
||||
Reference in New Issue
Block a user