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
- cf615eca024f13bde4d094781ea0f67cf224c139
- author
- bamen · · 2025-06-07 13:11 UTC
- parent
- 3820de3
- 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 | |||
| 76 | 76 | ||
| 77 | 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 | 80 | ```bash | |
| 81 | 81 | # Any VPS provider: DigitalOcean, Linode, Vultr, Hetzner | |
| 82 | 82 | # Ubuntu/Debian recommended | |
| 83 | 83 | ||
| 84 | + | # Install Essentials | |
| 85 | + | sudo apt update | |
| 86 | + | sudo apt install -y podman ufw | |
| 87 | + | ||
| 84 | 88 | # Configure UFW firewall first | |
| 85 | 89 | sudo ufw --force enable | |
| 86 | 90 | sudo ufw default deny incoming | |
| @@ -88,12 +92,20 @@ sudo ufw default allow outgoing | |||
| 88 | 92 | sudo ufw allow 22/tcp | |
| 89 | 93 | sudo ufw allow 80/tcp | |
| 90 | 94 | 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) | |
| 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 | + | ``` | |
| 97 | 109 | echo 'user.max_user_namespaces=28633' | sudo tee -a /etc/sysctl.conf | |
| 98 | 110 | sudo sysctl -p | |
| 99 | 111 | ||
| @@ -102,8 +114,10 @@ sudo usermod --add-subuids 100000-165535 --add-subgids 100000-165535 $USER | |||
| 102 | 114 | ||
| 103 | 115 | # Start user services (no root required!) | |
| 104 | 116 | systemctl --user enable --now podman.socket | |
| 117 | + | ``` | |
| 105 | 118 | ||
| 106 | - | # Configure registries for your Gordon registry | |
| 119 | + | ### 4. Configure registries for your Gordon registry | |
| 120 | + | ``` | |
| 107 | 121 | mkdir -p ~/.config/containers | |
| 108 | 122 | tee ~/.config/containers/registries.conf > /dev/null <<EOF | |
| 109 | 123 | [registries.search] | |
| @@ -117,23 +131,21 @@ registries = [] | |||
| 117 | 131 | EOF | |
| 118 | 132 | ``` | |
| 119 | 133 | ||
| 120 | - | ### 2. Install Gordon | |
| 134 | + | ### 5. Install Gordon | |
| 121 | 135 | ```bash | |
| 122 | 136 | wget https://github.com/bnema/gordon/releases/latest/download/gordon-linux-amd64 | |
| 123 | 137 | chmod +x gordon-linux-amd64 | |
| 124 | 138 | sudo mv gordon-linux-amd64 /usr/local/bin/gordon | |
| 125 | 139 | ``` | |
| 126 | 140 | ||
| 127 | - | ### 3. Create Config | |
| 141 | + | ### 6. Create Config | |
| 128 | 142 | ```toml | |
| 129 | - | # Create gordon.toml in current directory (or use --config flag) | |
| 130 | 143 | # Gordon searches for config in: ./ → ~/.config/gordon/ → ~/.gordon/ → ~/ → /etc/gordon/ | |
| 131 | - | ||
| 144 | + | # (or use --config flag) | |
| 132 | 145 | [server] | |
| 133 | 146 | port = 8080 | |
| 134 | 147 | 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 | |
| 137 | 149 | ||
| 138 | 150 | [registry_auth] | |
| 139 | 151 | enabled = true | |
| @@ -149,13 +161,13 @@ password = "your-secure-password" | |||
| 149 | 161 | # gordon --config /path/to/custom.toml start | |
| 150 | 162 | ``` | |
| 151 | 163 | ||
| 152 | - | ### 4. Point Cloudflare DNS | |
| 164 | + | ### 7. Point Cloudflare DNS | |
| 153 | 165 | ``` | |
| 154 | 166 | A *.yourdomain.com → YOUR_VPS_IP | |
| 155 | 167 | A yourdomain.com → YOUR_VPS_IP | |
| 156 | 168 | ``` | |
| 157 | 169 | ||
| 158 | - | ### 5. Create Systemd Service (Rootless) | |
| 170 | + | ### 8. Create Systemd Service (Rootless) | |
| 159 | 171 | ```bash | |
| 160 | 172 | # Create user systemd service (no root privileges needed!) | |
| 161 | 173 | mkdir -p ~/.config/systemd/user | |
| @@ -189,18 +201,7 @@ sudo loginctl enable-linger $USER | |||
| 189 | 201 | systemctl --user status gordon | |
| 190 | 202 | ``` | |
| 191 | 203 | ||
| 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 | |
| 204 | 205 | ```bash | |
| 205 | 206 | # Now from your local development machine: | |
| 206 | 207 | # Authenticate with your Gordon registry | |
| @@ -215,50 +216,59 @@ podman push registry.yourdomain.com/myapp:latest | |||
| 215 | 216 | ||
| 216 | 217 | ## Real-World Examples | |
| 217 | 218 | ||
| 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 | + | ||
| 219 | 222 | ```bash | |
| 220 | - | # Build and test locally first | |
| 223 | + | # 1. Build and test locally first | |
| 221 | 224 | podman build -t myapp . | |
| 222 | 225 | podman run -p 3000:3000 myapp # Test it! | |
| 223 | 226 | ||
| 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 | |
| 226 | 231 | podman tag myapp registry.yourdomain.com/myapp:latest | |
| 227 | 232 | ||
| 228 | - | # Push both tags to your Gordon registry | |
| 229 | - | podman push registry.yourdomain.com/myapp:v1.0.0 | |
| 233 | + | # 4. Push to deploy | |
| 230 | 234 | podman push registry.yourdomain.com/myapp:latest | |
| 231 | 235 | ||
| 232 | - | # Gordon automatically detects the push and deploys to app.yourdomain.com | |
| 236 | + | # Gordon automatically detects the push and deploys the new 'latest' version. | |
| 233 | 237 | ``` | |
| 234 | 238 | ||
| 235 | 239 | ### 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 | 242 | ```bash | |
| 237 | - | # Always push versioned tags first | |
| 243 | + | # 1. Always push a specific version tag first. This creates a history. | |
| 238 | 244 | podman tag myapp registry.yourdomain.com/myapp:v1.0.1 | |
| 239 | 245 | podman push registry.yourdomain.com/myapp:v1.0.1 | |
| 240 | 246 | ||
| 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" | |
| 244 | 250 | ||
| 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 | |
| 247 | 254 | 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 | 260 | ### Instant Rollback When Things Break | |
| 251 | 261 | ```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: | |
| 254 | 264 | ||
| 255 | 265 | # From: | |
| 256 | - | "app.yourdomain.com" = "myapp:v1.0.2" | |
| 266 | + | "app.yourdomain.com" = "myapp:latest" | |
| 257 | 267 | ||
| 258 | 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 | 274 | ### 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 | ```bash | 80 | ```bash | ||
| 81 | # Any VPS provider: DigitalOcean, Linode, Vultr, Hetzner | 81 | # Any VPS provider: DigitalOcean, Linode, Vultr, Hetzner | ||
| 82 | # Ubuntu/Debian recommended | 82 | # Ubuntu/Debian recommended | ||
| 83 | 83 | ||||
| 84 | + | # Install Essentials | |||
| 85 | + | sudo apt update | |||
| 86 | + | sudo apt install -y podman ufw | |||
| 87 | + | ||||
| 84 | # Configure UFW firewall first | 88 | # Configure UFW firewall first | ||
| 85 | sudo ufw --force enable | 89 | sudo ufw --force enable | ||
| 86 | sudo ufw default deny incoming | 90 | sudo ufw default deny incoming | ||
| @@ -88,12 +92,20 @@ sudo ufw default allow outgoing | |||||
| 88 | sudo ufw allow 22/tcp | 92 | sudo ufw allow 22/tcp | ||
| 89 | sudo ufw allow 80/tcp | 93 | sudo ufw allow 80/tcp | ||
| 90 | sudo ufw allow 443/tcp | 94 | 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 update | 104 | + | sudo apt install -y iptables-persistent |
| 94 | - | sudo apt install -y podman | 105 | + | sudo netfilter-persistent save |
| 95 | - | 106 | + | ``` | |
| 96 | - | # Enable rootless mode for enhanced security | 107 | + | ### 3. Enable rootless mode for enhanced security |
| 108 | + | ``` | |||
| 97 | echo 'user.max_user_namespaces=28633' | sudo tee -a /etc/sysctl.conf | 109 | echo 'user.max_user_namespaces=28633' | sudo tee -a /etc/sysctl.conf | ||
| 98 | sudo sysctl -p | 110 | 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.socket | 116 | systemctl --user enable --now podman.socket | ||
| 117 | + | ``` | |||
| 105 | 118 | ||||
| 106 | - | # Configure registries for your Gordon registry | 119 | + | ### 4. Configure registries for your Gordon registry |
| 120 | + | ``` | |||
| 107 | mkdir -p ~/.config/containers | 121 | mkdir -p ~/.config/containers | ||
| 108 | tee ~/.config/containers/registries.conf > /dev/null <<EOF | 122 | tee ~/.config/containers/registries.conf > /dev/null <<EOF | ||
| 109 | [registries.search] | 123 | [registries.search] | ||
| @@ -117,23 +131,21 @@ registries = [] | |||||
| 117 | EOF | 131 | EOF | ||
| 118 | ``` | 132 | ``` | ||
| 119 | 133 | ||||
| 120 | - | ### 2. Install Gordon | 134 | + | ### 5. Install Gordon |
| 121 | ```bash | 135 | ```bash | ||
| 122 | wget https://github.com/bnema/gordon/releases/latest/download/gordon-linux-amd64 | 136 | wget https://github.com/bnema/gordon/releases/latest/download/gordon-linux-amd64 | ||
| 123 | chmod +x gordon-linux-amd64 | 137 | chmod +x gordon-linux-amd64 | ||
| 124 | sudo mv gordon-linux-amd64 /usr/local/bin/gordon | 138 | sudo mv gordon-linux-amd64 /usr/local/bin/gordon | ||
| 125 | ``` | 139 | ``` | ||
| 126 | 140 | ||||
| 127 | - | ### 3. Create Config | 141 | + | ### 6. Create Config |
| 128 | ```toml | 142 | ```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 = 8080 | 146 | port = 8080 | ||
| 134 | registry_domain = "registry.yourdomain.com" | 147 | registry_domain = "registry.yourdomain.com" | ||
| 135 | - | runtime = "podman-rootless" # Secure rootless mode | 148 | + | 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 = true | 151 | enabled = true | ||
| @@ -149,13 +161,13 @@ password = "your-secure-password" | |||||
| 149 | # gordon --config /path/to/custom.toml start | 161 | # gordon --config /path/to/custom.toml start | ||
| 150 | ``` | 162 | ``` | ||
| 151 | 163 | ||||
| 152 | - | ### 4. Point Cloudflare DNS | 164 | + | ### 7. Point Cloudflare DNS |
| 153 | ``` | 165 | ``` | ||
| 154 | A *.yourdomain.com → YOUR_VPS_IP | 166 | A *.yourdomain.com → YOUR_VPS_IP | ||
| 155 | A yourdomain.com → YOUR_VPS_IP | 167 | A yourdomain.com → YOUR_VPS_IP | ||
| 156 | ``` | 168 | ``` | ||
| 157 | 169 | ||||
| 158 | - | ### 5. Create Systemd Service (Rootless) | 170 | + | ### 8. Create Systemd Service (Rootless) |
| 159 | ```bash | 171 | ```bash | ||
| 160 | # Create user systemd service (no root privileges needed!) | 172 | # Create user systemd service (no root privileges needed!) | ||
| 161 | mkdir -p ~/.config/systemd/user | 173 | mkdir -p ~/.config/systemd/user | ||
| @@ -189,18 +201,7 @@ sudo loginctl enable-linger $USER | |||||
| 189 | systemctl --user status gordon | 201 | systemctl --user status gordon | ||
| 190 | ``` | 202 | ``` | ||
| 191 | 203 | ||||
| 192 | - | ### 6. Redirect Ports 80/443 to 8080 | 204 | + | ### 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 | ```bash | 205 | ```bash | ||
| 205 | # Now from your local development machine: | 206 | # Now from your local development machine: | ||
| 206 | # Authenticate with your Gordon registry | 207 | # Authenticate with your Gordon registry | ||
| @@ -215,50 +216,59 @@ podman push registry.yourdomain.com/myapp:latest | |||||
| 215 | 216 | ||||
| 216 | ## Real-World Examples | 217 | ## Real-World Examples | ||
| 217 | 218 | ||||
| 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 | + | ||||
| 219 | ```bash | 222 | ```bash | ||
| 220 | - | # Build and test locally first | 223 | + | # 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 latest | 227 | + | # 2. In gordon.toml, point your domain to the 'latest' tag |
| 225 | - | podman tag myapp registry.yourdomain.com/myapp:v1.0.0 | 228 | + | # "app.yourdomain.com" = "myapp:latest" |
| 229 | + | ||||
| 230 | + | # 3. Tag your image as 'latest' for your registry | |||
| 226 | podman tag myapp registry.yourdomain.com/myapp:latest | 231 | podman tag myapp registry.yourdomain.com/myapp:latest | ||
| 227 | 232 | ||||
| 228 | - | # Push both tags to your Gordon registry | 233 | + | # 4. Push to deploy |
| 229 | - | podman push registry.yourdomain.com/myapp:v1.0.0 | |||
| 230 | podman push registry.yourdomain.com/myapp:latest | 234 | podman push registry.yourdomain.com/myapp:latest | ||
| 231 | 235 | ||||
| 232 | - | # Gordon automatically detects the push and deploys to app.yourdomain.com | 236 | + | # Gordon automatically detects the push and deploys the new 'latest' version. |
| 233 | ``` | 237 | ``` | ||
| 234 | 238 | ||||
| 235 | ### Smart Versioning Strategy | 239 | ### 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 | ```bash | 242 | ```bash | ||
| 237 | - | # Always push versioned tags first | 243 | + | # 1. Always push a specific version tag first. This creates a history. |
| 238 | podman tag myapp registry.yourdomain.com/myapp:v1.0.1 | 244 | podman tag myapp registry.yourdomain.com/myapp:v1.0.1 | ||
| 239 | podman push registry.yourdomain.com/myapp:v1.0.1 | 245 | podman push registry.yourdomain.com/myapp:v1.0.1 | ||
| 240 | 246 | ||||
| 241 | - | # Update config to test the new version | 247 | + | # 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 latest | 251 | + | # 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:latest | 252 | + | # 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:latest | 254 | 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 Break | 260 | ### Instant Rollback When Things Break | ||
| 251 | ```toml | 261 | ```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 Environments | 274 | ### Multiple Environments | ||