* bootstrap: `garage layout show` truncates node IDs to 16 chars, but
the membership check compared against the full hex. After the first
successful join, subsequent runs no longer found the short ID in
`layout show` and re-issued `layout assign`, marking the task
changed every time. Compare against both the truncated and the full
form so a configured node stays detected. Also tag the read-only
`garage node id` / `layout show` probes with `changed_when: false`.
* provision keys: the old parser sliced `stdout_lines[1:]` to drop the
header but missed that INFO log lines and ANSI escapes can interleave
with table rows. Replace with an explicit `^GK[0-9a-fA-F]+` filter
after stripping ANSI, so probe-output noise no longer corrupts the
existing-keys set and triggers spurious `key new` calls.
* provision buckets: same class of fix — match `^[0-9a-f]{16}\s` data
rows instead of slicing `[2:]`, which broke when the table header
wasn't exactly two lines.
* provision permissions: pre-read `bucket info` for each (key, bucket)
pair and only run `bucket allow` when the current `RWO` flag set for
that key ID doesn't already match the desired permissions. Previously
`bucket allow` ran unconditionally and reported changed every play.
* `changed_when: false` on all read-only probes (`key list`, `key info`,
`bucket list`).
|
||
|---|---|---|
| .. | ||
| defaults | ||
| handlers | ||
| meta | ||
| tasks | ||
| templates | ||
| tests | ||
| vars | ||
| README.md | ||
Garage
Ansible role to deploy Garage S3-compatible object storage using Docker Compose.
Requirements
- Docker and Docker Compose installed on the target host
- Ansible collection:
community.docker - Traefik reverse proxy (for external access)
Role Variables
Key variables defined in defaults/main.yml:
Base Configuration:
docker_compose_base_dir: Base directory for Docker Compose files (default:/etc/docker/compose)docker_volume_base_dir: Base directory for Docker volumes (default:/srv/data)
Garage Configuration:
garage_service_name: Service name (default:garage)garage_image: Garage Docker image (default:dxflrs/garage:v2.1.0)garage_s3_domain: Domain for S3 API endpoint (default:storage.local.test)garage_web_domain: Domain for S3 web endpoint (default:web.storage.local.test)garage_webui_domain: Domain for web console (default:console.storage.local.test)
Garage Storage Configuration:
garage_replication_factor: Replication factor (default:1)garage_compression_level: Compression level (default:1)garage_db_engine: Database engine (default:lmdb)garage_s3_region: S3 region (default:us-east-1)
Garage Ports:
garage_s3_api_port: S3 API port (default:3900)garage_s3_web_port: S3 web port (default:3902)garage_admin_port: Admin API port (default:3903)garage_rpc_port: RPC port (default:3901)
Garage Security:
garage_rpc_secret: RPC secret for node communicationgarage_admin_token: Admin API tokengarage_metrics_token: Metrics API token
Garage WebUI Configuration:
garage_webui_enabled: Enable web UI (default:true)garage_webui_image: WebUI Docker image (default:khairul169/garage-webui:latest)garage_webui_port: WebUI port (default:3909)garage_webui_username: WebUI username (default:admin)garage_webui_password: WebUI password in plaintext (default:admin)
Traefik Configuration:
garage_traefik_network: Traefik network name (default:proxy)garage_internal_network: Internal network name (default:internal)garage_use_ssl: Enable SSL (default:true)
Dependencies
This role requires:
- Traefik reverse proxy to be configured and the
proxynetwork to be created htpasswdutility (fromapache2-utilspackage) for generating bcrypt password hashes
Example Playbook
- hosts: storage_servers
roles:
- role: garage
vars:
garage_s3_domain: "storage.example.com"
garage_rpc_secret: "your-secure-rpc-secret"
garage_admin_token: "your-admin-token"
garage_webui_enabled: true
garage_webui_username: "admin"
garage_webui_password: "secure-password"
Note: The WebUI password is specified in plaintext and will be automatically hashed using bcrypt during deployment. The role uses htpasswd to generate a secure bcrypt hash that is then properly escaped for use in Docker Compose.
Post-Installation
After deployment, you need to configure the Garage cluster:
-
Connect to the node and get the node ID:
docker exec -ti garage /garage node id -
Configure the node layout:
docker exec -ti garage /garage layout assign -z dc1 -c 1G <node-id> docker exec -ti garage /garage layout apply --version 1 -
Create a key for S3 access:
docker exec -ti garage /garage key create my-key -
Create a bucket:
docker exec -ti garage /garage bucket create my-bucket docker exec -ti garage /garage bucket allow my-bucket --read --write --key my-key
License
MIT-0