Sign inSign up

waazaafr/garage-s3-tailscale

By waazaafr

•Updated about 1 month ago

An S3 object store so reliable you can run it outside datacenters by DeuxFleurs with tailscale.

Image
Content management system
0

10K+

waazaafr/garage-s3-tailscale repository overview

⁠Garage S3 with Tailscale

A ready-to-run Docker image for Garage⁠, the lightweight, S3-compatible distributed object storage made by Deuxfleurs⁠, with a built-in Tailscale⁠ client.

Your Garage nodes join your tailnet and talk to each other over Tailscale: build a multi-site cluster without opening any port on the internet.

Don't need Tailscale? Use waazaafr/garage-s3-simple⁠ instead.


⁠Features

  • 📦 Official Garage binary, on Alpine Linux for a minimal footprint
  • 🔒 Built-in Tailscale client: the node's Tailscale IP is detected and used automatically
  • ⚙️ Automatic garage.toml generation from environment variables
  • 🧰 AWS CLI pre-installed (with an s3 alias for aws s3)
  • 📊 Optional web UI to monitor your Garage node
  • 🖥️ Multi-arch: linux/amd64 and linux/arm64

⁠Tags

TagGarage version
latestlatest release
2.4.1v2.4.1⁠

New image releases follow the Garage releases⁠ from Deuxfleurs.


⁠Quick start

  1. Create an auth key in the Tailscale admin console⁠ (a reusable key is recommended for containers).
  2. Start the container:
⁠Docker Compose
services:
  garage:
    image: waazaafr/garage-s3-tailscale:latest
    container_name: garage
    restart: unless-stopped
    cap_add:
      - NET_ADMIN
      - SYS_MODULE
    devices:
      - /dev/net/tun
    ports:
      - "9000:9000"   # S3 API
      - "3901:3901"   # RPC
      - "3902:3902"   # S3 web hosting
      - "3903:3903"   # Admin API
      - "4080:4080"   # Web UI (optional)
    volumes:
      - ./garage/config:/config
      - ./garage/data:/data
      - ./garage/meta:/meta
      - ./garage/tailscale:/var/lib/tailscale
    environment:
      TS_AUTHKEY: "tskey-auth-xxxxx"
      TS_HOSTNAME: "garage-node1"
      ADMIN_TOKEN: "your-secure-token"
      WEBUI_ENABLED: "true"
⁠Docker run
docker run -d \
  --name garage \
  --restart unless-stopped \
  --cap-add=NET_ADMIN \
  --cap-add=SYS_MODULE \
  --device=/dev/net/tun \
  -p 9000:9000 \
  -p 3901:3901 \
  -p 3902:3902 \
  -p 3903:3903 \
  -p 4080:4080 \
  -v /path/to/config:/config \
  -v /path/to/data:/data \
  -v /path/to/meta:/meta \
  -v /path/to/tailscale:/var/lib/tailscale \
  -e TS_AUTHKEY="tskey-auth-xxxxx" \
  -e TS_HOSTNAME="garage-node1" \
  -e ADMIN_TOKEN="your-secure-token" \
  -e WEBUI_ENABLED="true" \
  waazaafr/garage-s3-tailscale:latest

The node then appears in your tailnet as garage-node1, and Garage is reachable on its Tailscale IP as well as on the published ports.


⁠Configuration

⁠Environment variables

Required

VariableDescription
ADMIN_TOKENToken for the Admin API (and the web UI)
TS_AUTHKEYTailscale auth key used to join your tailnet
TS_HOSTNAMEName of this node in your tailnet

Optional

VariableDefaultDescription
GATEWAY0.0.0.0Bind address of the S3 API and the Admin API
RPC_SECRETauto-generatedRPC secret shared by all nodes of a cluster (64 hex characters)
REPLICATION_FACTOR1Number of copies of each object
CONSISTENCY_MODEdegradedconsistent, degraded or dangerous
BLOCK_SIZE5Block size, in MB
COMPRESSION_LEVEL2Compression level
TAILSCALE_FORCE_PORTfalsetrue to make Tailscale use a fixed UDP port
TAILSCALE_UDP_PORT25565UDP port used when TAILSCALE_FORCE_PORT=true
WEBUI_ENABLEDfalsetrue to start the web UI on port 4080
META_SNAPSHOTS_ENABLEfalsetrue to enable automatic metadata snapshots
META_SNAPSHOTS_DIR/data/snapshots_metaWhere metadata snapshots are stored
META_SNAPSHOTS_INTERVAL24Interval between metadata snapshots, in hours

💡 For a multi-node cluster, every node must use the same RPC_SECRET: let the first node generate it, then copy it from its /config/garage.toml to the other nodes.

⁠Ports
PortService
9000S3 API
3901RPC (communication between Garage nodes, over Tailscale)
3902S3 web hosting (static websites)
3903Admin API
4080Web UI (only if WEBUI_ENABLED=true)
⁠Volumes
PathContent
/configGarage configuration (garage.toml, including secrets)
/dataObject data — make sure it has enough space
/metaMetadata
/var/lib/tailscaleTailscale state, so the node keeps its identity and IP across restarts
⁠Required container capabilities
OptionWhy
--cap-add=NET_ADMINLets Tailscale create and configure its network interface
--cap-add=SYS_MODULELets Tailscale load the kernel modules it needs
--device=/dev/net/tunGives access to the TUN device used by Tailscale
⁠What happens at startup
  1. Tailscale starts and joins your tailnet with TS_AUTHKEY and TS_HOSTNAME.
  2. The Tailscale IP is read from the tailscale0 interface and used as the RPC address of the node: nothing to configure.
  3. The Garage configuration is prepared:
    • First start (/config/garage.toml does not exist): it is created from the environment variables; unset optional variables use their defaults, and a random RPC_SECRET is generated if none is given.
    • Next starts: the Tailscale IP, GATEWAY and ADMIN_TOKEN are always re-applied; optional variables are updated only if they are explicitly set, everything else (such as RPC_SECRET) is kept.
  4. Garage starts, followed by the web UI if enabled.

⁠Changelog

Garage release notes: git.deuxfleurs.fr/Deuxfleurs/garage/releases⁠

⁠2026-09-08
  • Garage v2.3.0 → v2.4.1.
  • Updated Tailscale and process-compose.
  • Fixed process-compose on arm64.
⁠2026-08-04
  • Added an optional web UI showing Garage information. Enable it with WEBUI_ENABLED=true and publish port 4080.

Tag summary

Content type

Image

Digest

sha256:fdb4b0991…

Size

132.1 MB

Last updated

about 1 month ago

docker pull waazaafr/garage-s3-tailscale