Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Garage Setup

Overview

Garage is an open-source distributed object storage service compatible with the Amazon S3 API. It lets you self-host S3-compatible storage on your own infrastructure — useful for backing up files, hosting app data, or serving as object storage for self-hosted services like Nextcloud.

Unlike cloud S3 services, Garage keeps your data on your own servers with no egress fees.

Prerequisites

  • Docker installed and configured (see Docker Setup)
  • Docker Compose installed (see Docker Compose)
  • Caddy running with external caddy network (see Caddy Setup)
  • Domain name pointed to your VPS

Docker Compose Setup

Create the Garage directory:

sudo mkdir -p /opt/garage
cd /opt/garage

Create garage.toml:

metadata_dir = "/var/lib/garage/meta"
data_dir = "/var/lib/garage/data"
db_engine = "sqlite"
replication_factor = 1

rpc_bind_addr = "[::]:3901"
rpc_public_addr = "127.0.0.1:3901"
rpc_secret = "<rpc-secret>"

[s3_api]
s3_region = "garage"
api_bind_addr = "[::]:3900"
root_domain = ".s3.<yourdomain>.com"

[s3_web]
bind_addr = "[::]:3902"
root_domain = ".web.<yourdomain>.com"
index = "index.html"

[admin]
api_bind_addr = "[::]:3903"
admin_token = "<admin-token>"
metrics_token = "<metrics-token>"

Generate secrets and replace the placeholders:

openssl rand -hex 32     # rpc-secret
openssl rand -base64 32  # admin-token
openssl rand -base64 32  # metrics-token

What are these secrets?

  • rpc_secret: Encrypts communication between Garage nodes (only matters in multi-node clusters)
  • admin_token: Authentication token for admin CLI commands
  • metrics_token: Token for accessing Prometheus metrics

Create docker-compose.yml:

services:
  garage:
    image: dxflrs/garage:v2.2.0
    container_name: garage
    ports:
      - "3900:3900"
    volumes:
      - ./garage.toml:/etc/garage.toml
      - garage_meta:/var/lib/garage/meta
      - garage_data:/var/lib/garage/data
    networks:
      - caddy
    restart: unless-stopped

volumes:
  garage_meta:
  garage_data:

networks:
  caddy:
    external: true

Start Garage:

sudo docker compose up -d

Note: Check Docker Hub for the latest version tag. Replace v2.2.0 with the newest stable release.

Initialize Garage

Garage requires a one-time initialization before it can store data.

1. Check node status

docker exec garage /garage status

Copy the node ID from the output (first column, e.g., 563e1ac825ee3323).

2. Assign cluster layout

Replace <node-id> with the ID from the previous step:

docker exec garage /garage layout assign -z dc1 -c 1G <node-id>
docker exec garage /garage layout apply --version 1

3. Create a bucket

docker exec garage /garage bucket create my-bucket

4. Create an API key

docker exec garage /garage key create my-key

5. Allow key access to the bucket

docker exec garage /garage bucket allow --read --write my-bucket --key my-key

6. Get key credentials

docker exec garage /garage key info my-key

Save the Key ID and Secret key — you’ll need them for S3 clients.

Caddy Configuration

Garage serves static websites from buckets through the S3 web endpoint (port 3902). To expose your buckets as websites via HTTPS, add to your Caddyfile:

garage.<yourdomain>.com {
    reverse_proxy garage:3902
}

Note: Port 3902 is the S3 web endpoint — it serves static website files stored in your buckets. It is NOT a web admin UI. Garage v2 does not include a graphical admin panel; you manage buckets via the CLI or S3-compatible tools.

S3 API Access

For S3 API access through Caddy, you need wildcard subdomain support. S3 clients access buckets as my-bucket.s3.<yourdomain>.com. Caddy can handle this with wildcard certificates, but requires a DNS challenge:

*.s3.<yourdomain>.com {
    tls {
        dns <provider>
    }
    reverse_proxy garage:3900
}

Setting up DNS challenges requires Caddy DNS plugins and is beyond the scope of this guide. For most use cases, accessing Garage directly via Tailscale or the awscli endpoint (shown below) is simpler.

Restart Caddy after any changes:

docker compose -f /opt/caddy/docker-compose.yml restart caddy

Access Garage

Garage is managed via the CLI or any S3-compatible client. There is no web admin UI.

Using awscli

Install awscli:

sudo apt install -y awscli

Configure your credentials (the interactive setup stores them securely in ~/.aws/credentials):

aws configure

When prompted:

  • AWS Access Key ID: Your Garage key ID from step 6 above
  • AWS Secret Access Key: Your Garage secret key from step 6
  • Default region name: garage
  • Default output format: (leave blank or type json)

Then set the endpoint URL:

export AWS_ENDPOINT_URL=https://127.0.0.1:3900

Tip: Add the export line to your ~/.bashrc so it’s set automatically in new sessions.

Use Garage:

aws s3 ls
aws s3 cp file.txt s3://my-bucket/
aws s3 ls s3://my-bucket/

Managing Buckets

docker exec garage /garage bucket list                      # List all buckets
docker exec garage /garage bucket info my-bucket            # Show bucket details
docker exec garage /garage key list                         # List API keys
docker exec garage /garage status                           # Cluster node status

Key Commands

docker compose -f /opt/garage/docker-compose.yml up -d      # Start
docker compose -f /opt/garage/docker-compose.yml down       # Stop
docker compose -f /opt/garage/docker-compose.yml logs -f    # View logs

Data Persistence

Garage stores bucket metadata in the garage_meta volume and object data in the garage_data volume. Your data persists across container restarts.