v2.31.0 e02f654

index.md RawHistoryFolder

Deployment Overview

Gordon deploys containers when you push images to its built-in registry. Three deployment methods are available depending on your workflow and infrastructure.

gordon push --build --remote is the simplest way to build, push, and deploy from CI/CD pipelines.

  • Single command: build + push + deploy
  • Single secret (GORDON_TOKEN): auto-exchanges for a short-lived registry token
  • Auto-detects version from CI environment ($GITHUB_REF, $CI_COMMIT_TAG, $BUILD_SOURCEBRANCH, or git describe)
  • Chunked uploads (50MB chunks) — works behind Cloudflare and restrictive proxies
gordon push --build --remote https://gordon.example.com --no-confirm

All Deployment Methods

Method Best For Secrets Needed Registry Access Deploy Control
gordon push (Recommended) CI/CD pipelines 1 (GORDON_TOKEN) Via gordon domain (HTTPS) Explicit (CLI-triggered)
docker push Simple setups, existing Docker workflows 2 (username + token) Via gordon domain (HTTPS) Automatic (event-based)
Docker labels + auto-route GitOps, zero-config deploys 2 (username + token) Via gordon domain (HTTPS) Automatic (label-driven)

The Gordon CLI handles authentication, image building, and deployment in a single step.

  • Single token handles everything: admin API access + registry auth via automatic token exchange
  • Version tag auto-detected from $GITHUB_REF, $CI_COMMIT_TAG, $BUILD_SOURCEBRANCH, or git describe
  • Use --no-deploy for push-only workflows (useful for staging images without triggering deployment)
  • Requires the Gordon binary on the CI runner
# Build, push, and deploy
gordon push --build --remote https://gordon.example.com --no-confirm

# Push only, no deploy
gordon push --build --remote https://gordon.example.com --no-deploy --no-confirm

Method 2: docker push

Standard Docker workflow — no Gordon binary required on the runner.

  • Use docker login, docker build, and docker push as usual
  • Gordon auto-deploys when it receives the image (event-based, no explicit trigger needed)
  • No Gordon binary needed on the CI runner
  • Registry endpoint is gordon.example.com (not a separate registry host)
echo "$GORDON_TOKEN" | docker login -u ci-bot --password-stdin gordon.example.com
docker build -t gordon.example.com/myapp:v1.2.0 .
docker push gordon.example.com/myapp:v1.2.0

Method 3: Docker labels + auto-route

Add a gordon.domain label to your image and Gordon creates the route automatically on push.

  • Add gordon.domain=app.example.com label to your Dockerfile
  • Push image — Gordon creates or updates the route without manual config
  • Gated by the auto_route_allowed_domains allowlist in gordon.toml
  • Best for GitOps workflows where routes are defined alongside the application
LABEL gordon.domain="app.example.com"

See Auto-Route for configuration details.

Registry Access

Gordon's registry is served through the main gordon domain over HTTPS on port 443. The internal registry port (5000) is never exposed externally. All push methods use https://gordon.example.com/v2/....

Network Topologies

Setup Configuration Use Case
Public (default) auth.enabled = true Hosted CI runners (GitHub Actions, GitLab CI)
Tailscale only registry_allowed_ips = ["100.64.0.0/10"] Self-hosted runners in Tailnet
Localhost only auth.enabled = false Local development, single-machine deploys

Token Setup

See the examples below for the right scopes for each workflow.

# Minimum scope for gordon push — route lookup + registry push
# Server auto-deploys when it receives the image
gordon auth token generate \
  --subject ci-bot \
  --scopes "push,pull,admin:routes:read" \
  --expiry 90d

# With explicit CLI-managed deploy (adds config:write for deploy control)
gordon auth token generate \
  --subject ci-bot \
  --scopes "push,pull,admin:routes:read,admin:config:write" \
  --expiry 90d

# Scoped to a specific repository
gordon auth token generate \
  --subject ci-bot \
  --repo myapp \
  --scopes "push,pull,admin:routes:read" \
  --expiry 90d

# For docker push — registry scopes only
gordon auth token generate \
  --subject ci-bot \
  --scopes "push,pull" \
  --expiry 90d

