Stop Wrestling with S3 CLIs! garage-webui Makes Object Storage Effortless
What if managing petabytes of distributed object storage was as simple as checking your email?
Here's the dirty secret nobody tells you about self-hosted infrastructure: the command line is a productivity killer. You've spun up Garage—brilliant, S3-compatible, distributed object storage that puts AWS to shame on privacy and cost. But now you're trapped in a terminal maze of garage subcommands, squinting at JSON outputs, and praying you don't accidentally nuke a bucket policy. Every bucket creation feels like defusing a bomb. Every access key rotation requires cross-referencing three different docs. And don't even get me started on cluster health monitoring—because you won't see problems coming until your nodes are already on fire.
Sound familiar? You're not alone. Thousands of developers adopt Garage for its technical excellence, then silently suffer through operational friction that kills momentum. But what if I told you there's a single binary that transforms this pain into point-and-click simplicity?
Enter garage-webui—the open-source web interface that makes Garage object storage management actually enjoyable. Created by Khairul Hidayat, this tool is spreading through DevOps circles like wildfire for one simple reason: it respects your time. No more memorizing CLI flags. No more parsing cryptic API responses. Just a clean, modern dashboard where clusters, buckets, and access keys bow to your cursor.
Ready to reclaim your sanity? Let's dive deep into why garage-webui is becoming the secret weapon for developers who refuse to let infrastructure management suck their soul dry.
What is garage-webui?
garage-webui is a lightweight, self-hosted administrative web interface purpose-built for Garage—the increasingly popular open-source, S3-compatible distributed object storage service developed by Deuxfleurs. While Garage itself handles the heavy lifting of data replication, erasure coding, and distributed consensus, garage-webui provides the human-friendly control layer that transforms raw infrastructure into manageable resources.
The project emerged from a genuine pain point: Garage's native administration relies heavily on command-line tools and direct API calls. For infrastructure veterans, this is workable. For teams scaling quickly, or for developers wearing multiple hats, it's friction that compounds. Khairul Hidayat recognized this gap and built garage-webui as a single executable binary that bridges Garage's powerful backend with an intuitive React-based frontend.
What makes garage-webui genuinely exciting right now? Three converging trends:
- The self-hosted renaissance: Post-Snowden, post-ChatGPT-data-scraping-paranoia, organizations are aggressively repatriating data. Garage downloads are spiking, and every new Garage deployment needs management tooling.
- The "platform engineering" mandate: Companies want internal developer platforms with GUIs, not ticket-ops workflows. garage-webui drops perfectly into this paradigm.
- Container-native simplicity: With first-class Docker and Docker Compose support, it integrates seamlessly into existing infrastructure-as-code setups without adding operational complexity.
The project is built on a TypeScript/React frontend with a Go backend—a stack chosen for performance, maintainability, and ease of contribution. It's not trying to be Kubernetes-dashboard-complex; it's deliberately focused on doing one thing spectacularly well: making Garage administration effortless.
Key Features That Actually Matter
Let's cut through feature-list fluff. Here's what garage-webui delivers and why each capability saves you real hours:
Real-Time Garage Health Status
Stop SSH-ing into nodes to check if your cluster's heart is still beating. The dashboard surfaces node health, replication status, and potential issues in a single glance. This isn't vanity metrics—it's early warning radar that prevents 3 AM pages.
Cluster & Layout Management
Garage's distributed nature means nodes join, leave, and rebalance. garage-webui visualizes your cluster topology and lets you manage layout assignments without touching garage layout assign commands. Visual cluster surgery beats textual node lists every single time.
Full Bucket Lifecycle Control
Create buckets, update configurations, inspect metadata, and browse contents—all through a clean interface. The integrated objects/bucket browser means you can verify uploads, debug permissions issues, and spot-check data without configuring separate S3 clients like aws-cli or s3cmd.
Access Key Management
Generate, rotate, and assign S3-compatible access keys with proper scoping. This is where garage-webui shines for security hygiene: key rotation becomes a 30-second task instead of a scripted ordeal. No more stale credentials lurking in environment variables for months.
Zero-Config Authentication Option
The optional AUTH_USER_PASS environment variable with bcrypt hashing means you can front your admin panel with basic auth without deploying a separate reverse proxy layer. Perfect for homelabs and rapid prototypes where you need protection without complexity.
Configuration Inheritance
Rather than forcing duplicate configuration, garage-webui reads your existing garage.toml and extracts rpc_public_addr, admin.admin_token, and related values automatically. This design choice reveals mature engineering: the tool respects your existing setup instead of inventing parallel config systems.
Use Cases Where garage-webui Absolutely Dominates
1. Homelab Storage Sovereignty
You're running Garage on a Proxmox cluster or a few Raspberry Pis. You want S3-compatible storage for Nextcloud backups, Plex media, or personal photo archives. But you don't want to maintain mental models of Garage's CLI for a system you touch twice a month. garage-webui gives you set-and-forget management with occasional GUI check-ins.
2. Startup MVP Infrastructure
Your seed-stage company needs cost-effective object storage without AWS egress fee surprises. Garage on Hetzner or OVH plus garage-webui means your non-technical co-founder can create buckets for new features without pinging you on Slack. Democratized infrastructure access without democratized disaster potential.
3. CI/CD Artifact Storage
Garage stores build artifacts, container layers, and release binaries. garage-webui lets you debug failed uploads, verify retention policies, and rotate CI-specific access keys when employees depart—all without breaking your deployment flow to open terminals.
4. Multi-Tenant Platform Engineering
You're building an internal platform where teams request S3 buckets. garage-webui becomes your operator's cockpit: provision resources, audit access patterns, and present cluster health to stakeholders who want dashboards, not log streams. The visual browser proves invaluable when teams claim "our data isn't there"—you verify in seconds.
5. Edge/Offline Deployments
Garage's eventual consistency model works brilliantly in disconnected environments. garage-webui running locally lets field engineers manage storage without internet-dependent cloud consoles. Think research vessels, remote mining operations, or military edge nodes.
Step-by-Step Installation & Setup Guide
Method 1: Docker Compose (Recommended)
This approach integrates garage-webui alongside your existing Garage deployment. Create or extend your docker-compose.yml:
services:
garage:
image: dxflrs/garage:v2.0.0
container_name: garage
volumes:
- ./garage.toml:/etc/garage.toml
- ./meta:/var/lib/garage/meta
- ./data:/var/lib/garage/data
restart: unless-stopped
ports:
- 3900:3900 # S3 API endpoint
- 3901:3901 # RPC communication
- 3902:3902 # S3 web gateway
- 3903:3903 # Admin API (CRITICAL for webui)
webui:
image: khairul169/garage-webui:latest
container_name: garage-webui
restart: unless-stopped
volumes:
- ./garage.toml:/etc/garage.toml:ro # Read-only: security best practice
ports:
- 3909:3909
environment:
API_BASE_URL: "http://garage:3903" # Points to Garage admin API
S3_ENDPOINT_URL: "http://garage:3900" # Points to S3 API for browsing
Critical requirement: Ensure your garage.toml has the [admin] section configured with api_bind_addr and admin_token. Without this, garage-webui cannot authenticate to Garage's management API.
Deploy with:
docker compose up -d
Access the interface at http://your-server-ip:3909.
Method 2: Standalone Docker
For quick testing or when Garage runs elsewhere:
docker run -p 3909:3909 \
-v ./garage.toml:/etc/garage.toml:ro \
--restart unless-stopped \
--name garage-webui \
khairul169/garage-webui:latest
Method 3: Binary Installation (Systemd Production Setup)
When Docker overhead is unacceptable or you're running on constrained hardware:
# Download latest release (check https://github.com/khairul169/garage-webui/releases for newer versions)
wget -O garage-webui https://github.com/khairul169/garage-webui/releases/download/1.1.0/garage-webui-v1.1.0-linux-amd64
# Make executable and install system-wide
chmod +x garage-webui
sudo cp garage-webui /usr/local/bin
# Verify binary works
CONFIG_PATH=./garage.toml garage-webui --help
Create a systemd service for automatic startup and crash recovery:
sudo nano /etc/systemd/system/garage-webui.service
Paste this service definition:
[Unit]
Description=Garage Web UI
After=network.target
[Service]
Environment="PORT=3919" # Custom port to avoid conflicts
Environment="CONFIG_PATH=/etc/garage.toml" # System config location
ExecStart=/usr/local/bin/garage-webui
Restart=always # Auto-recover from crashes
RestartSec=5
[Install]
WantedBy=default.target
Activate the service:
sudo systemctl daemon-reload
sudo systemctl enable --now garage-webui
sudo systemctl status garage-webui # Verify healthy startup
Essential Configuration Checklist
Your garage.toml must include these sections for garage-webui functionality:
[admin]
api_bind_addr = "[::]:3903"
admin_token = "YOUR_ADMIN_TOKEN_HERE" # Treat as root password
metrics_token = "YOUR_METRICS_TOKEN_HERE"
The rpc_public_addr value is also required for cluster operations:
rpc_public_addr = "localhost:3901" # Must be resolvable by webui
REAL Code Examples from the Repository
Let's examine actual implementation patterns from the garage-webui codebase and documentation, with detailed explanations of what makes each configuration work.
Example 1: Production Docker Compose with Authentication
This is the complete reference deployment from the repository, enhanced with security hardening:
services:
garage:
image: dxflrs/garage:v2.0.0
container_name: garage
volumes:
- ./garage.toml:/etc/garage.toml
- ./meta:/var/lib/garage/meta # Persistent metadata
- ./data:/var/lib/garage/data # Persistent object data
restart: unless-stopped
ports:
- 3900:3900 # S3 API: where applications connect
- 3901:3901 # Internal RPC: inter-node communication
- 3902:3902 # S3 web: bucket website hosting
- 3903:3903 # Admin API: webui lifeline
webui:
image: khairul169/garage-webui:latest
container_name: garage-webui
restart: unless-stopped
volumes:
- ./garage.toml:/etc/garage.toml:ro # Read-only mount prevents container from corrupting config
ports:
- 3909:3909
environment:
API_BASE_URL: "http://garage:3903" # Internal Docker DNS resolution
S3_ENDPOINT_URL: "http://garage:3900" # For object browser functionality
AUTH_USER_PASS: "admin:$2y$10$DSTi9o..." # bcrypt-secured access (optional but recommended)
Key insights: The ro (read-only) mount on garage.toml is a defense-in-depth measure—even if the webui container is compromised, the attacker cannot modify Garage's core configuration. The API_BASE_URL uses Docker's internal DNS (garage resolves to the service's container IP), keeping admin traffic off public interfaces. The S3_ENDPOINT_URL enables the integrated object browser to fetch actual object listings and metadata.
Example 2: Complete garage.toml Configuration
This configuration from the README represents a production-ready Garage setup:
metadata_dir = "/var/lib/garage/meta" # Where bucket metadata lives
data_dir = "/var/lib/garage/data" # Where actual objects are stored
db_engine = "sqlite" # Lightweight; use "lmdb" for heavy workloads
metadata_auto_snapshot_interval = "6h" # Automatic backup of metadata state
replication_factor = 3 # Copies per object; tolerate 2 node failures
compression_level = 2 # ZSTD compression; 0=none, 1-9=trade speed/ratio
rpc_bind_addr = "[::]:3901" # Listen on all interfaces, IPv6 compatible
rpc_public_addr = "localhost:3901" # MUST be reachable by webui; use real hostname in production
rpc_secret = "YOUR_RPC_SECRET_HERE" # Shared secret for cluster node authentication
[s3_api]
s3_region = "garage" # Arbitrary region identifier for API compatibility
api_bind_addr = "[::]:3900"
root_domain = ".s3.domain.com" # Virtual-hosted buckets: bucketname.s3.domain.com
[s3_web] # Optional: serve buckets as static websites
bind_addr = "[::]:3902"
root_domain = ".web.domain.com"
index = "index.html" # Default file for directory requests
[admin] # REQUIRED for garage-webui functionality
api_bind_addr = "[::]:3903"
admin_token = "YOUR_ADMIN_TOKEN_HERE" # Generate with: openssl rand -hex 32
metrics_token = "YOUR_METRICS_TOKEN_HERE" # For Prometheus scraping, if needed
Critical understanding: The rpc_public_addr is the most commonly misconfigured value. In Docker contexts, this must be resolvable from the webui container. Using localhost works for single-node testing but fails in distributed setups—use actual hostnames or IP addresses. The admin_token is your root credential; rotate it immediately if exposed.
Example 3: Generating Authentication Credentials
The repository provides this exact pattern for securing your dashboard:
# Generate bcrypt hash of your password
# -n: don't print newline after output
# -b: use password from command line (batch mode)
# -B: force bcrypt encryption
# -C 10: cost factor 10 (adjust for security/performance balance)
htpasswd -nbBC 10 "YOUR_USERNAME" "YOUR_PASSWORD"
Sample output:
admin:$2y$10$DSTi9o9L.KjaAyN6I8wO3O0U1kXqGjKpRtWqZrStUvWxYzAbCdEfGh
Integration into docker-compose.yml:
webui:
....
environment:
AUTH_USER_PASS: "admin:$2y$10$DSTi9o..."
Security note: The htpasswd utility comes from apache2-utils (Debian/Ubuntu) or httpd-tools (RHEL/CentOS). Cost factor 10 requires ~100ms to verify—tune higher for production, lower if you observe login latency issues. Never commit unhashed passwords to version control; generate hashes in CI/CD or locally.
Example 4: Environment Variable Override Pattern
When garage.toml parsing fails or you need runtime flexibility:
# Override auto-detected values with explicit environment variables
export API_BASE_URL="https://garage-admin.internal:3903" # HTTPS in production!
export API_ADMIN_KEY="your-admin-token-here" # Direct token injection
export S3_REGION="us-east-1" # Override region for compatibility
export S3_ENDPOINT_URL="https://s3.internal:3900" # HTTPS S3 endpoint
export BASE_PATH="/storage-admin" # Serve under subpath for reverse proxy
# Then launch
garage-webui
When to use overrides: Multi-environment deployments where garage.toml differs per stage; emergency recovery when config parsing breaks; or when running garage-webui on a separate network segment from Garage itself.
Advanced Usage & Best Practices
Reverse Proxy SSL Termination
Never expose garage-webui directly to the internet. Use nginx, Caddy, or Traefik:
server {
listen 443 ssl;
server_name storage.example.com;
location / {
proxy_pass http://localhost:3909;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
Backup Your garage.toml Before Major Changes
The webui reads configuration but doesn't validate your edits to the source file. Version control your garage.toml with Git for rollback capability.
Monitor Webui Logs for API Deprecations
Garage evolves rapidly. Watch for warnings about deprecated admin API endpoints—these signal needed garage-webui upgrades.
Use Separate Admin Tokens Per Environment
Don't share production admin tokens with staging. The environment variable override (API_ADMIN_KEY) makes this trivial to implement.
Resource Limits in Docker
Prevent memory exhaustion on shared hosts:
webui:
deploy:
resources:
limits:
memory: 256M
cpus: '0.5'
Comparison with Alternatives
| Capability | garage-webui | AWS S3 Console | MinIO Console | Native Garage CLI |
|---|---|---|---|---|
| Self-hosted | ✅ Yes | ❌ Cloud-only | ✅ Yes | ✅ Yes |
| Zero cloud cost | ✅ Yes | ❌ Usage fees | ✅ Yes | ✅ Yes |
| Garage-native | ✅ Purpose-built | ❌ N/A | ❌ MinIO-only | ✅ Native |
| Visual cluster mgmt | ✅ Full | N/A | ⚠️ Limited | ❌ CLI only |
| Integrated object browser | ✅ Built-in | ✅ Yes | ✅ Yes | ❌ Separate tools |
| Single binary deploy | ✅ ~20MB | ❌ N/A | ❌ Larger footprint | ⚠️ Garage itself |
| No vendor lock-in | ✅ Open source | ❌ AWS captive | ⚠️ MinIO ecosystem | ✅ Open source |
| Offline capable | ✅ Yes | ❌ No | ✅ Yes | ✅ Yes |
Verdict: garage-webui fills a unique niche—Garage-specific, lightweight, and deliberately focused. MinIO Console is excellent but couples you to MinIO's architecture. AWS S3 Console requires... AWS. The native Garage CLI remains essential for automation, but garage-webui eliminates it for daily operations.
FAQ: Developer Concerns Answered
Is garage-webui officially part of Garage?
No—it's a community project by Khairul Hidayat. However, it uses Garage's public admin API and tracks official releases closely. Many Garage users treat it as de facto standard tooling.
Can garage-webui manage multiple Garage clusters?
Not simultaneously in one instance. Deploy separate garage-webui containers per cluster, or use environment variable switching with orchestration tools.
What happens if Garage upgrades break the admin API?
garage-webui may need updates for major Garage versions. Pin your Garage version in Docker Compose (dxflrs/garage:v2.0.0 not latest) and test upgrades in staging.
Is the webui itself a security risk?
Any admin interface expands attack surface. Mitigate: use AUTH_USER_PASS, place behind VPN/reverse proxy, run with read-only config mounts, and monitor access logs.
Can I contribute features or report bugs?
Absolutely. The project welcomes contributions. Issues go here. The TypeScript/React + Go stack is approachable for most full-stack developers.
Does garage-webui support SSO or OAuth?
Currently, only bcrypt AUTH_USER_PASS is built-in. For SSO, front with a reverse proxy handling OIDC (Authelia, Authentik, oauth2-proxy) and disable AUTH_USER_PASS.
What's the performance impact on Garage?
Negligible for typical use. The webui is stateless and caches minimally—all heavy operations hit Garage's API directly. Benchmark if managing 10,000+ buckets.
Conclusion: Your Object Storage Deserves Better
Here's the truth: infrastructure tools should reduce cognitive load, not add to it. Garage gives you world-class distributed object storage without cloud vendor shackles. garage-webui completes that promise by removing the final barrier—operational complexity—between you and your data.
I've watched too many talented developers burn hours on CLI archaeology when they could be shipping features. I've seen teams delay self-hosted storage adoption because "nobody wants to manage another black box." garage-webui demolishes both excuses. It's a single binary, a few lines of YAML, and suddenly your object storage is as approachable as any SaaS dashboard—except you own every byte.
The project is actively maintained, sensibly architected, and solving a real problem with elegant restraint. Whether you're running a homelab NAS alternative, building startup infrastructure, or designing internal platforms, this tool earns its place in your stack.
Stop fighting your tools. Start managing storage like a human.
👉 Get garage-webui on GitHub — star it, deploy it, and reclaim your time.