Set Up Garage as Backup Storage for Zimly: A Step-by-Step Guide

Garage Object Storage is an open-source, S3-compatible object store developed by Deuxfleurs. It is used by Nextcloud and other projects. Garage provides an API and a CLI that allow you to manage buckets, access keys, and secrets. It is also compatible with other S3 clients.

Prerequisites

In this guide, we’ll set up a local Garage instance using Docker. This setup is intended for development or testing purposes only — for production deployments, refer to the official Garage documentation for best practices.

The setup steps are similar to configuring Garage for Nextcloud.

Before you begin, make sure to:

Docker compose

We’ll use Docker Compose to automate some setup steps, including key/secret creation, policy assignment, and bucket creation. This setup uses a custom garage.toml configuration file and a docker-compose.yml file.

# Create a secret
openssl rand -hex 32

Copy and paste the garage.toml file to your working directory and mount it in your docker-compose.yaml file. Make sure you replace the rpc_secret and use the same s3_region later in your Zimly configuration.

metadata_dir = "/var/lib/garage/meta"
data_dir = "/var/lib/garage/data"
db_engine = "sqlite" # SQLite is only recommended for testing, use LMDB in production

replication_factor = 1

rpc_bind_addr = "[::]:3901"
rpc_secret = "..." # insert the created secret here

[s3_api]
s3_region = "garage" # Make sure you set the region accordingly in Zimly.
api_bind_addr = "[::]:3900"
root_domain = "localhost"

services:
  zimly-garage:
    image: dxflrs/garage:v1.1.0
    ports:
      - "3900:3900"
    volumes:
      - ./garage.toml:/etc/garage.toml
      - ./garage-meta:/var/lib/garage/meta
      - ./garage-data:/var/lib/garage/data

Start the service with docker compose up -d.

Set the garage alias correctly and paste the following script to get a minimal setup working for Zimly. Note down the generated key and secret.

# Copy the container id
docker ps
alias garage="docker exec -ti <CONTAINER_NAME> /garage"

ZIMLY_KEY_NAME=zimly-key
ZIMLY_BUCKET=2025-zimly
    
node_id="$(garage node id | head -n 1 | tr -d '\r\n' | xargs)"
garage layout assign -z dc1 -c1G ${node_id}
garage layout apply --version 1
garage bucket create ${ZIMLY_BUCKET}

raw_key="$(garage key create ${ZIMLY_KEY_NAME})"
# Extract Key ID
key_id=$(echo "$raw_key" | grep "Key ID:" | awk '{print $NF}')

# Extract Secret key
secret_key=$(echo "$raw_key" | grep "Secret key:" | awk '{print $NF}')

# Print values (or use them as needed)
echo "Key ID: $key_id"
echo "Secret Key: $secret_key"

garage bucket allow --read --write --owner ${ZIMLY_BUCKET} --key ${ZIMLY_KEY_NAME}

Finalizing Your Backup Setup in zimly

Now, let’s put everything together and finalize the backup setup in zimly. We’ll create a new configuration to back up the Pictures folder.

Name: Zimly Docker bucket
URL: http://localhost:3900
Region: garage
Key: <GARAGE_KEY_ID>
Secret: <GARAGE_KEY_SECRET>
Bucket: 2025-zimly

Folder: Pictures