v2.31.0-dev18 7b9923f

routes.md RawHistoryFolder

Routes Configuration

Routes map hostnames to container images.

Configuration

[routes]
"app.mydomain.com" = { image = "myapp:latest" }
"api.mydomain.com" = { image = "myapi:v2.1.0" }
"admin.mydomain.com" = { image = "admin-panel:v1.0.0" }

Syntax

[routes]
"<domain>" = { image = "<image>:<tag>" }
Component Description
domain Public, fully qualified domain name
image Full container image reference, including tag
https Optional; add false for HTTP-only routes

Legacy http://... route keys are still read for backward compatibility and rewritten on the next save.

Route Types

HTTPS Routes (Default)

Standard routes expect HTTPS traffic (terminated by Cloudflare or similar):

[routes]
"app.mydomain.com" = { image = "myapp:latest" }

Route domains must be plain hostnames. Gordon rejects http:// and https:// prefixes, .local and .internal suffixes, localhost names, and IP literals.

Development Routes

For local testing, use a hostname you can resolve yourself:

[routes]
"dev-app.example.com" = { image = "internal-app:latest", https = false }

Version Strategies

Latest Tag

Always deploy the most recent push:

[routes]
"app.mydomain.com" = { image = "myapp:latest" }

Pinned Version

Deploy a specific version:

[routes]
"app.mydomain.com" = { image = "myapp:v2.1.0" }

Update the config to deploy a new version:

[routes]
"app.mydomain.com" = { image = "myapp:v2.2.0" }  # Changed

Semantic Versioning

Use different routes for different versions:

[routes]
"app.mydomain.com" = { image = "myapp:v2.1.0" }        # Production
"staging.mydomain.com" = { image = "myapp:staging" }    # Staging
"canary.mydomain.com" = { image = "myapp:canary" }      # Canary

Multiple Routes

Same Image, Different Domains

[routes]
"app.mydomain.com" = { image = "myapp:latest" }
"www.mydomain.com" = { image = "myapp:latest" }
"mydomain.com" = { image = "myapp:latest" }

Multiple Services

[routes]
"app.mydomain.com" = { image = "frontend:latest" }
"api.mydomain.com" = { image = "backend:v2.1.0" }
"docs.mydomain.com" = { image = "documentation:latest" }
"status.mydomain.com" = { image = "status-page:v1.0.0" }

How Routing Works

  1. Request arrives for app.mydomain.com
  2. Gordon looks up the route in configuration
  3. Finds running container for myapp:latest
  4. Proxies request to container's exposed port
  5. Returns response to client
Client ─> Gordon Proxy ─> Container
          (port 80)       (exposed port)

Deployment Flow

When you push an image:

docker push registry.mydomain.com/myapp:latest
  1. Gordon receives the image
  2. Checks routes for any that use myapp:latest
  3. Deploys new container for each matching route
  4. Updates proxy to route traffic to new container
  5. Stops old container

Route Changes

Route changes in the config file are hot-reloaded automatically:

  1. Edit [routes] in gordon.toml
  2. Save the file
  3. Gordon reloads the updated routes and proxy config

Legacy http://... route keys are still read here for backward compatibility and rewritten the next time Gordon saves the config.

You can still manage routes with the API or CLI if you prefer live mutations:

gordon routes add newapp.mydomain.com newapp:latest
gordon routes add app.mydomain.com myapp:v2.2.0
gordon routes remove oldapp.mydomain.com

Examples

Development Setup

[routes]
"dev-app.example.com" = { image = "myapp:latest" }
"dev-api.example.com" = { image = "myapi:latest" }

Add to /etc/hosts:

127.0.0.1  dev-app.example.com dev-api.example.com registry.example.com

Production Setup

[routes]
"app.company.com" = { image = "company-app:v2.1.0" }
"api.company.com" = { image = "company-api:v1.5.2" }
"admin.company.com" = { image = "admin-panel:v1.0.1" }
"docs.company.com" = { image = "company-docs:latest" }

Multi-Tenant SaaS

[routes]
# Platform services
"app.saas-platform.com" = { image = "saas-frontend:v2.1.0" }
"api.saas-platform.com" = { image = "saas-api:v3.2.1" }

# Customer subdomains
"acme.saas-platform.com" = { image = "saas-app:v2.1.0" }
"beta.saas-platform.com" = { image = "saas-app:v2.1.0" }

# Customer custom domains
"portal.acme-corp.com" = { image = "saas-app:v2.1.0" }

External Services

For non-containerized services (databases, legacy apps, etc.), see External Routes.

