All checks were successful
Deploy Fly.io Proxy / deploy (push) Successful in 1m28s
## Summary Expose Forgejo publicly at `forge.eblu.me` via the Fly.io reverse proxy — the first dynamic, authenticated public-facing service. - **Forgejo hardening:** Domain changed to forge.eblu.me, SSH stays on forge.ops.eblu.me, reverse proxy trust headers configured, local registration locked to external-only (Authentik SSO) - **Tailscale Ingress:** ExternalName Service + Ingress in tailscale-operator creates forge.tail8d86e.ts.net endpoint - **Fly.io proxy:** nginx server block with rate-limited auth endpoints (3r/s), fail2ban with custom nginx-deny action, security headers, /swagger blocked, WebSocket support, 512m body limit - **Authentik:** OAuth callback updated to forge.eblu.me - **DNS/TLS:** CNAME record in Pulumi, cert in fly-setup - **Rename:** ~29 files updated from forge.ops.eblu.me to forge.eblu.me (HTTPS refs only; SSH, container builds, and Caddy table kept as-is) ## Deployment Order 1. `mise run provision-indri -- --tags forgejo` (config changes) 2. Verify forge.ops.eblu.me still works 3. `argocd app set tailscale-operator --revision feature/forge-public && argocd app sync tailscale-operator` 4. Verify `curl https://forge.tail8d86e.ts.net` 5. `cd fly && fly deploy` 6. Verify pre-DNS: `curl -H "Host: forge.eblu.me" https://blumeops-proxy.fly.dev/` 7. `fly certs add forge.eblu.me -a blumeops-proxy` 8. `argocd app set authentik --revision feature/forge-public && argocd app sync authentik` 9. `mise run dns-preview && mise run dns-up` 10. Full verification (see below) 11. Rehearse `mise run fly-shutoff` 12. After merge: reset ArgoCD revisions to main, re-sync ## Verification Checklist - [ ] forge.eblu.me loads, shows public repos - [ ] forge.ops.eblu.me still works from tailnet - [ ] SSH clone via forge.ops.eblu.me:2222 works - [ ] HTTPS clone via forge.eblu.me works - [ ] UI shows forge.eblu.me for HTTPS clone, forge.ops.eblu.me for SSH - [ ] /swagger returns 403 - [ ] Rapid login attempts trigger 429 rate limit - [ ] fail2ban bans after 5 failed logins in 10 minutes - [ ] ArgoCD can still sync (SSH unaffected) - [ ] `mise run fly-shutoff` stops all public traffic - [ ] `mise run services-check` passes Reviewed-on: #278
2 KiB
2 KiB
| title | modified | tags | ||||
|---|---|---|---|---|---|---|
| Register Zot OIDC Client | 2026-02-21 |
|
Register Zot OIDC Client
Register a zot OAuth2 provider and application in Authentik via blueprint, following the same pattern as Grafana and Forgejo.
Completed in PR #236.
What Was Done
- Added
zot.yamlblueprint section toargocd/manifests/authentik/configmap-blueprint.yaml:- OAuth2Provider (
client_id: zot), Application, PolicyBinding (admins group),artifact-workloadsgroup, andzot-ciservice account
- OAuth2Provider (
- Client secret stored in 1Password as field
zot-client-secreton the "Authentik (blumeops)" item (referenced by item IDoor7os5kapczgpbwv7obkca4y4to avoid parentheses inop read) - ExternalSecret wired
zot-client-secret→ worker Deployment env varAUTHENTIK_ZOT_CLIENT_SECRET→ blueprint!Env - OIDC credentials template (
ansible/roles/zot/templates/oidc-credentials.json.j2) deployed by zot role with awhenguard; pre_task inansible/playbooks/indri.ymlfetches the secret from 1Password
Deviations from Original Plan
- Worker Deployment env var injection was an additional wiring step not originally listed
- Service account password and API keys are manual post-deploy steps (not automated in the blueprint)
Key Files
| File | Purpose |
|---|---|
argocd/manifests/authentik/configmap-blueprint.yaml |
Zot blueprint (provider + app + policy + group + service account) |
argocd/manifests/authentik/external-secret.yaml |
AUTHENTIK_ZOT_CLIENT_SECRET env var |
argocd/manifests/authentik/deployment-worker.yaml |
Env var injection for blueprint !Env |
ansible/roles/zot/templates/oidc-credentials.json.j2 |
OIDC credentials for zot |
ansible/playbooks/indri.yml |
Pre_task for zot OIDC client secret |
Related
- harden-zot-registry — Parent goal
- deploy-authentik — Authentik deployment (completed)