detached 702f8ae

docs(README): Update quick start guide with UFW installation and port redirection instructions

- Modify quick start steps to include UFW installation for enhanced security.
- Add instructions for redirecting ports 80/443 to 8080 using iptables.
- Reorganize steps for clarity and consistency in the setup process.
commit
702f8aeb56322dc6ff267f8eb78790b687cd82e9
author
bamen · · 2025-06-07 13:11 UTC
parent
aa7164f
signature
unsigned
1 file · +55 -45
M README.md +55 -45
@@ -76,11 +76,15 @@ Containers deploy instantly when you push new images. No manual deployment steps
7676
7777 ## Quick Start (5 minutes)
7878
79-### 1. Get a VPS & Install Podman (Rootless & Secure)
79+### 1. Get a VPS, Install Podman and UFW
8080 ```bash
8181 # Any VPS provider: DigitalOcean, Linode, Vultr, Hetzner
8282 # Ubuntu/Debian recommended
8383
84+# Install Essentials
85+sudo apt update
86+sudo apt install -y podman ufw
87+
8488 # Configure UFW firewall first
8589 sudo ufw --force enable
8690 sudo ufw default deny incoming
@@ -88,12 +92,20 @@ sudo ufw default allow outgoing
8892 sudo ufw allow 22/tcp
8993 sudo ufw allow 80/tcp
9094 sudo ufw allow 443/tcp
95+sudo ufw enable
96+```
97+### 2. Redirect Ports 80/443 to 8080
98+```bash
99+# Simple iptables redirect
100+sudo iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 8080
101+sudo iptables -t nat -A PREROUTING -p tcp --dport 443 -j REDIRECT --to-port 8080
91102
92-# Install Podman (more secure than Docker)
93-sudo apt update
94-sudo apt install -y podman
95-
96-# Enable rootless mode for enhanced security
103+# Make rules persistent across reboots
104+sudo apt install -y iptables-persistent
105+sudo netfilter-persistent save
106+```
107+### 3. Enable rootless mode for enhanced security
108+```
97109 echo 'user.max_user_namespaces=28633' | sudo tee -a /etc/sysctl.conf
98110 sudo sysctl -p
99111
@@ -102,8 +114,10 @@ sudo usermod --add-subuids 100000-165535 --add-subgids 100000-165535 $USER
102114
103115 # Start user services (no root required!)
104116 systemctl --user enable --now podman.socket
117+```
105118
106-# Configure registries for your Gordon registry
119+### 4. Configure registries for your Gordon registry
120+```
107121 mkdir -p ~/.config/containers
108122 tee ~/.config/containers/registries.conf > /dev/null <<EOF
109123 [registries.search]
@@ -117,23 +131,21 @@ registries = []
117131 EOF
118132 ```
119133
120-### 2. Install Gordon
134+### 5. Install Gordon
121135 ```bash
122136 wget https://github.com/bnema/gordon/releases/latest/download/gordon-linux-amd64
123137 chmod +x gordon-linux-amd64
124138 sudo mv gordon-linux-amd64 /usr/local/bin/gordon
125139 ```
126140
127-### 3. Create Config
141+### 6. Create Config
128142 ```toml
129-# Create gordon.toml in current directory (or use --config flag)
130143 # Gordon searches for config in: ./ → ~/.config/gordon/ → ~/.gordon/ → ~/ → /etc/gordon/
131-
144+# (or use --config flag)
132145 [server]
133146 port = 8080
134147 registry_domain = "registry.yourdomain.com"
135-runtime = "podman-rootless" # Secure rootless mode
136-ssl_email = "you@yourdomain.com"
148+runtime = "podman-rootless" # Can be auto, docker, podman, podman-rootless
137149
138150 [registry_auth]
139151 enabled = true
@@ -149,13 +161,13 @@ password = "your-secure-password"
149161 # gordon --config /path/to/custom.toml start
150162 ```
151163
152-### 4. Point Cloudflare DNS
164+### 7. Point Cloudflare DNS
153165 ```
154166 A *.yourdomain.com → YOUR_VPS_IP
155167 A yourdomain.com → YOUR_VPS_IP
156168 ```
157169
158-### 5. Create Systemd Service (Rootless)
170+### 8. Create Systemd Service (Rootless)
159171 ```bash
160172 # Create user systemd service (no root privileges needed!)
161173 mkdir -p ~/.config/systemd/user
@@ -189,18 +201,7 @@ sudo loginctl enable-linger $USER
189201 systemctl --user status gordon
190202 ```
191203
192-### 6. Redirect Ports 80/443 to 8080
193-```bash
194-# Simple iptables redirect
195-sudo iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 8080
196-sudo iptables -t nat -A PREROUTING -p tcp --dport 443 -j REDIRECT --to-port 8080
197-
198-# Make rules persistent across reboots
199-sudo apt install -y iptables-persistent
200-sudo netfilter-persistent save
201-```
202-
203-### 7. Deploy Your First App
204+### 8. Deploy Your First App
204205 ```bash
205206 # Now from your local development machine:
206207 # Authenticate with your Gordon registry
@@ -215,50 +216,59 @@ podman push registry.yourdomain.com/myapp:latest
215216
216217 ## Real-World Examples
217218
218-### Deploy a Node.js App
219+### Deploy a Node.js App (The "Push-to-Deploy" Way)
220+This is the simplest way to deploy. Your production environment is always in sync with your `latest` tag.
221+
219222 ```bash
220-# Build and test locally first
223+# 1. Build and test locally first
221224 podman build -t myapp .
222225 podman run -p 3000:3000 myapp # Test it!
223226
224-# Tag with registry prefix for both version and latest
225-podman tag myapp registry.yourdomain.com/myapp:v1.0.0
227+# 2. In gordon.toml, point your domain to the 'latest' tag
228+# "app.yourdomain.com" = "myapp:latest"
229+
230+# 3. Tag your image as 'latest' for your registry
226231 podman tag myapp registry.yourdomain.com/myapp:latest
227232
228-# Push both tags to your Gordon registry
229-podman push registry.yourdomain.com/myapp:v1.0.0
233+# 4. Push to deploy
230234 podman push registry.yourdomain.com/myapp:latest
231235
232-# Gordon automatically detects the push and deploys to app.yourdomain.com
236+# Gordon automatically detects the push and deploys the new 'latest' version.
233237 ```
234238
235239 ### Smart Versioning Strategy
240+For more control, especially in production, you can use a combination of version tags and the `latest` tag. This makes rollbacks trivial and allows for staging environments.
241+
236242 ```bash
237-# Always push versioned tags first
243+# 1. Always push a specific version tag first. This creates a history.
238244 podman tag myapp registry.yourdomain.com/myapp:v1.0.1
239245 podman push registry.yourdomain.com/myapp:v1.0.1
240246
241-# Update config to test the new version
242-# Edit gordon.toml:
243-"app.yourdomain.com" = "myapp:v1.0.1"
247+# 2. Test the new version on a staging domain.
248+# In gordon.toml:
249+"staging.yourdomain.com" = "myapp:v1.0.1"
244250
245-# Happy with the new version? Tag and push as latest
246-podman tag registry.yourdomain.com/myapp:v1.0.1 registry.yourdomain.com/myapp:latest
251+# 3. Once tested and confirmed, promote it to production by updating 'latest'.
252+# This assumes 'myapp' still refers to the image for v1.0.1
253+podman tag myapp registry.yourdomain.com/myapp:latest
247254 podman push registry.yourdomain.com/myapp:latest
255+
256+# Your production route, which follows 'latest', will now be updated automatically.
257+# "app.yourdomain.com" = "myapp:latest"
248258 ```
249259
250260 ### Instant Rollback When Things Break
251261 ```toml
252-# Production broke after deploying v1.0.2?
253-# Just edit gordon.toml:
262+# Production broke after the latest push?
263+# Just edit gordon.toml to point to a previously pushed, stable version tag:
254264
255265 # From:
256-"app.yourdomain.com" = "myapp:v1.0.2"
266+"app.yourdomain.com" = "myapp:latest"
257267
258268 # To:
259-"app.yourdomain.com" = "myapp:v1.0.1"
269+"app.yourdomain.com" = "myapp:v1.0.0"
260270
261-# Save. Fixed in seconds. No scripts, no drama.
271+# Save the file. Gordon redeploys the stable version in seconds. No scripts, no drama.
262272 ```
263273
264274 ### Multiple Environments
@@ -76,11 +76,15 @@ Containers deploy instantly when you push new images. No manual deployment steps
76 76
77 ## Quick Start (5 minutes)77 ## Quick Start (5 minutes)
78 78
79-### 1. Get a VPS & Install Podman (Rootless & Secure)79+### 1. Get a VPS, Install Podman and UFW
80 ```bash80 ```bash
81 # Any VPS provider: DigitalOcean, Linode, Vultr, Hetzner81 # Any VPS provider: DigitalOcean, Linode, Vultr, Hetzner
82 # Ubuntu/Debian recommended82 # Ubuntu/Debian recommended
83 83
84+# Install Essentials
85+sudo apt update
86+sudo apt install -y podman ufw
87+
84 # Configure UFW firewall first88 # Configure UFW firewall first
85 sudo ufw --force enable89 sudo ufw --force enable
86 sudo ufw default deny incoming90 sudo ufw default deny incoming
@@ -88,12 +92,20 @@ sudo ufw default allow outgoing
88 sudo ufw allow 22/tcp92 sudo ufw allow 22/tcp
89 sudo ufw allow 80/tcp93 sudo ufw allow 80/tcp
90 sudo ufw allow 443/tcp94 sudo ufw allow 443/tcp
95+sudo ufw enable
96+```
97+### 2. Redirect Ports 80/443 to 8080
98+```bash
99+# Simple iptables redirect
100+sudo iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 8080
101+sudo iptables -t nat -A PREROUTING -p tcp --dport 443 -j REDIRECT --to-port 8080
91 102
92-# Install Podman (more secure than Docker)103+# Make rules persistent across reboots
93-sudo apt update104+sudo apt install -y iptables-persistent
94-sudo apt install -y podman105+sudo netfilter-persistent save
95-106+```
96-# Enable rootless mode for enhanced security107+### 3. Enable rootless mode for enhanced security
108+```
97 echo 'user.max_user_namespaces=28633' | sudo tee -a /etc/sysctl.conf109 echo 'user.max_user_namespaces=28633' | sudo tee -a /etc/sysctl.conf
98 sudo sysctl -p110 sudo sysctl -p
99 111
@@ -102,8 +114,10 @@ sudo usermod --add-subuids 100000-165535 --add-subgids 100000-165535 $USER
102 114
103 # Start user services (no root required!)115 # Start user services (no root required!)
104 systemctl --user enable --now podman.socket116 systemctl --user enable --now podman.socket
117+```
105 118
106-# Configure registries for your Gordon registry119+### 4. Configure registries for your Gordon registry
120+```
107 mkdir -p ~/.config/containers121 mkdir -p ~/.config/containers
108 tee ~/.config/containers/registries.conf > /dev/null <<EOF122 tee ~/.config/containers/registries.conf > /dev/null <<EOF
109 [registries.search]123 [registries.search]
@@ -117,23 +131,21 @@ registries = []
117 EOF131 EOF
118 ```132 ```
119 133
120-### 2. Install Gordon134+### 5. Install Gordon
121 ```bash135 ```bash
122 wget https://github.com/bnema/gordon/releases/latest/download/gordon-linux-amd64136 wget https://github.com/bnema/gordon/releases/latest/download/gordon-linux-amd64
123 chmod +x gordon-linux-amd64137 chmod +x gordon-linux-amd64
124 sudo mv gordon-linux-amd64 /usr/local/bin/gordon138 sudo mv gordon-linux-amd64 /usr/local/bin/gordon
125 ```139 ```
126 140
127-### 3. Create Config141+### 6. Create Config
128 ```toml142 ```toml
129-# Create gordon.toml in current directory (or use --config flag)
130 # Gordon searches for config in: ./ → ~/.config/gordon/ → ~/.gordon/ → ~/ → /etc/gordon/143 # Gordon searches for config in: ./ → ~/.config/gordon/ → ~/.gordon/ → ~/ → /etc/gordon/
131-144+# (or use --config flag)
132 [server]145 [server]
133 port = 8080146 port = 8080
134 registry_domain = "registry.yourdomain.com"147 registry_domain = "registry.yourdomain.com"
135-runtime = "podman-rootless" # Secure rootless mode148+runtime = "podman-rootless" # Can be auto, docker, podman, podman-rootless
136-ssl_email = "you@yourdomain.com"
137 149
138 [registry_auth]150 [registry_auth]
139 enabled = true151 enabled = true
@@ -149,13 +161,13 @@ password = "your-secure-password"
149 # gordon --config /path/to/custom.toml start161 # gordon --config /path/to/custom.toml start
150 ```162 ```
151 163
152-### 4. Point Cloudflare DNS164+### 7. Point Cloudflare DNS
153 ```165 ```
154 A *.yourdomain.com → YOUR_VPS_IP166 A *.yourdomain.com → YOUR_VPS_IP
155 A yourdomain.com → YOUR_VPS_IP167 A yourdomain.com → YOUR_VPS_IP
156 ```168 ```
157 169
158-### 5. Create Systemd Service (Rootless)170+### 8. Create Systemd Service (Rootless)
159 ```bash171 ```bash
160 # Create user systemd service (no root privileges needed!)172 # Create user systemd service (no root privileges needed!)
161 mkdir -p ~/.config/systemd/user173 mkdir -p ~/.config/systemd/user
@@ -189,18 +201,7 @@ sudo loginctl enable-linger $USER
189 systemctl --user status gordon201 systemctl --user status gordon
190 ```202 ```
191 203
192-### 6. Redirect Ports 80/443 to 8080204+### 8. Deploy Your First App
193-```bash
194-# Simple iptables redirect
195-sudo iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 8080
196-sudo iptables -t nat -A PREROUTING -p tcp --dport 443 -j REDIRECT --to-port 8080
197-
198-# Make rules persistent across reboots
199-sudo apt install -y iptables-persistent
200-sudo netfilter-persistent save
201-```
202-
203-### 7. Deploy Your First App
204 ```bash205 ```bash
205 # Now from your local development machine:206 # Now from your local development machine:
206 # Authenticate with your Gordon registry207 # Authenticate with your Gordon registry
@@ -215,50 +216,59 @@ podman push registry.yourdomain.com/myapp:latest
215 216
216 ## Real-World Examples217 ## Real-World Examples
217 218
218-### Deploy a Node.js App219+### Deploy a Node.js App (The "Push-to-Deploy" Way)
220+This is the simplest way to deploy. Your production environment is always in sync with your `latest` tag.
221+
219 ```bash222 ```bash
220-# Build and test locally first223+# 1. Build and test locally first
221 podman build -t myapp .224 podman build -t myapp .
222 podman run -p 3000:3000 myapp # Test it!225 podman run -p 3000:3000 myapp # Test it!
223 226
224-# Tag with registry prefix for both version and latest227+# 2. In gordon.toml, point your domain to the 'latest' tag
225-podman tag myapp registry.yourdomain.com/myapp:v1.0.0228+# "app.yourdomain.com" = "myapp:latest"
229+
230+# 3. Tag your image as 'latest' for your registry
226 podman tag myapp registry.yourdomain.com/myapp:latest231 podman tag myapp registry.yourdomain.com/myapp:latest
227 232
228-# Push both tags to your Gordon registry233+# 4. Push to deploy
229-podman push registry.yourdomain.com/myapp:v1.0.0
230 podman push registry.yourdomain.com/myapp:latest234 podman push registry.yourdomain.com/myapp:latest
231 235
232-# Gordon automatically detects the push and deploys to app.yourdomain.com236+# Gordon automatically detects the push and deploys the new 'latest' version.
233 ```237 ```
234 238
235 ### Smart Versioning Strategy239 ### Smart Versioning Strategy
240+For more control, especially in production, you can use a combination of version tags and the `latest` tag. This makes rollbacks trivial and allows for staging environments.
241+
236 ```bash242 ```bash
237-# Always push versioned tags first243+# 1. Always push a specific version tag first. This creates a history.
238 podman tag myapp registry.yourdomain.com/myapp:v1.0.1244 podman tag myapp registry.yourdomain.com/myapp:v1.0.1
239 podman push registry.yourdomain.com/myapp:v1.0.1245 podman push registry.yourdomain.com/myapp:v1.0.1
240 246
241-# Update config to test the new version247+# 2. Test the new version on a staging domain.
242-# Edit gordon.toml:248+# In gordon.toml:
243-"app.yourdomain.com" = "myapp:v1.0.1"249+"staging.yourdomain.com" = "myapp:v1.0.1"
244 250
245-# Happy with the new version? Tag and push as latest251+# 3. Once tested and confirmed, promote it to production by updating 'latest'.
246-podman tag registry.yourdomain.com/myapp:v1.0.1 registry.yourdomain.com/myapp:latest252+# This assumes 'myapp' still refers to the image for v1.0.1
253+podman tag myapp registry.yourdomain.com/myapp:latest
247 podman push registry.yourdomain.com/myapp:latest254 podman push registry.yourdomain.com/myapp:latest
255+
256+# Your production route, which follows 'latest', will now be updated automatically.
257+# "app.yourdomain.com" = "myapp:latest"
248 ```258 ```
249 259
250 ### Instant Rollback When Things Break260 ### Instant Rollback When Things Break
251 ```toml261 ```toml
252-# Production broke after deploying v1.0.2?262+# Production broke after the latest push?
253-# Just edit gordon.toml:263+# Just edit gordon.toml to point to a previously pushed, stable version tag:
254 264
255 # From:265 # From:
256-"app.yourdomain.com" = "myapp:v1.0.2"266+"app.yourdomain.com" = "myapp:latest"
257 267
258 # To:268 # To:
259-"app.yourdomain.com" = "myapp:v1.0.1"269+"app.yourdomain.com" = "myapp:v1.0.0"
260 270
261-# Save. Fixed in seconds. No scripts, no drama.271+# Save the file. Gordon redeploys the stable version in seconds. No scripts, no drama.
262 ```272 ```
263 273
264 ### Multiple Environments274 ### Multiple Environments

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