Skip to content

Deploying GarageHQ

Introduction

GarageHQ (commonly called Garage) is a lightweight, self-hosted distributed storage system that provides S3-compatible object storage. Designed for simplicity and resilience, Garage enables you to build your own storage infrastructure that can span multiple locations while remaining easy to operate.

Built in Rust for performance and reliability, Garage is designed to run on commodity hardware and can operate across heterogeneous nodes with varying storage capacities and network conditions. Unlike enterprise storage solutions that require specialized hardware, Garage works on anything from Raspberry Pis to powerful servers.

Key highlights of Garage:

  • S3-Compatible API: Use existing S3 tools and libraries without modification
  • Distributed Architecture: Spread data across multiple nodes for redundancy
  • Geo-Distribution: Design clusters that span data centers or geographic regions
  • Lightweight: Written in Rust with minimal resource requirements
  • Self-Healing: Automatic data repair and rebalancing
  • Simple Operation: No complex cluster management or specialized knowledge required
  • Flexible Topology: Mix nodes with different capacities and performance characteristics
  • Web Interface: Built-in admin panel for cluster management
  • K2V API: Key-value store API for application state (in addition to S3)
  • 100% Open Source: Licensed under AGPL-3.0

This guide walks through deploying Garage on Klutch.sh using Docker, configuring a storage cluster, and using the S3-compatible API for your applications.

Why Deploy GarageHQ on Klutch.sh

Deploying Garage on Klutch.sh provides several advantages for your object storage needs:

Simplified Deployment: Klutch.sh automatically detects your Dockerfile and builds Garage without complex orchestration. Push to GitHub, and your storage node deploys automatically.

Persistent Storage: Attach persistent volumes for your object data and metadata. Your files survive container restarts and redeployments without data loss.

HTTPS by Default: Klutch.sh provides automatic SSL certificates, ensuring secure access to your S3 API endpoint from anywhere.

GitHub Integration: Connect your configuration repository directly from GitHub. Updates to your configuration trigger automatic redeployments.

Scalable Resources: Allocate CPU, memory, and storage based on your needs. Start small and scale up as your storage requirements grow.

Environment Variable Management: Securely store sensitive configuration like RPC secrets and access keys through Klutch.sh’s environment variable system.

Custom Domains: Assign a custom domain to your Garage instance for S3 endpoint URLs that match your infrastructure.

Always-On Availability: Your storage service remains accessible 24/7 without managing your own hardware.

Prerequisites

Before deploying Garage on Klutch.sh, ensure you have:

  • A Klutch.sh account
  • A GitHub account with a repository for your Garage configuration
  • Basic familiarity with Docker and containerization concepts
  • Understanding of S3 object storage concepts
  • (Optional) A custom domain for your S3 endpoint

Understanding Garage Architecture

Garage is built on a distributed architecture:

Nodes: Each Garage instance is a node in the cluster. Nodes communicate via an RPC protocol for coordination and data transfer.

Zones: Nodes are organized into zones (typically representing failure domains like data centers). Garage distributes data across zones for resilience.

Replication: Data is replicated across multiple nodes based on your replication factor. The default is 3 copies across different zones.

Metadata: Garage uses a distributed metadata store for bucket and object information. Metadata is also replicated for durability.

S3 Gateway: Each node can serve S3 API requests, routing reads and writes to the appropriate data locations.

Web Gateway: Serves static websites directly from buckets, similar to AWS S3 static hosting.

Preparing Your Repository

To deploy Garage on Klutch.sh, create a GitHub repository containing your Dockerfile and configuration.

Repository Structure

garage-deploy/
├── Dockerfile
├── garage.toml
├── README.md
└── .dockerignore

Creating the Dockerfile

Create a Dockerfile in the root of your repository:

FROM dxflrs/garage:v0.9
# Copy configuration file
COPY garage.toml /etc/garage.toml
# Create data directories
RUN mkdir -p /var/lib/garage/data /var/lib/garage/meta
# Expose ports
# S3 API
EXPOSE 3900
# Web gateway
EXPOSE 3902
# Admin API
EXPOSE 3903
# Run Garage with the configuration file
CMD ["garage", "-c", "/etc/garage.toml", "server"]

Advanced Dockerfile with Health Checks

For production deployments:

