Two related additions for gating a cross-host service (garage WebUI on a storage host) behind authentik without breaking on TLS or X-Forwarded-Host: garage role: - Add garage_webui_domains (list), mirroring garage_s3_domains. The console router now accepts every entry, so a DMZ reverseproxy can use a backend_host whose cert SAN matches an internal *.int.* name instead of connecting by IP (which fails acme cert verification). Defaults to the single garage_webui_domain so existing inventories are unaffected. authentik_outpost_proxy role (new): - Standalone proxy (ForwardAuth) outpost, modelled on authentik_outpost_ldap. Co-locate it with the protected service so the ForwardAuth subrequest reaches authentik over the local docker network. The embedded outpost only works for services on the authentik host: a cross-host subrequest routed through an extra reverse-proxy hop arrives with a polluted X-Forwarded-Host (port/comma-appended), which the outpost no longer matches against the provider's external_host (404). |
||
|---|---|---|
| .. | ||
| defaults | ||
| handlers | ||
| meta | ||
| tasks | ||
| templates | ||
| tests | ||
| vars | ||
| README.md | ||
Garage
Ansible role to deploy Garage S3-compatible object storage via Docker Compose, with declarative key/bucket provisioning and an optional WebUI behind htpasswd or authentik ForwardAuth.
Requirements
- Docker and Docker Compose installed on the target host
- Ansible collection:
community.docker htpasswd(fromapache2-utils/httpd-tools) when the WebUI is enabled and authentik ForwardAuth is not used- Traefik with a shared
garage_traefik_network(defaultproxy)
Role variables
Full spec with types and defaults: meta/argument_specs.yml. The most
common overrides:
Service
garage_s3_domains: FQDNs the S3 router accepts. The first entry is the canonical hostname;garage.tomlderives the virtual-hosted-style S3root_domainfrom it as.s3.<first-entry>(so buckets resolve under<bucket>.s3.<first-entry>).garage_web_domain,garage_webui_domain: separate hostnames for the S3-website endpoint and the console.garage_image,garage_replication_factor,garage_db_engine,garage_s3_region.
Required secrets
Generate with openssl rand -hex 32 (32 bytes / 64 hex chars):
garage_rpc_secret: node-to-node RPC secretgarage_admin_token: admin API tokengarage_metrics_token: metrics endpoint token
WebUI authentication
Three modes:
- htpasswd (default):
garage_webui_username/garage_webui_passwordin plaintext. The role hashes the password withhtpasswd -nbBC 10, persists the hash on disk, and re-verifies withhtpasswd -vbBso unchanged passwords don't churn the play. - authentik ForwardAuth: set
garage_webui_authentik_forward_auth: trueandgarage_webui_authentik_forward_auth_url: "https://auth.example.com/outpost.goauthentik.io/auth/traefik".AUTH_USER_PASSis dropped from the container env so authentik is the only gate. - Disabled:
garage_webui_enabled: false.
Layout bootstrap
Setting garage_bootstrap_enabled: true runs the bootstrap task, which
joins the local node to the layout (zone: garage_bootstrap_zone,
capacity: garage_bootstrap_capacity) on the first run. The check
tolerates the 16-char truncation that garage layout show performs.
Declarative S3 keys and buckets
garage_s3_keys:
- name: nextcloud
buckets:
- name: nextcloud-data
permissions: [read, write]
- name: backup
buckets:
- name: restic-prod
permissions: [read, write, owner]
The role:
- Lists existing keys (
garage key list), creates missing ones - Lists existing buckets (
garage bucket list), creates missing ones - Reads current permissions via
garage bucket infoand runsgarage bucket allowonly when the current RWO flags for the key don't already match the desired permissions
stdout parsing is hardened against ANSI escapes and interleaved INFO
log lines, so probe noise no longer produces spurious changes.
Dependencies
- Traefik network (
garage_traefik_network, defaultproxy) - Internal network (
garage_internal_network, defaultinternal)
Example playbook
- hosts: storage_servers
roles:
- role: digitalboard.core.garage
vars:
garage_s3_domains:
- "storage.example.com"
- "storage.int.example.com"
garage_rpc_secret: "{{ vault_garage_rpc_secret }}"
garage_admin_token: "{{ vault_garage_admin_token }}"
garage_metrics_token: "{{ vault_garage_metrics_token }}"
garage_bootstrap_enabled: true
garage_webui_authentik_forward_auth: true
garage_webui_authentik_forward_auth_url: "https://auth.example.com/outpost.goauthentik.io/auth/traefik"
garage_s3_keys:
- name: nextcloud
buckets:
- name: nextcloud-data
permissions: [read, write]
License
MIT-0