Set the generated token as GORDON_TOKEN in your CI environment.

Version Strategies

Latest Tag

Always deploy the most recent build:

docker tag myapp gordon.example.com/myapp:latest
docker push gordon.example.com/myapp:latest
[routes]
"app.example.com" = "myapp:latest"

Semantic Versioning

Pin routes to specific versions and update config to roll forward:

docker tag myapp gordon.example.com/myapp:v2.1.0
docker push gordon.example.com/myapp:v2.1.0
[routes]
"app.example.com" = "myapp:v2.1.0"

To deploy a new version, update the tag in gordon.toml and push the new image.

Git SHA Tags

Tag with commit hash for full traceability:

VERSION=$(git rev-parse --short HEAD)
docker tag myapp gordon.example.com/myapp:$VERSION
docker push gordon.example.com/myapp:$VERSION

Zero-Downtime Deployment

Gordon performs zero-downtime deployments by default:

  1. New container starts while the old one is still running
  2. Health check waits for the new container to become ready
  3. Traffic switches to the new container
  4. Old container stops after traffic moves
Timeline ─────────────────────────────────────────>

Old Container:  [═══════════════════]
                                    ↓ stop
New Container:           [═════════════════════════>
                         ↑ start    ↑ traffic routed
source
1# Deployment Overview
2
3Gordon deploys containers when you push images to its built-in registry. Three deployment methods are available depending on your workflow and infrastructure.
4
5## Recommended: gordon push
6
7`gordon push --build --remote` is the simplest way to build, push, and deploy from CI/CD pipelines.
8
9- Single command: build + push + deploy
10- Single secret (`GORDON_TOKEN`): auto-exchanges for a short-lived registry token
11- Auto-detects version from CI environment (`$GITHUB_REF`, `$CI_COMMIT_TAG`, `$BUILD_SOURCEBRANCH`, or `git describe`)
12- Chunked uploads (50MB chunks) — works behind Cloudflare and restrictive proxies
13
14```bash
15gordon push --build --remote https://gordon.example.com --no-confirm
16```
17
18## All Deployment Methods
19
20| Method | Best For | Secrets Needed | Registry Access | Deploy Control |
21|--------|----------|----------------|-----------------|----------------|
22| `gordon push` (Recommended) | CI/CD pipelines | 1 (`GORDON_TOKEN`) | Via gordon domain (HTTPS) | Explicit (CLI-triggered) |
23| `docker push` | Simple setups, existing Docker workflows | 2 (`username` + `token`) | Via gordon domain (HTTPS) | Automatic (event-based) |
24| Docker labels + auto-route | GitOps, zero-config deploys | 2 (`username` + `token`) | Via gordon domain (HTTPS) | Automatic (label-driven) |
25
26### Method 1: gordon push (Recommended)
27
28The Gordon CLI handles authentication, image building, and deployment in a single step.
29
30- Single token handles everything: admin API access + registry auth via automatic token exchange
31- Version tag auto-detected from `$GITHUB_REF`, `$CI_COMMIT_TAG`, `$BUILD_SOURCEBRANCH`, or `git describe`
32- Use `--no-deploy` for push-only workflows (useful for staging images without triggering deployment)
33- Requires the Gordon binary on the CI runner
34
35```bash
36# Build, push, and deploy
37gordon push --build --remote https://gordon.example.com --no-confirm
38
39# Push only, no deploy
40gordon push --build --remote https://gordon.example.com --no-deploy --no-confirm
41```
42
43### Method 2: docker push
44
45Standard Docker workflow — no Gordon binary required on the runner.
46
47- Use `docker login`, `docker build`, and `docker push` as usual
48- Gordon auto-deploys when it receives the image (event-based, no explicit trigger needed)
49- No Gordon binary needed on the CI runner
50- Registry endpoint is `gordon.example.com` (not a separate registry host)
51
52```bash
53echo "$GORDON_TOKEN" | docker login -u ci-bot --password-stdin gordon.example.com
54docker build -t gordon.example.com/myapp:v1.2.0 .
55docker push gordon.example.com/myapp:v1.2.0
56```
57
58### Method 3: Docker labels + auto-route
59
60Add a `gordon.domain` label to your image and Gordon creates the route automatically on push.
61
62- Add `gordon.domain=app.example.com` label to your Dockerfile
63- Push image — Gordon creates or updates the route without manual config
64- Gated by the `auto_route_allowed_domains` allowlist in `gordon.toml`
65- Best for GitOps workflows where routes are defined alongside the application
66
67```dockerfile
68LABEL gordon.domain="app.example.com"
69```
70
71See [Auto-Route](../config/auto-route.md) for configuration details.
72
73## Registry Access
74
75Gordon's registry is served through the main gordon domain over HTTPS on port 443. The internal registry port (5000) is never exposed externally. All push methods use `https://gordon.example.com/v2/...`.
76
77### Network Topologies
78
79| Setup | Configuration | Use Case |
80|-------|--------------|----------|
81| Public (default) | `auth.enabled = true` | Hosted CI runners (GitHub Actions, GitLab CI) |
82| Tailscale only | `registry_allowed_ips = ["100.64.0.0/10"]` | Self-hosted runners in Tailnet |
83| Localhost only | `auth.enabled = false` | Local development, single-machine deploys |
84
85## Token Setup
86
87See the examples below for the right scopes for each workflow.
88
89```bash
90# Minimum scope for gordon push — route lookup + registry push
91# Server auto-deploys when it receives the image
92gordon auth token generate \
93  --subject ci-bot \
94  --scopes "push,pull,admin:routes:read" \
95  --expiry 90d
96
97# With explicit CLI-managed deploy (adds config:write for deploy control)
98gordon auth token generate \
99  --subject ci-bot \
100  --scopes "push,pull,admin:routes:read,admin:config:write" \
101  --expiry 90d
102
103# Scoped to a specific repository
104gordon auth token generate \
105  --subject ci-bot \
106  --repo myapp \
107  --scopes "push,pull,admin:routes:read" \
108  --expiry 90d
109
110# For docker push — registry scopes only
111gordon auth token generate \
112  --subject ci-bot \
113  --scopes "push,pull" \
114  --expiry 90d
115```
116
117Set the generated token as `GORDON_TOKEN` in your CI environment.
118
119## Version Strategies
120
121### Latest Tag
122
123Always deploy the most recent build:
124
125```bash
126docker tag myapp gordon.example.com/myapp:latest
127docker push gordon.example.com/myapp:latest
128```
129
130```toml
131[routes]
132"app.example.com" = "myapp:latest"
133```
134
135### Semantic Versioning
136
137Pin routes to specific versions and update config to roll forward:
138
139```bash
140docker tag myapp gordon.example.com/myapp:v2.1.0
141docker push gordon.example.com/myapp:v2.1.0
142```
143
144```toml
145[routes]
146"app.example.com" = "myapp:v2.1.0"
147```
148
149To deploy a new version, update the tag in `gordon.toml` and push the new image.
150
151### Git SHA Tags
152
153Tag with commit hash for full traceability:
154
155```bash
156VERSION=$(git rev-parse --short HEAD)
157docker tag myapp gordon.example.com/myapp:$VERSION
158docker push gordon.example.com/myapp:$VERSION
159```
160
161## Zero-Downtime Deployment
162
163Gordon performs zero-downtime deployments by default:
164
1651. **New container starts** while the old one is still running
1662. **Health check** waits for the new container to become ready
1673. **Traffic switches** to the new container
1684. **Old container stops** after traffic moves
169
170```
171Timeline ─────────────────────────────────────────>
172
173Old Container:  [═══════════════════]
174                                    ↓ stop
175New Container:           [═════════════════════════>
176                         ↑ start    ↑ traffic routed
177```
178
179## Related
180
181- [GitHub Actions](./github-actions.md)
182- [GitLab CI](./gitlab-ci.md)
183- [Generic CI](./generic-ci.md)
184- [Rollback](./rollback.md)
185- [Routes Configuration](../config/routes.md)
186- [Authentication](../config/auth.md)
187- [Auto-Route](../config/auto-route.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