Each of the five roles touched in this branch now ships: * meta/argument_specs.yml: typed schema for every variable in defaults/main.yml plus the optional inputs surfaced via this branch (traefik_extra_hosts, authentik_host_rewrite_domains, authentik_proxy_apps.mode / .allowed_groups, drawio_extra_domains, drawio_authentik_forward_auth*, garage_webui_authentik_forward_auth*). All five specs load cleanly through ansible-core's ArgumentSpecValidator. * README.md: replaces the ansible-galaxy boilerplate (where it was still in place) with a focused write-up — service vars, required secrets, ForwardAuth/idempotency notes, dependencies, and a working example playbook. authentik and garage READMEs are rewritten to cover the new knobs while preserving their existing content.
3.7 KiB
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. First entry is the canonical hostname and is used asroot_domainingarage.toml.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