digitalboard.core/roles/garage
Simon Bärlocher 1157448d59
fix(garage): make bootstrap & provision idempotent across reruns
* 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`).
2026-05-26 14:03:58 +02:00
..
defaults feat(drawio,garage): optional Authentik ForwardAuth in front of UIs 2026-05-26 14:03:38 +02:00
handlers feat: add basic garage s3 storage role 2025-11-07 17:35:32 +01:00
meta feat: add basic garage s3 storage role 2025-11-07 17:35:32 +01:00
tasks fix(garage): make bootstrap & provision idempotent across reruns 2026-05-26 14:03:58 +02:00
templates feat(drawio,garage): optional Authentik ForwardAuth in front of UIs 2026-05-26 14:03:38 +02:00
tests feat: add basic garage s3 storage role 2025-11-07 17:35:32 +01:00
vars feat: add basic garage s3 storage role 2025-11-07 17:35:32 +01:00
README.md feat: add basic garage s3 storage role 2025-11-07 17:35:32 +01:00

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 communication
  • garage_admin_token: Admin API token
  • garage_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 proxy network to be created
  • htpasswd utility (from apache2-utils package) 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:

  1. Connect to the node and get the node ID:

    docker exec -ti garage /garage node id
    
  2. 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
    
  3. Create a key for S3 access:

    docker exec -ti garage /garage key create my-key
    
  4. 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