| ← Back to Documentation Index | Main README |
This guide covers day-2 operations for managing your Garage cluster after installation.
Basic Status Check:
ssh user@node1 "docker exec garage /garage status"
Expected Output:
==== HEALTHY NODES ====
ID Hostname Address Tags Zone Capacity
abc123... node1.local 192.168.1.100 - dc1 100 GB
def456... node2.local 192.168.1.101 - dc1 100 GB
==== LAYOUT ====
Version: 1
Replicas: 2
ID Tags Zone Capacity
abc123... - dc1 100 GB (100%)
def456... - dc1 100 GB (100%)
Key Health Indicators:
is_up: truelast_seen_secs_ago < 10 secondsGet Node ID:
docker exec garage /garage node id
View All Nodes:
docker exec garage /garage status | grep -A 100 "HEALTHY NODES"
Check Layout:
docker exec garage /garage layout show
Check Container Status:
docker ps | grep garage
View Container Logs:
# Real-time logs
docker logs -f garage
# Last 100 lines
docker logs --tail 100 garage
# Logs with timestamps
docker logs --timestamps garage
# Logs since specific time
docker logs --since 1h garage
Check Container Resource Usage:
docker stats garage --no-stream
Access Metrics Endpoint:
curl http://node1:3903/metrics
Key Metrics to Monitor:
garage_block_bytes_written_total - Data writtengarage_block_bytes_read_total - Data readgarage_rpc_request_duration_seconds - RPC latencygarage_api_request_duration_seconds - API latencygarage_replication_queue_length - Pending replicationsSet Up Prometheus (optional):
# prometheus.yml
scrape_configs:
- job_name: 'garage'
static_configs:
- targets: ['node1:3903', 'node2:3903']
Create a New Key:
docker exec garage /garage key create my-app-key
Output:
Key created successfully!
Access Key ID: GK123456789...
Secret Access Key: abc123def456...
⚠️ Save the Secret Access Key immediately - it won’t be shown again!
docker exec garage /garage key list
docker exec garage /garage key info my-app-key
Create a New Bucket:
docker exec garage /garage bucket create my-bucket
List All Buckets:
docker exec garage /garage bucket list
View Bucket Details:
docker exec garage /garage bucket info my-bucket
Allow Key to Access Bucket:
# Read and write permissions
docker exec garage /garage bucket allow my-bucket \
--read --write --key my-app-key
# Read-only permissions
docker exec garage /garage bucket allow my-bucket \
--read --key readonly-key
# Owner permissions (create/delete bucket)
docker exec garage /garage bucket allow my-bucket \
--read --write --owner --key admin-key
Deny Permissions:
docker exec garage /garage bucket deny my-bucket --key my-app-key
Delete a Bucket (must be empty):
docker exec garage /garage bucket delete my-bucket
Delete a Key:
docker exec garage /garage key delete my-app-key
List All Buckets:
aws s3 ls --endpoint-url http://node1:3900
List Bucket Contents:
aws s3 ls s3://my-bucket/ --endpoint-url http://node1:3900
Upload a File:
aws s3 cp file.txt s3://my-bucket/ --endpoint-url http://node1:3900
Download a File:
aws s3 cp s3://my-bucket/file.txt ./ --endpoint-url http://node1:3900
Sync a Directory:
# Upload directory
aws s3 sync ./local-dir s3://my-bucket/remote-dir/ \
--endpoint-url http://node1:3900
# Download directory
aws s3 sync s3://my-bucket/remote-dir/ ./local-dir \
--endpoint-url http://node1:3900
Delete a File:
aws s3 rm s3://my-bucket/file.txt --endpoint-url http://node1:3900
Delete All Files in Bucket:
aws s3 rm s3://my-bucket/ --recursive --endpoint-url http://node1:3900
View Block Statistics:
docker exec garage /garage stats
Check Replication Status:
docker logs garage 2>&1 | grep -i replication
Stop Garage (on one node):
ssh user@node1
cd ~/garage
docker compose stop
Start Garage:
docker compose start
Restart Garage:
docker compose restart
Full Restart (stop, remove, recreate):
docker compose down
docker compose up -d
1. Update docker-compose.yml:
ssh user@node1
cd ~/garage
nano docker-compose.yml
Change:
image: dxflrs/garage:v2.1.0
To:
image: dxflrs/garage:v2.2.0 # New version
2. Pull New Image:
docker compose pull
3. Recreate Container:
docker compose up -d
4. Verify Health:
docker exec garage /garage status
5. Repeat for Node 2
⚠️ Upgrading Notes:
Inspect Container:
docker inspect garage
Check Container Filesystem:
docker exec garage ls -la /var/lib/garage/
Check Configuration:
docker exec garage cat /etc/garage.toml
1. Edit Configuration:
ssh user@node1
cd ~/garage
nano garage.toml
2. Restart Container (config is mounted):
docker compose restart
3. Verify Changes:
docker logs garage --tail 50
Change Capacity:
# Update layout with new capacity
docker exec garage /garage layout assign -z dc1 -c 200G <node-id>
docker exec garage /garage layout apply --version <current+1>
Add Bootstrap Peers (if adding nodes later):
# In garage.toml
[rpc]
bootstrap_peers = [
"abc123@node1.local:3901",
"def456@node2.local:3901",
"ghi789@node3.local:3901"
]
Change Admin Token:
# In garage.toml
[admin]
admin_token = "new-token-here"
Then restart container.
Edit Compose File:
cd ~/garage
nano docker-compose.yml
Common Changes:
Apply Changes:
docker compose up -d
What to Backup:
~/garage/garage.toml~/garage/docker-compose.yml.garage-installer-state.json (if preserved)~/garage/meta/~/garage/data/⚠️ Important: With a 2-node cluster and replication factor 2, losing one node means you still have all data on the remaining node.
Manual Backup:
# From local machine
ssh user@node1 "cd ~/garage && tar czf - garage.toml docker-compose.yml" > node1-config-$(date +%Y%m%d).tar.gz
# Or on the node
ssh user@node1
cd ~/garage
tar czf ~/backup-config-$(date +%Y%m%d).tar.gz garage.toml docker-compose.yml
Stop Container First (for consistency):
docker compose stop
Backup Metadata Directory:
# On the node
cd ~/garage
tar czf ~/backup-meta-$(date +%Y%m%d).tar.gz meta/
# Or remotely via SSH
ssh user@node1 "cd ~/garage && docker compose stop && tar czf - meta/" > node1-meta-$(date +%Y%m%d).tar.gz
Restart Container:
docker compose start
⚠️ Warning: This can be very large!
# On the node (with container stopped)
cd ~/garage
tar czf ~/backup-data-$(date +%Y%m%d).tar.gz data/
Better Alternative: Use S3 sync to backup to another location:
# Backup to another S3 service
aws s3 sync s3://my-bucket/ s3://backup-bucket/ \
--source-region garage \
--endpoint-url http://node1:3900 \
# destination endpoint for backup location
1. Stop Container:
cd ~/garage
docker compose stop
2. Restore Configuration:
tar xzf backup-config-20251116.tar.gz
3. Restore Metadata:
# Remove current metadata
rm -rf meta/*
# Extract backup
tar xzf backup-meta-20251116.tar.gz
4. Restore Data (if backed up):
rm -rf data/*
tar xzf backup-data-20251116.tar.gz
5. Restart Container:
docker compose up -d
6. Verify Health:
docker exec garage /garage status
Example Backup Script:
#!/bin/bash
# backup-garage.sh
BACKUP_DIR="/backups/garage"
DATE=$(date +%Y%m%d-%H%M%S)
NODE="node1"
mkdir -p "$BACKUP_DIR"
echo "Stopping Garage..."
ssh user@$NODE "cd ~/garage && docker compose stop"
echo "Backing up configuration..."
ssh user@$NODE "cd ~/garage && tar czf - garage.toml docker-compose.yml" > "$BACKUP_DIR/config-$DATE.tar.gz"
echo "Backing up metadata..."
ssh user@$NODE "cd ~/garage && tar czf - meta/" > "$BACKUP_DIR/meta-$DATE.tar.gz"
echo "Starting Garage..."
ssh user@$NODE "cd ~/garage && docker compose start"
echo "Backup complete: $BACKUP_DIR"
Schedule with Cron:
# Backup daily at 2 AM
0 2 * * * /path/to/backup-garage.sh >> /var/log/garage-backup.log 2>&1
Check Container Status:
docker ps -a | grep garage
If Exited - View logs:
docker logs garage
Common Issues:
Restart Container:
docker compose restart
Symptoms:
garage statuslast_seen_secs_ago valuesCheck RPC Connectivity:
# From node1 to node2
ssh user@node1 "nc -zv node2 3901"
# Or test with bash TCP
ssh user@node1 "timeout 5 bash -c 'cat < /dev/null > /dev/tcp/node2/3901' && echo 'Connected' || echo 'Failed'"
Check Firewall:
# Allow RPC port
sudo ufw allow from 192.168.1.100 to any port 3901
sudo ufw allow from 192.168.1.101 to any port 3901
Verify RPC Secret Matches:
ssh user@node1 "docker exec garage grep rpc_secret /etc/garage.toml"
ssh user@node2 "docker exec garage grep rpc_secret /etc/garage.toml"
View Current Layout:
docker exec garage /garage layout show
Revert Layout (if staging exists):
docker exec garage /garage layout revert
Force Layout Application (advanced):
# Increment version manually
docker exec garage /garage layout apply --version <current+1>
Run Repair:
# Repair all data blocks
docker exec garage /garage repair -a
# Repair specific bucket
docker exec garage /garage repair --bucket my-bucket
Check for Corruption:
docker exec garage /garage verify
Check Disk Usage:
df -h | grep garage
du -sh ~/garage/data
du -sh ~/garage/meta
Clean Up Docker:
# Remove unused containers, images, volumes
docker system prune -a --volumes
Increase Capacity (if possible):
For more troubleshooting, see the Troubleshooting Guide.
⚠️ Current Limitation: The installer currently only supports 2-node clusters.
Manual Process (requires Garage knowledge):
Planned: See FUTURES.md for roadmap on 3+ node support.
⚠️ Warning: Cannot be changed after initial setup without rebuilding cluster.
For 2-node cluster, replication factor must be 2 or less. Changing requires:
Increase Worker Threads (in garage.toml):
[rpc]
rpc_worker_threads = 4 # Default is 2
Adjust Block Size (for large files):
block_size = 2097152 # 2MB blocks instead of default 1MB
Tune Metadata Engine (advanced):
metadata_fsync = false # Faster but less safe
Restart Required after configuration changes.
Current Setup (2-node cluster):
For Production HA:
1. Set Up Alerts:
2. Regular Health Checks:
# Daily health check script
#!/bin/bash
STATUS=$(ssh user@node1 "docker exec garage /garage status" 2>&1)
if echo "$STATUS" | grep -q "ERROR"; then
echo "ALERT: Garage cluster unhealthy" | mail -s "Garage Alert" admin@example.com
fi
3. Log Aggregation:
4. Metrics Dashboard:
docker exec garage /garage status # Cluster status
docker logs --tail 50 garage # Recent logs
docker stats garage --no-stream # Resource usage
curl http://node1:3903/metrics # Prometheus metrics
docker compose stop # Stop
docker compose start # Start
docker compose restart # Restart
docker compose down && docker compose up -d # Full restart
docker exec garage /garage key create KEY_NAME
docker exec garage /garage key list
docker exec garage /garage bucket create BUCKET_NAME
docker exec garage /garage bucket list
docker exec garage /garage bucket allow BUCKET --read --write --key KEY
aws s3 ls --endpoint-url http://node1:3900
aws s3 cp file.txt s3://bucket/ --endpoint-url http://node1:3900
aws s3 sync local/ s3://bucket/remote/ --endpoint-url http://node1:3900
| ← Back to Documentation Index | Main README |