2.0.1 dcf7d6b

README.md RawHistoryFolder

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?

  1. Your machine already works - Why replicate your dev environment in CI/CD?
  2. Instant feedback - Build errors show up immediately, not after pushing
  3. Perfect reproducibility - "Works on my machine" becomes a feature, not a bug
  4. 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:

  1. Docker (/var/run/docker.sock)
  2. Podman root (/run/podman/podman.sock)
  3. 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.


source
1# Gordon
2
3<div align="center">
4  <img src="assets/gordon-mascot.png" alt="Gordon Mascot" width="200">
5  <h3>The Smart Way to Deploy Containers on Your VPS</h3>
6  <p><em>Push code โ†’ Auto-deploy โ†’ Zero complexity</em></p>
7</div>
8
9## Why Gordon?
10
11**You have a $5 VPS. You want to run multiple apps. You don't want Kubernetes.**
12
13Gordon 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.
14
15### ๐ŸŽฏ Perfect For
16
17- **Solo developers** with multiple side projects on one VPS
18- **Small teams** who want Heroku-like simplicity without the cost
19- **Agencies** deploying client apps across VPS servers
20- **Anyone** tired of complex deployment pipelines
21
22## ๐Ÿš€ How It Works
23
24### Build Locally, Deploy Instantly
25
26```bash
27# 1. Build & test on YOUR machine
28docker build -t myapp .
29docker run -p 8080:8080 myapp  # Works? Great!
30
31# 2. Push to deploy
32docker tag myapp registry.yourdomain.com/myapp:latest
33docker push registry.yourdomain.com/myapp:latest
34
35# 3. That's it. Gordon deploys it automatically.
36```
37
38**No build servers. No CI/CD complexity. If it runs on your machine, it runs in production.**
39
40### ๐Ÿ”„ Instant Rollbacks
41
42Something broke? Just change your config:
43
44```toml
45# Before (in gordon.toml)
46"app.yourdomain.com" = "myapp:latest"
47
48# After - instant rollback!
49"app.yourdomain.com" = "myapp:v1.2.3"
50```
51
52Save the file. Gordon redeploys the previous version. Problem solved in seconds.
53
54## โœจ Key Features
55
56### ๐Ÿ  Local-First Development
57**Your machine is the build server.** Test locally, push when ready. No waiting for remote builds.
58
59### ๐Ÿฆ Built-in Docker Registry
60Your VPS becomes a private Docker registry. No Docker Hub subscription needed.
61
62### ๐Ÿ”„ Push-to-Deploy Magic
63Gordon watches for new images and deploys them instantly to configured domains.
64
65### โฎ๏ธ Version Control Built-In
66Keep multiple versions in your registry. Switch between them instantly by editing the config.
67
68### ๐ŸŒ Multi-Domain Routing
69Run unlimited apps on one server. Each gets its own domain with automatic HTTPS via Cloudflare.
70
71### ๐Ÿ“ฆ Zero-Downtime Updates
72Push new versions anytime. Gordon handles graceful container swaps.
73
74### ๐Ÿš€ Automatic Deployment
75Containers deploy instantly when you push new images. No manual deployment steps needed.
76
77## ๐Ÿ’ฐ Cost Comparison
78
79| Solution | Monthly Cost | Setup Complexity | # Apps |
80|----------|-------------|------------------|--------|
81| Heroku | $7-25/app | โญ | Limited |
82| AWS ECS | $50-200+ | โญโญโญโญโญ | Unlimited |
83| Kubernetes | $100+ | โญโญโญโญโญ | Unlimited |
84| **Gordon + VPS** | **$5-20 total** | **โญโญ** | **Unlimited** |
85
86## ๐Ÿš€ Quick Start (5 minutes)
87
88### 1. Get a VPS & Install Docker
89```bash
90# Any VPS provider: DigitalOcean, Linode, Vultr, Hetzner
91# Ubuntu/Debian recommended
92curl -fsSL https://get.docker.com | sh
93```
94
95### 2. Install Gordon
96```bash
97wget https://github.com/yourusername/gordon/releases/latest/download/gordon-linux-amd64
98chmod +x gordon-linux-amd64
99sudo mv gordon-linux-amd64 /usr/local/bin/gordon
100```
101
102### 3. Create Config
103```toml
104# gordon.toml
105[server]
106port = 8080
107registry_domain = "registry.yourdomain.com"
108runtime = "auto"  # auto-detects Docker/Podman
109ssl_email = "you@yourdomain.com"
110
111[registry_auth]
112enabled = true
113username = "admin"
114password = "your-secure-password"
115
116[routes]
117"app.yourdomain.com" = "myapp:latest"
118"api.yourdomain.com" = "api:v1"
119"blog.yourdomain.com" = "wordpress:latest"
120```
121
122### 4. Point Cloudflare DNS
123```
124A    *.yourdomain.com    โ†’    YOUR_VPS_IP
125A    yourdomain.com      โ†’    YOUR_VPS_IP
126```
127
128### 5. Start Gordon & Configure Firewall
129```bash
130# Start Gordon
131sudo gordon start
132
133# Set up port forwarding (choose one option)
134
135# Option A: iptables (most common)
136sudo iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 8080
137sudo iptables -t nat -A PREROUTING -p tcp --dport 443 -j REDIRECT --to-port 8080
138
139# Option B: UFW with NAT (Ubuntu)
140sudo ufw allow 22,80,443,8080/tcp
141echo 'net.ipv4.ip_forward=1' | sudo tee -a /etc/sysctl.conf
142sudo sysctl -p
143
144# Deploy your first app
145docker tag myapp:latest registry.yourdomain.com/myapp:latest
146docker push registry.yourdomain.com/myapp:latest
147# Visit https://app.yourdomain.com ๐ŸŽ‰
148```
149
150## ๐ŸŽฏ Real-World Examples
151
152### Deploy a Node.js App
153```bash
154# Build and test locally first
155docker build -t myapp .
156docker run -p 3000:3000 myapp  # Test it!
157
158# Tag with version AND latest
159docker tag myapp registry.yourdomain.com/myapp:v1.0.0
160docker tag myapp registry.yourdomain.com/myapp:latest
161
162# Push both tags
163docker push registry.yourdomain.com/myapp:v1.0.0
164docker push registry.yourdomain.com/myapp:latest
165
166# Auto-deployed to app.yourdomain.com
167```
168
169### Smart Versioning Strategy
170```bash
171# Always push versioned tags
172docker tag myapp registry.yourdomain.com/myapp:v1.0.1
173docker push registry.yourdomain.com/myapp:v1.0.1
174
175# Update config to test
176"app.yourdomain.com" = "myapp:v1.0.1"
177
178# Happy? Update latest
179docker tag myapp registry.yourdomain.com/myapp:latest
180docker push registry.yourdomain.com/myapp:latest
181```
182
183### Instant Rollback When Things Break
184```toml
185# Production broke after deploying v1.0.2?
186# Just edit gordon.toml:
187
188# From:
189"app.yourdomain.com" = "myapp:v1.0.2"
190
191# To:
192"app.yourdomain.com" = "myapp:v1.0.1"
193
194# Save. Fixed in seconds. No scripts, no drama.
195```
196
197### Multiple Environments
198```toml
199[routes]
200"app.yourdomain.com" = "myapp:v1.0.0"      # Stable production
201"staging.yourdomain.com" = "myapp:latest"   # Latest builds
202"feature-xyz.yourdomain.com" = "myapp:feature-xyz"  # Feature branch
203```
204
205## ๐Ÿ›ก๏ธ Production-Ready
206
207### Systemd Service
208```bash
209sudo tee /etc/systemd/system/gordon.service > /dev/null <<EOF
210[Unit]
211Description=Gordon Container Platform
212After=docker.service
213
214[Service]
215Type=simple
216Restart=always
217RestartSec=5
218ExecStart=/usr/local/bin/gordon start
219
220[Install]
221WantedBy=multi-user.target
222EOF
223
224sudo systemctl enable --now gordon
225```
226
227### With Docker Compose
228```yaml
229version: '3.8'
230services:
231  gordon:
232    image: gordon:latest
233    ports:
234      - "80:8080"
235      - "443:8080"
236    volumes:
237      - /var/run/docker.sock:/var/run/docker.sock
238      - ./gordon.toml:/app/gordon.toml:ro
239      - ./data:/data
240    restart: unless-stopped
241```
242
243## ๐Ÿค” FAQ
244
245**Q: How is this different from Traefik/Nginx Proxy Manager?**  
246A: Gordon includes a Docker registry and automatic deployment. Push an image, get a deployment. No manual container management.
247
248**Q: Where do builds happen?**  
249A: On YOUR machine. If it runs locally, it'll run in production. No mysterious build server issues.
250
251**Q: How do I handle broken deployments?**  
252A: Just edit gordon.toml to point to a previous version. Rollback takes seconds, not minutes.
253
254**Q: Do I need CI/CD?**  
255A: Nope! Your laptop is the CI/CD. Build, test locally, push when ready. Keep it simple.
256
257**Q: Do I need Cloudflare?**  
258A: Recommended for free SSL and DDoS protection, but Gordon works with any DNS provider.
259
260**Q: Can I run databases?**  
261A: Yes! Gordon manages any container. Use volumes for persistent data.
262
263**Q: Resource requirements?**  
264A: Runs comfortably on 1GB RAM VPS. Gordon itself uses <50MB.
265
266**Q: What about secrets?**  
267A: Use environment variables in your container or Docker secrets. Gordon doesn't interfere.
268
269## ๐Ÿ’ก Philosophy: Build Local, Deploy Simple
270
271### Why No Build Servers?
272
2731. **Your machine already works** - Why replicate your dev environment in CI/CD?
2742. **Instant feedback** - Build errors show up immediately, not after pushing
2753. **Perfect reproducibility** - "Works on my machine" becomes a feature, not a bug
2764. **Zero build queues** - Deploy as fast as your internet can push
277
278### The Gordon Way
279
280```bash
281# Traditional CI/CD
282push code โ†’ wait for build โ†’ hope it works โ†’ debug remotely โ†’ repeat
283
284# The Gordon Way
285build locally โ†’ test locally โ†’ push image โ†’ instant deploy
286```
287
288## ๐Ÿ—๏ธ Architecture
289
290```
291Your Machine โ†’ Docker Image โ†’ Gordon Registry โ†’ Auto-Deploy โ†’ Live App
292                                      โ†“
293                               Event System
294                                      โ†“
295                           Domain Router โ†’ Container
296```
297
298- **Event-Driven**: Push events trigger deployments automatically
299- **Config Hot-Reload**: Edit gordon.toml, changes apply instantly
300- **Single Binary**: No dependencies except Docker
301- **Stateless**: Configuration is the only state
302- **Fast**: Written in Go for minimal overhead
303
304## ๐Ÿš€ Advanced Usage
305
306### Container Runtime Configuration
307```toml
308[server]
309runtime = "auto"  # auto, docker, podman, podman-rootless
310socket_path = ""  # optional custom socket path
311
312# Examples:
313# runtime = "docker"
314# runtime = "podman"
315# socket_path = "unix:///run/user/1000/podman/podman.sock"
316```
317
318### Environment Override
319```bash
320# Override container socket with environment variable
321export CONTAINER_HOST=unix:///custom/path/container.sock
322export CONTAINER_HOST=tcp://remote-docker:2376
323
324# Works for both Docker and Podman
325gordon start
326```
327
328### Runtime Auto-Detection
329Gordon automatically detects available container runtimes in this order:
3301. **Docker** (`/var/run/docker.sock`)
3312. **Podman root** (`/run/podman/podman.sock`) 
3323. **Podman rootless** (`$XDG_RUNTIME_DIR/podman/podman.sock`)
333
334### Custom Ports
335```toml
336# Gordon auto-detects ports: 80, 8080, 3000
337# Or use EXPOSE in Dockerfile
338```
339
340### Registry Operations
341```bash
342# List images
343curl -u admin:password https://registry.yourdomain.com/v2/_catalog
344
345# List tags
346curl -u admin:password https://registry.yourdomain.com/v2/myapp/tags/list
347```
348
349### Multi-Server Setup
350Deploy Gordon on multiple VPS servers with different configs for geographic distribution or separation of concerns.
351
352## ๐Ÿค Contributing
353
354Gordon is open source and we love contributions! Check out our [issues](https://github.com/yourusername/gordon/issues) or submit a PR.
355
356## ๐Ÿ“„ License
357
358GPL-3.0 - Use freely, contribute back.
359
360---
361
362<div align="center">
363  <p><strong>Stop overcomplicating container deployment.</strong></p>
364  <p>Star โญ this repo if Gordon saves you money!</p>
365</div>

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
โ†‘ โ†“ โ† โ†’ home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 7

Tags 106

โ†‘โ†“ moveenter openesc close