# Gordon
The Smart Way to Deploy Containers on Your VPS
Push code → Auto-deploy → Zero complexity
## 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
```bash
# 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:
```toml
# 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
```bash
# Any VPS provider: DigitalOcean, Linode, Vultr, Hetzner
# Ubuntu/Debian recommended
curl -fsSL https://get.docker.com | sh
```
### 2. Install Gordon
```bash
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
```toml
# 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
```bash
# 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
```bash
# 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
```bash
# 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
```toml
# 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
```toml
[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
```bash
sudo tee /etc/systemd/system/gordon.service > /dev/null <
Stop overcomplicating container deployment.
Star ⭐ this repo if Gordon saves you money!