Garage
| Description / name | Input element |
|---|---|
| Container Registry | |
| Container Configuration Root Path | |
| Timezone | |
| User ID | |
| Group ID | |
| Garage Host Port | |
| Garage /config Path | |
| Garage /data Path |
Lightweight, geo-distributed S3-compatible object storage service designed for self-hosting on commodity hardware.
| Port | 3900 |
| Registry | ghcr.io/daemonless/garage |
| Daemonless | daemonless/garage |
| Source | git.deuxfleurs.fr/Deuxfleurs/garage |
| Website | garagehq.deuxfleurs.fr |
Version Tags
Multi-arch manifests — resolve automatically to the right image for your platform.
| Tag | Description | Best For |
|---|---|---|
latest / pkg |
FreeBSD Quarterly. Uses stable, tested packages. | Most users — recommended. |
pkg-latest |
FreeBSD Latest. Rolling package updates. | Staying current. |
| Tag | Description | Best For |
|---|---|---|
latest-amd64 / pkg-amd64 |
FreeBSD Quarterly. Uses stable, tested packages. | Most users — recommended. |
pkg-latest-amd64 |
FreeBSD Latest. Rolling package updates. | Staying current. |
| Tag | Description | Best For |
|---|---|---|
latest-aarch64 / pkg-aarch64 |
FreeBSD Quarterly. Uses stable, tested packages. | Most users — recommended. |
pkg-latest-aarch64 |
FreeBSD Latest. Rolling package updates. | Staying current. |
Before deploying, ensure your host environment is ready. See the Quick Start Guide for host setup instructions, including the security model for host vs. container privileges.
Deployment
Save as compose.yaml, then run podman-compose up -d.
Save as run.sh, then run sh run.sh.
Save as garage-deploy.yaml, then run ansible-playbook garage-deploy.yaml.
Warning
Exposing ports in AppJail means that your service can be reached from remote hosts. If that is not your intention, do not expose the ports and communicate with the service using the jail's IPv4 address or hostname assigned by the virtual network.
Save the files above, then run appjail-director up.
Save the files above, then run sh run.sh.
Experimental
Bastille's OCI support is experimental. It requires buildah and shares the host network stack (inherit). Mount volumes with --volume HOST JAIL; without it, image-declared volumes are stored under ${bastille_volumesdir}/${jail}.
Save as bastille-compose.yml, then run bastille up.
Interactive Configuration
Parameters
Environment Variables
| Variable | Default | Description |
|---|---|---|
PUID |
1000 |
User ID for the application process |
PGID |
1000 |
Group ID for the application process |
TZ |
UTC |
Timezone for the container |
RPC_SECRET |
${RPC_SECRET} |
32-byte hex RPC secret for cluster authentication (auto-generated on first run if unset) |
ADMIN_TOKEN |
${ADMIN_TOKEN} |
Admin API and metrics authorization bearer token (auto-generated on first run if unset) |
RPC_PUBLIC_ADDR |
${RPC_PUBLIC_ADDR:-127.0.0.1:3901} |
Address other cluster nodes reach this one on. The default suits a single node; clustering needs a routable address. |
GARAGE_AUTO_LAYOUT |
${GARAGE_AUTO_LAYOUT:-true} |
Assign a single-node layout on first boot so the node stores data without manual setup. Set false when joining an existing cluster. |
GARAGE_ZONE |
${GARAGE_ZONE:-dc1} |
Zone name used by the automatic single-node layout |
GARAGE_CAPACITY |
${GARAGE_CAPACITY:-10G} |
Storage this node advertises to the cluster, e.g. 10G or 2T |
GARAGE_ARGS |
`` | Additional command-line arguments passed to garage server |
Volumes
| Path | Description |
|---|---|
/config |
Configuration directory containing garage.toml |
/data |
Object storage: metadata in /data/meta, data blocks in /data/data |
Ports
| Port | Protocol | Description |
|---|---|---|
3900 |
TCP | S3 API endpoint |
3901 |
TCP | RPC endpoint for inter-cluster node communication |
3902 |
TCP | S3 web endpoint (static website hosting) |
3903 |
TCP | Admin API and Prometheus metrics endpoint |
There is no web UI
Port 3900 is the S3 API and only answers SigV4-signed requests. Opening it in a browser always returns:
That is Garage working, not a fault. Use an S3 client, the admin API on
3903, or the garage CLI.
Modern AWS clients: turn off flexible checksums
botocore >= 1.36 and aws-cli >= 2.23 send CRC32 "flexible checksums" by
default, and Garage's multipart checksum does not match what they compute.
A large download then aborts with FlexibleChecksumError even though the
object is intact (verified: md5 of a 12 MB object matches end to end).
Small objects are unaffected; this only bites on multipart transfers.
First run: assign a layout
A fresh node starts with NO ROLE ASSIGNED and stores nothing until a
layout is applied. This container does that for you on first boot
(GARAGE_AUTO_LAYOUT=true, zone GARAGE_ZONE, size GARAGE_CAPACITY).
Set GARAGE_AUTO_LAYOUT=false when joining an existing cluster, and assign
the layout across nodes yourself:
-c is the capacity this node advertises; -z its zone.
Create a bucket and key
Then point any S3 client at it, with region garage:
Admin API
The admin token is generated into /config/garage.toml on first run (or set
ADMIN_TOKEN):
Static website hosting
Served on 3902, not 3900, and matched by Host header:
FreeBSD notes
The generated config binds 0.0.0.0 rather than [::]. FreeBSD defaults
net.inet6.ip6.v6only=1, so an IPv6 wildcard socket refuses IPv4 and the
service would be unreachable on 127.0.0.1 -- taking the healthcheck and
the s6 readiness probe down with it.
rpc_public_addr is pinned to 127.0.0.1:3901, which suits a single node.
Clustering needs it set to an address the other nodes can reach.
Implementation Details
- Architectures: amd64, aarch64
- User:
bsd(UID/GID set via PUID/PGID). Defaults to1000:1000. - Base: Built on
ghcr.io/daemonless/base(FreeBSD 15.1).
Need help? Join our Discord community.