FROM dxflrs/garage:v0.9
# Copy configuration file
COPY garage.toml /etc/garage.toml
# Create data directories
RUN mkdir -p /var/lib/garage/data /var/lib/garage/meta
# Set environment variables
ENV GARAGE_CONFIG_FILE=/etc/garage.toml
ENV RUST_LOG=garage=info
# Health check for S3 API
HEALTHCHECK --interval=30s --timeout=10s --start-period=30s --retries=3 \
CMD wget --no-verbose --tries=1 --spider http://localhost:3903/health || exit 1
# Expose ports
EXPOSE 3900 3902 3903
CMD ["garage", "-c", "/etc/garage.toml", "server"]

Creating the Configuration File

Create a garage.toml file:

# Garage configuration file
# Metadata directory
metadata_dir = "/var/lib/garage/meta"
# Data directory
data_dir = "/var/lib/garage/data"
# Size of data blocks (default 1MB)
block_size = 1048576
# Replication mode
# 1 = none (single copy)
# 2 = 2 copies
# 3 = 3 copies (recommended for production)
replication_mode = "1"
# Compression (none, lz4, zstd)
compression_level = "none"
# RPC configuration
[rpc]
# RPC secret key (32 bytes hex-encoded)
# Generate with: openssl rand -hex 32
rpc_secret = "${RPC_SECRET}"
# RPC bind address
rpc_bind_addr = "[::]:3901"
# Public RPC address (for other nodes to connect)
rpc_public_addr = "${RPC_PUBLIC_ADDR}"
# Bootstrap peers (for multi-node clusters)
# bootstrap_peers = []
# S3 API configuration
[s3_api]
s3_region = "garage"
api_bind_addr = "[::]:3900"
root_domain = "${S3_ROOT_DOMAIN}"
# S3 Web gateway configuration
[s3_web]
bind_addr = "[::]:3902"
root_domain = "${WEB_ROOT_DOMAIN}"
index = "index.html"
# Admin API configuration
[admin]
api_bind_addr = "[::]:3903"
admin_token = "${ADMIN_TOKEN}"
metrics_token = "${METRICS_TOKEN}"

Creating the .dockerignore File

Create a .dockerignore file:

.git
.github
*.md
README.md
LICENSE
.gitignore
*.log
.DS_Store
.env
.env.local

Environment Variables Reference

VariableRequiredDefaultDescription
RPC_SECRETYes-32-byte hex-encoded secret for RPC authentication
RPC_PUBLIC_ADDRYes-Public address for RPC (e.g., your-app.klutch.sh:3901)
S3_ROOT_DOMAINNo-Root domain for virtual-hosted bucket URLs
WEB_ROOT_DOMAINNo-Root domain for web gateway
ADMIN_TOKENYes-Token for admin API authentication
METRICS_TOKENNo-Token for metrics endpoint

Deploying GarageHQ on Klutch.sh

Once your repository is prepared, follow these steps to deploy Garage:

    Generate Security Secrets

    Before deployment, generate the required secrets:

    Terminal window
    # Generate RPC secret
    openssl rand -hex 32
    # Generate admin token
    openssl rand -hex 32
    # Generate metrics token (optional)
    openssl rand -hex 32

    Save these secrets securely for the environment variables configuration.

    Push Your Repository to GitHub

    Initialize your repository and push to GitHub:

    Terminal window
    git init
    git add Dockerfile garage.toml .dockerignore README.md
    git commit -m "Initial Garage deployment configuration"
    git remote add origin https://github.com/yourusername/garage-deploy.git
    git push -u origin main

    Create a New Project on Klutch.sh

    Navigate to the Klutch.sh dashboard and create a new project. Give it a descriptive name like “garage” or “storage”.

    Create a New App

    Within your project, create a new app. Connect your GitHub account if you haven’t already, then select the repository containing your Garage Dockerfile.

    Configure HTTP Traffic

    Garage exposes multiple ports. Configure the primary S3 API port:

    • Select HTTP as the traffic type
    • Set the internal port to 3900 (S3 API port)

    Note: For the admin API (3903) and web gateway (3902), you may need additional configuration or separate deployments.

    Set Environment Variables

    In the environment variables section, add the following:

    VariableValue
    RPC_SECRETYour generated 32-byte hex secret
    RPC_PUBLIC_ADDRyour-app-name.klutch.sh:3901
    ADMIN_TOKENYour generated admin token
    METRICS_TOKENYour generated metrics token
    S3_ROOT_DOMAIN.s3.your-app-name.klutch.sh (optional)

    Attach Persistent Volumes

    Persistent storage is essential for Garage. Add the following volumes:

    Mount PathRecommended SizePurpose
    /var/lib/garage/data100+ GBObject data storage
    /var/lib/garage/meta10 GBMetadata storage

    Deploy Your Application

    Click Deploy to start the build process. Klutch.sh will:

    • Detect your Dockerfile automatically
    • Build the container image
    • Attach the persistent volumes
    • Start the Garage container
    • Provision an HTTPS certificate

    Configure the Cluster

    After deployment, configure your Garage node using the admin CLI:

    Terminal window
    # Connect to your Garage instance
    garage -c /etc/garage.toml status
    # Set the node's zone and capacity
    garage layout assign <node-id> --zone dc1 --capacity 100G
    # Apply the layout
    garage layout apply --version 1

    Access Garage

    Once deployment completes, access your Garage instance:

    • S3 API: https://your-app-name.klutch.sh (port 3900)
    • Admin API: Port 3903 (if configured)