source
1# Routes Configuration
2
3Routes map hostnames to container images.
4
5## Configuration
6
7```toml
8[routes]
9"app.mydomain.com" = { image = "myapp:latest" }
10"api.mydomain.com" = { image = "myapi:v2.1.0" }
11"admin.mydomain.com" = { image = "admin-panel:v1.0.0" }
12```
13
14## Syntax
15
16```toml
17[routes]
18"<domain>" = { image = "<image>:<tag>" }
19```
20
21| Component | Description |
22|-----------|-------------|
23| `domain` | Public, fully qualified domain name |
24| `image` | Full container image reference, including tag |
25| `https` | Optional; add `false` for HTTP-only routes |
26
27Legacy `http://...` route keys are still read for backward compatibility and rewritten on the next save.
28
29## Route Types
30
31### HTTPS Routes (Default)
32
33Standard routes expect HTTPS traffic (terminated by Cloudflare or similar):
34
35```toml
36[routes]
37"app.mydomain.com" = { image = "myapp:latest" }
38```
39
40Route domains must be plain hostnames. Gordon rejects `http://` and `https://` prefixes, `.local` and `.internal` suffixes, localhost names, and IP literals.
41
42### Development Routes
43
44For local testing, use a hostname you can resolve yourself:
45
46```toml
47[routes]
48"dev-app.example.com" = { image = "internal-app:latest", https = false }
49```
50
51## Version Strategies
52
53### Latest Tag
54
55Always deploy the most recent push:
56
57```toml
58[routes]
59"app.mydomain.com" = { image = "myapp:latest" }
60```
61
62### Pinned Version
63
64Deploy a specific version:
65
66```toml
67[routes]
68"app.mydomain.com" = { image = "myapp:v2.1.0" }
69```
70
71Update the config to deploy a new version:
72
73```toml
74[routes]
75"app.mydomain.com" = { image = "myapp:v2.2.0" }  # Changed
76```
77
78### Semantic Versioning
79
80Use different routes for different versions:
81
82```toml
83[routes]
84"app.mydomain.com" = { image = "myapp:v2.1.0" }        # Production
85"staging.mydomain.com" = { image = "myapp:staging" }    # Staging
86"canary.mydomain.com" = { image = "myapp:canary" }      # Canary
87```
88
89## Multiple Routes
90
91### Same Image, Different Domains
92
93```toml
94[routes]
95"app.mydomain.com" = { image = "myapp:latest" }
96"www.mydomain.com" = { image = "myapp:latest" }
97"mydomain.com" = { image = "myapp:latest" }
98```
99
100### Multiple Services
101
102```toml
103[routes]
104"app.mydomain.com" = { image = "frontend:latest" }
105"api.mydomain.com" = { image = "backend:v2.1.0" }
106"docs.mydomain.com" = { image = "documentation:latest" }
107"status.mydomain.com" = { image = "status-page:v1.0.0" }
108```
109
110## How Routing Works
111
1121. Request arrives for `app.mydomain.com`
1132. Gordon looks up the route in configuration
1143. Finds running container for `myapp:latest`
1154. Proxies request to container's exposed port
1165. Returns response to client
117
118```
119Client ─> Gordon Proxy ─> Container
120          (port 80)       (exposed port)
121```
122
123## Deployment Flow
124
125When you push an image:
126
127```bash
128docker push registry.mydomain.com/myapp:latest
129```
130
1311. Gordon receives the image
1322. Checks routes for any that use `myapp:latest`
1333. Deploys new container for each matching route
1344. Updates proxy to route traffic to new container
1355. Stops old container
136
137## Route Changes
138
139Route changes in the config file are hot-reloaded automatically:
140
1411. Edit `[routes]` in `gordon.toml`
1422. Save the file
1433. Gordon reloads the updated routes and proxy config
144
145Legacy `http://...` route keys are still read here for backward compatibility and rewritten the next time Gordon saves the config.
146
147You can still manage routes with the API or CLI if you prefer live mutations:
148
149```bash
150gordon routes add newapp.mydomain.com newapp:latest
151gordon routes add app.mydomain.com myapp:v2.2.0
152gordon routes remove oldapp.mydomain.com
153```
154
155## Examples
156
157### Development Setup
158
159```toml
160[routes]
161"dev-app.example.com" = { image = "myapp:latest" }
162"dev-api.example.com" = { image = "myapi:latest" }
163```
164
165Add to `/etc/hosts`:
166
167```text
168127.0.0.1  dev-app.example.com dev-api.example.com registry.example.com
169```
170
171### Production Setup
172
173```toml
174[routes]
175"app.company.com" = { image = "company-app:v2.1.0" }
176"api.company.com" = { image = "company-api:v1.5.2" }
177"admin.company.com" = { image = "admin-panel:v1.0.1" }
178"docs.company.com" = { image = "company-docs:latest" }
179```
180
181### Multi-Tenant SaaS
182
183```toml
184[routes]
185# Platform services
186"app.saas-platform.com" = { image = "saas-frontend:v2.1.0" }
187"api.saas-platform.com" = { image = "saas-api:v3.2.1" }
188
189# Customer subdomains
190"acme.saas-platform.com" = { image = "saas-app:v2.1.0" }
191"beta.saas-platform.com" = { image = "saas-app:v2.1.0" }
192
193# Customer custom domains
194"portal.acme-corp.com" = { image = "saas-app:v2.1.0" }
195```
196
197## External Services
198
199For non-containerized services (databases, legacy apps, etc.), see [External Routes](./external-routes.md).
200
201## Related
202
203- [Configuration Overview](./index.md)
204- [Auto Route](./auto-route.md)
205- [Attachments](./attachments.md)
206- [External Routes](./external-routes.md)

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