Gordon
Why Gordon?
You have a $5 VPS. You want to run multiple apps. You don't want Kubernetes.
Gordon is the missing piece that makes container deployment on budget VPS servers as simple as expensive PaaS solutions. One binary, one config file, unlimited apps.
๐ฏ Perfect For
- Solo developers with multiple side projects on one VPS
- Small teams who want Heroku-like simplicity without the cost
- Agencies deploying client apps across VPS servers
- Anyone tired of complex deployment pipelines
๐ How It Works
Build Locally, Deploy Instantly
# 1. Build & test on YOUR machine
docker build -t myapp .
docker run -p 8080:8080 myapp # Works? Great!
# 2. Push to deploy
docker tag myapp registry.yourdomain.com/myapp:latest
docker push registry.yourdomain.com/myapp:latest
# 3. That's it. Gordon deploys it automatically.
No build servers. No CI/CD complexity. If it runs on your machine, it runs in production.
๐ Instant Rollbacks
Something broke? Just change your config:
# Before (in gordon.toml)
"app.yourdomain.com" = "myapp:latest"
# After - instant rollback!
"app.yourdomain.com" = "myapp:v1.2.3"
Save the file. Gordon redeploys the previous version. Problem solved in seconds.
โจ Key Features
๐ Local-First Development
Your machine is the build server. Test locally, push when ready. No waiting for remote builds.
๐ฆ Built-in Docker Registry
Your VPS becomes a private Docker registry. No Docker Hub subscription needed.
๐ Push-to-Deploy Magic
Gordon watches for new images and deploys them instantly to configured domains.
โฎ๏ธ Version Control Built-In
Keep multiple versions in your registry. Switch between them instantly by editing the config.
๐ Multi-Domain Routing
Run unlimited apps on one server. Each gets its own domain with automatic HTTPS via Cloudflare.
๐ฆ Zero-Downtime Updates
Push new versions anytime. Gordon handles graceful container swaps.
๐ Automatic Deployment
Containers deploy instantly when you push new images. No manual deployment steps needed.
๐ฐ Cost Comparison
| Solution | Monthly Cost | Setup Complexity | # Apps |
|---|---|---|---|
| Heroku | $7-25/app | โญ | Limited |
| AWS ECS | $50-200+ | โญโญโญโญโญ | Unlimited |
| Kubernetes | $100+ | โญโญโญโญโญ | Unlimited |
| Gordon + VPS | $5-20 total | โญโญ | Unlimited |
๐ Quick Start (5 minutes)
1. Get a VPS & Install Docker
# Any VPS provider: DigitalOcean, Linode, Vultr, Hetzner
# Ubuntu/Debian recommended
curl -fsSL https://get.docker.com | sh
2. Install Gordon
wget https://github.com/yourusername/gordon/releases/latest/download/gordon-linux-amd64
chmod +x gordon-linux-amd64
sudo mv gordon-linux-amd64 /usr/local/bin/gordon
3. Create Config
# gordon.toml
[server]
port = 8080
registry_domain = "registry.yourdomain.com"
runtime = "auto" # auto-detects Docker/Podman
ssl_email = "you@yourdomain.com"
[registry_auth]
enabled = true
username = "admin"
password = "your-secure-password"
[routes]
"app.yourdomain.com" = "myapp:latest"
"api.yourdomain.com" = "api:v1"
"blog.yourdomain.com" = "wordpress:latest"
4. Point Cloudflare DNS
A *.yourdomain.com โ YOUR_VPS_IP
A yourdomain.com โ YOUR_VPS_IP
5. Start Gordon & Configure Firewall
# Start Gordon
sudo gordon start
# Set up port forwarding (choose one option)
# Option A: iptables (most common)
sudo iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 8080
sudo iptables -t nat -A PREROUTING -p tcp --dport 443 -j REDIRECT --to-port 8080
# Option B: UFW with NAT (Ubuntu)
sudo ufw allow 22,80,443,8080/tcp
echo 'net.ipv4.ip_forward=1' | sudo tee -a /etc/sysctl.conf
sudo sysctl -p
# Deploy your first app
docker tag myapp:latest registry.yourdomain.com/myapp:latest
docker push registry.yourdomain.com/myapp:latest
# Visit https://app.yourdomain.com ๐
๐ฏ Real-World Examples
Deploy a Node.js App
# Build and test locally first
docker build -t myapp .
docker run -p 3000:3000 myapp # Test it!
# Tag with version AND latest
docker tag myapp registry.yourdomain.com/myapp:v1.0.0
docker tag myapp registry.yourdomain.com/myapp:latest
# Push both tags
docker push registry.yourdomain.com/myapp:v1.0.0
docker push registry.yourdomain.com/myapp:latest
# Auto-deployed to app.yourdomain.com
Smart Versioning Strategy
# Always push versioned tags
docker tag myapp registry.yourdomain.com/myapp:v1.0.1
docker push registry.yourdomain.com/myapp:v1.0.1
# Update config to test
"app.yourdomain.com" = "myapp:v1.0.1"
# Happy? Update latest
docker tag myapp registry.yourdomain.com/myapp:latest
docker push registry.yourdomain.com/myapp:latest
Instant Rollback When Things Break
# Production broke after deploying v1.0.2?
# Just edit gordon.toml:
# From:
"app.yourdomain.com" = "myapp:v1.0.2"
# To:
"app.yourdomain.com" = "myapp:v1.0.1"
# Save. Fixed in seconds. No scripts, no drama.
Multiple Environments
[routes]
"app.yourdomain.com" = "myapp:v1.0.0" # Stable production
"staging.yourdomain.com" = "myapp:latest" # Latest builds
"feature-xyz.yourdomain.com" = "myapp:feature-xyz" # Feature branch
๐ก๏ธ Production-Ready
Systemd Service
sudo tee /etc/systemd/system/gordon.service > /dev/null <<EOF
[Unit]
Description=Gordon Container Platform
After=docker.service
[Service]
Type=simple
Restart=always
RestartSec=5
ExecStart=/usr/local/bin/gordon start
[Install]
WantedBy=multi-user.target
EOF
sudo systemctl enable --now gordon
With Docker Compose
version: '3.8'
services:
gordon:
image: gordon:latest
ports:
- "80:8080"
- "443:8080"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- ./gordon.toml:/app/gordon.toml:ro
- ./data:/data
restart: unless-stopped
๐ค FAQ
Q: How is this different from Traefik/Nginx Proxy Manager?
A: Gordon includes a Docker registry and automatic deployment. Push an image, get a deployment. No manual container management.
Q: Where do builds happen?
A: On YOUR machine. If it runs locally, it'll run in production. No mysterious build server issues.
Q: How do I handle broken deployments?
A: Just edit gordon.toml to point to a previous version. Rollback takes seconds, not minutes.
Q: Do I need CI/CD?
A: Nope! Your laptop is the CI/CD. Build, test locally, push when ready. Keep it simple.
Q: Do I need Cloudflare?
A: Recommended for free SSL and DDoS protection, but Gordon works with any DNS provider.
Q: Can I run databases?
A: Yes! Gordon manages any container. Use volumes for persistent data.
Q: Resource requirements?
A: Runs comfortably on 1GB RAM VPS. Gordon itself uses <50MB.
Q: What about secrets?
A: Use environment variables in your container or Docker secrets. Gordon doesn't interfere.
๐ก Philosophy: Build Local, Deploy Simple
Why No Build Servers?
- Your machine already works - Why replicate your dev environment in CI/CD?
- Instant feedback - Build errors show up immediately, not after pushing
- Perfect reproducibility - "Works on my machine" becomes a feature, not a bug
- Zero build queues - Deploy as fast as your internet can push
The Gordon Way
# Traditional CI/CD
push code โ wait for build โ hope it works โ debug remotely โ repeat
# The Gordon Way
build locally โ test locally โ push image โ instant deploy
๐๏ธ Architecture
Your Machine โ Docker Image โ Gordon Registry โ Auto-Deploy โ Live App
โ
Event System
โ
Domain Router โ Container
- Event-Driven: Push events trigger deployments automatically
- Config Hot-Reload: Edit gordon.toml, changes apply instantly
- Single Binary: No dependencies except Docker
- Stateless: Configuration is the only state
- Fast: Written in Go for minimal overhead
๐ Advanced Usage
Container Runtime Configuration
[server]
runtime = "auto" # auto, docker, podman, podman-rootless
socket_path = "" # optional custom socket path
# Examples:
# runtime = "docker"
# runtime = "podman"
# socket_path = "unix:///run/user/1000/podman/podman.sock"
Environment Override
# Override container socket with environment variable
export CONTAINER_HOST=unix:///custom/path/container.sock
export CONTAINER_HOST=tcp://remote-docker:2376
# Works for both Docker and Podman
gordon start
Runtime Auto-Detection
Gordon automatically detects available container runtimes in this order:
- Docker (
/var/run/docker.sock) - Podman root (
/run/podman/podman.sock) - Podman rootless (
$XDG_RUNTIME_DIR/podman/podman.sock)
Custom Ports
# Gordon auto-detects ports: 80, 8080, 3000
# Or use EXPOSE in Dockerfile
Registry Operations
# List images
curl -u admin:password https://registry.yourdomain.com/v2/_catalog
# List tags
curl -u admin:password https://registry.yourdomain.com/v2/myapp/tags/list
Multi-Server Setup
Deploy Gordon on multiple VPS servers with different configs for geographic distribution or separation of concerns.
๐ค Contributing
Gordon is open source and we love contributions! Check out our issues or submit a PR.
๐ License
GPL-3.0 - Use freely, contribute back.