Initial Setup and Configuration

Node Configuration

After deploying, configure your Garage node:

  1. Get Node ID: Check the container logs for the node ID
  2. Assign Layout: Set the zone and capacity for your node
  3. Apply Layout: Activate the node configuration

Creating Access Keys

Create S3 access keys for your applications:

Terminal window
# Create a new access key
garage key create my-app-key
# List access keys
garage key list
# Get key details
garage key info my-app-key

Creating Buckets

Create buckets for your data:

Terminal window
# Create a bucket
garage bucket create my-bucket
# Allow a key to access the bucket
garage bucket allow my-bucket --read --write --key my-app-key
# List buckets
garage bucket list

Bucket Permissions

Configure bucket access:

PermissionDescription
--readRead objects from bucket
--writeWrite objects to bucket
--ownerFull bucket management

Using the S3 API

AWS CLI Configuration

Configure the AWS CLI to use your Garage instance:

Terminal window
aws configure --profile garage
# AWS Access Key ID: (your access key id)
# AWS Secret Access Key: (your secret key)
# Default region name: garage
# Default output format: json

Create a profile configuration in ~/.aws/config:

[profile garage]
endpoint_url = https://your-app-name.klutch.sh
region = garage

Basic S3 Operations

Perform common S3 operations:

Terminal window
# List buckets
aws s3 ls --profile garage
# Upload a file
aws s3 cp myfile.txt s3://my-bucket/ --profile garage
# Download a file
aws s3 cp s3://my-bucket/myfile.txt . --profile garage
# List objects
aws s3 ls s3://my-bucket/ --profile garage
# Delete an object
aws s3 rm s3://my-bucket/myfile.txt --profile garage

Using S3 SDKs

Use Garage with any S3-compatible SDK:

Python (boto3):

import boto3
s3 = boto3.client(
's3',
endpoint_url='https://your-app-name.klutch.sh',
aws_access_key_id='YOUR_ACCESS_KEY',
aws_secret_access_key='YOUR_SECRET_KEY',
region_name='garage'
)
# Upload file
s3.upload_file('local-file.txt', 'my-bucket', 'remote-file.txt')
# Download file
s3.download_file('my-bucket', 'remote-file.txt', 'local-file.txt')

JavaScript (AWS SDK):

const { S3Client, PutObjectCommand } = require('@aws-sdk/client-s3');
const s3 = new S3Client({
endpoint: 'https://your-app-name.klutch.sh',
region: 'garage',
credentials: {
accessKeyId: 'YOUR_ACCESS_KEY',
secretAccessKey: 'YOUR_SECRET_KEY'
},
forcePathStyle: true
});
// Upload file
await s3.send(new PutObjectCommand({
Bucket: 'my-bucket',
Key: 'file.txt',
Body: 'Hello, Garage!'
}));

Static Website Hosting

Enabling Web Gateway

Garage can serve static websites from buckets:

  1. Create a bucket for your website
  2. Upload your static files
  3. Configure the bucket for website hosting
Terminal window
# Create website bucket
garage bucket create my-website
# Allow the web gateway to access the bucket
garage bucket website my-website --allow
# Upload files
aws s3 sync ./website s3://my-website/ --profile garage

Custom Index and Error Pages

Configure custom pages in garage.toml:

[s3_web]
bind_addr = "[::]:3902"
root_domain = ".web.example.com"
index = "index.html"

Multi-Node Clusters

Adding Nodes

For production, run multiple Garage nodes:

  1. Deploy additional Garage instances
  2. Configure each with the same rpc_secret
  3. Add bootstrap peers to connect nodes
  4. Distribute nodes across zones

Example Multi-Node Configuration

[rpc]
rpc_secret = "shared-secret-across-all-nodes"
bootstrap_peers = [
"node1.example.com:3901",
"node2.example.com:3901"
]

Zone Configuration

Organize nodes into zones for fault tolerance:

Terminal window
# Assign nodes to different zones
garage layout assign node1-id --zone zone1 --capacity 100G
garage layout assign node2-id --zone zone2 --capacity 100G
garage layout assign node3-id --zone zone3 --capacity 100G
# Apply the layout
garage layout apply --version 1

Monitoring and Administration

Admin API

Use the admin API for monitoring:

Terminal window
# Get cluster status
curl -H "Authorization: Bearer $ADMIN_TOKEN" \
https://your-app-name.klutch.sh:3903/v0/status
# Get node health
curl -H "Authorization: Bearer $ADMIN_TOKEN" \
https://your-app-name.klutch.sh:3903/health

Metrics

Garage exposes Prometheus-compatible metrics:

Terminal window
curl -H "Authorization: Bearer $METRICS_TOKEN" \
https://your-app-name.klutch.sh:3903/metrics

Key metrics to monitor:

MetricDescription
garage_data_bytesTotal stored data
garage_meta_bytesMetadata storage
garage_s3_requests_totalS3 API requests
garage_rpc_request_durationRPC latency

Logs

Access Garage logs through:

  1. Klutch.sh Dashboard: View runtime logs
  2. RUST_LOG: Configure log levels
  3. Container logs: Standard output logging

Production Best Practices

Security Recommendations

  • Strong Secrets: Use cryptographically secure random strings for all secrets
  • HTTPS Only: Always access Garage via HTTPS
  • Access Key Rotation: Regularly rotate access keys
  • Minimal Permissions: Grant only required permissions to keys
  • Network Security: Restrict RPC port access between trusted nodes

Performance Optimization

  • Block Size: Tune block size for your workload (smaller for many small files, larger for big files)
  • Compression: Enable compression for compressible data
  • Storage Sizing: Allocate sufficient storage for data and metadata
  • Memory: Allocate memory based on metadata size

Backup Strategy

Protect your data:

  1. Replication: Use replication mode 3 for production
  2. Cross-Zone: Distribute across multiple zones
  3. Key Backup: Securely store access keys
  4. Metadata Backup: Regular metadata snapshots

Troubleshooting Common Issues

Node Won’t Join Cluster

Symptoms: Node starts but doesn’t connect to other nodes.

Solutions:

  • Verify rpc_secret matches across all nodes
  • Check network connectivity to bootstrap peers
  • Ensure RPC port (3901) is accessible
  • Review logs for connection errors

S3 Operations Failing

Symptoms: S3 requests return errors.

Solutions:

  • Verify access key permissions
  • Check bucket exists and is accessible
  • Ensure endpoint URL is correct
  • Review Garage logs for specific errors

Layout Not Applying

Symptoms: Layout changes don’t take effect.

Solutions:

  • Increment layout version number
  • Ensure all nodes are reachable
  • Check for layout conflicts
  • Wait for layout propagation

Storage Full

Symptoms: Uploads fail, storage errors in logs.

Solutions:

  • Check available disk space
  • Expand persistent volume
  • Enable garbage collection
  • Review data retention policies

Updating Garage

To update to a newer version:

  1. Review Release Notes: Check Garage changelog
  2. Backup Data: Ensure data is replicated or backed up
  3. Update Dockerfile: Change the image tag
  4. Push Changes: Commit and push to trigger redeployment
  5. Verify: Test S3 operations after update

Additional Resources

Conclusion

Deploying Garage on Klutch.sh gives you a powerful, self-hosted S3-compatible object storage system with automatic builds, persistent storage, and secure HTTPS access. The combination of Garage’s lightweight distributed architecture and Klutch.sh’s deployment simplicity means you can focus on building applications rather than managing storage infrastructure.

With support for S3 API compatibility, geo-distribution, and automatic replication, Garage on Klutch.sh provides enterprise-grade object storage that runs on commodity infrastructure. Whether you’re storing application data, hosting static websites, or building a multi-region storage cluster, Garage delivers the reliability you need with complete control over your data.