v2.31.1 f37fe67

rollback.md RawHistoryFolder

Rollback

Roll back to previous versions when deployments fail.

gordon pin is the built-in rollback and roll-forward workflow for route images:

gordon pin app.example.com
gordon pin app.example.com --tag v2.30.1
gordon pin list app.example.com

Use it when the target image already exists in the Gordon registry and you want Gordon to update the route and redeploy it for you.

Rollback Strategies

1. Config-Based Rollback

Update the route to point to the previous version:

# Current (broken)
[routes]
"app.mydomain.com" = "myapp:v2.1.0"

# Rollback to previous
[routes]
"app.mydomain.com" = "myapp:v2.0.0"

Then reload:

gordon reload

2. Push Previous Version

Re-push the previous image with the latest tag:

docker pull registry.mydomain.com/myapp:v2.0.0
docker tag registry.mydomain.com/myapp:v2.0.0 registry.mydomain.com/myapp:latest
docker push registry.mydomain.com/myapp:latest

3. Manifest-Based Rollback

Use OCI manifest annotations for version control:

# Rollback to v2.0.0
export VERSION=v2.0.0
podman manifest create myapp:latest --amend
podman manifest add myapp:latest registry.mydomain.com/myapp:$VERSION
podman manifest annotate myapp:latest --annotation version=$VERSION registry.mydomain.com/myapp:$VERSION
podman manifest push myapp:latest registry.mydomain.com/myapp:latest

Version Management

Keep Previous Versions

Always push versioned tags alongside latest:

VERSION=$(git describe --tags)
docker tag myapp registry.mydomain.com/myapp:$VERSION
docker tag myapp registry.mydomain.com/myapp:latest
docker push registry.mydomain.com/myapp:$VERSION
docker push registry.mydomain.com/myapp:latest

Semantic Versioning

Use semantic versions for clear rollback targets:

v2.1.0  ← Current (broken)
v2.0.0  ← Rollback target
v1.9.0  ← Older stable

Git SHA Tags

Tag with commit SHA for precise rollbacks:

# Deploy
SHA=$(git rev-parse --short HEAD)
docker push registry.mydomain.com/myapp:$SHA

# Rollback to specific commit
docker pull registry.mydomain.com/myapp:abc1234
docker tag registry.mydomain.com/myapp:abc1234 registry.mydomain.com/myapp:latest
docker push registry.mydomain.com/myapp:latest

Rollback Workflow

Quick Rollback

# 1. Identify last working version
docker image ls registry.mydomain.com/myapp

# 2. Tag as latest
docker tag registry.mydomain.com/myapp:v2.0.0 registry.mydomain.com/myapp:latest

# 3. Push
docker push registry.mydomain.com/myapp:latest

Config Rollback

# 1. Edit config
vim ~/.config/gordon/gordon.toml

# 2. Change version
# "app.mydomain.com" = "myapp:v2.0.0"

# 3. Reload
gordon reload

Automated Rollback

GitHub Actions

Add rollback capability to your workflow:

name: Rollback

on:
  workflow_dispatch:
    inputs:
      version:
        description: 'Version to rollback to (e.g., v2.0.0)'
        required: true

jobs:
  rollback:
    runs-on: ubuntu-latest
    steps:
      - name: Login to Registry
        env:
          GORDON_TOKEN: ${{ secrets.GORDON_TOKEN }}
          GORDON_USERNAME: ${{ secrets.GORDON_USERNAME }}
          GORDON_REGISTRY: ${{ secrets.GORDON_REGISTRY }}
        run: printf '%s' "$GORDON_TOKEN" | docker login -u "$GORDON_USERNAME" --password-stdin "$GORDON_REGISTRY"

      - name: Rollback
        env:
          GORDON_REGISTRY: ${{ secrets.GORDON_REGISTRY }}
          VERSION: ${{ inputs.version }}
        run: |
          [[ "$VERSION" =~ ^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$ ]] || exit 1
          REPOSITORY="$GORDON_REGISTRY/myapp"
          SOURCE_IMAGE="$REPOSITORY:$VERSION"
          LATEST_IMAGE="$REPOSITORY:latest"
          SOURCE_DIGEST="$(docker buildx imagetools inspect "$SOURCE_IMAGE" --format '{{json .Manifest}}' | jq -er '.digest')"
          IMMUTABLE_IMAGE="$REPOSITORY@$SOURCE_DIGEST"
          docker buildx imagetools create --tag "$LATEST_IMAGE" "$IMMUTABLE_IMAGE"
          LATEST_DIGEST="$(docker buildx imagetools inspect "$LATEST_IMAGE" --format '{{json .Manifest}}' | jq -er '.digest')"
          [[ "$LATEST_DIGEST" == "$SOURCE_DIGEST" ]] || {
            echo "rollback verification failed: latest resolved to $LATEST_DIGEST, expected $SOURCE_DIGEST" >&2
            exit 1
          }

      - name: Summary
        env:
          VERSION: ${{ inputs.version }}
        run: |
          echo "## Rollback Complete" >> "$GITHUB_STEP_SUMMARY"
          printf 'Rolled back to version: %s\n' "$VERSION" >> "$GITHUB_STEP_SUMMARY"

Rollback Script

Create a local rollback script:

#!/bin/bash
# rollback.sh

REGISTRY="registry.mydomain.com"
IMAGE="myapp"
VERSION=$1

if [ -z "$VERSION" ]; then
  echo "Usage: ./rollback.sh <version>"
  echo "Available versions:"
  docker image ls "$REGISTRY/$IMAGE" --format "{{.Tag}}"
  exit 1
fi

echo "Rolling back to $IMAGE:$VERSION..."
docker pull "$REGISTRY/$IMAGE:$VERSION"
docker tag "$REGISTRY/$IMAGE:$VERSION" "$REGISTRY/$IMAGE:latest"
docker push "$REGISTRY/$IMAGE:latest"
echo "Rollback complete!"

Verifying Rollback

After rollback:

# Check container is running correct version
docker inspect gordon-app-mydomain-com | grep Image

# Check application responds
curl -I https://app.mydomain.com

# Check logs
gordon logs -f

Best Practices

  1. Always tag versions - Don't rely solely on latest
  2. Keep N previous versions - Maintain rollback options
  3. Test before deploy - Reduce need for rollbacks
  4. Document known-good versions - Track stable releases
  5. Automate rollback - Reduce time to recovery
source
1# Rollback
2
3Roll back to previous versions when deployments fail.
4
5## Recommended: Use `gordon pin`
6
7`gordon pin` is the built-in rollback and roll-forward workflow for route images:
8
9```bash
10gordon pin app.example.com
11gordon pin app.example.com --tag v2.30.1
12gordon pin list app.example.com
13```
14
15Use it when the target image already exists in the Gordon registry and you want Gordon to update the route and redeploy it for you.
16
17## Rollback Strategies
18
19### 1. Config-Based Rollback
20
21Update the route to point to the previous version:
22
23```toml
24# Current (broken)
25[routes]
26"app.mydomain.com" = "myapp:v2.1.0"
27
28# Rollback to previous
29[routes]
30"app.mydomain.com" = "myapp:v2.0.0"
31```
32
33Then reload:
34
35```bash
36gordon reload
37```
38
39### 2. Push Previous Version
40
41Re-push the previous image with the `latest` tag:
42
43```bash
44docker pull registry.mydomain.com/myapp:v2.0.0
45docker tag registry.mydomain.com/myapp:v2.0.0 registry.mydomain.com/myapp:latest
46docker push registry.mydomain.com/myapp:latest
47```
48
49### 3. Manifest-Based Rollback
50
51Use OCI manifest annotations for version control:
52
53```bash
54# Rollback to v2.0.0
55export VERSION=v2.0.0
56podman manifest create myapp:latest --amend
57podman manifest add myapp:latest registry.mydomain.com/myapp:$VERSION
58podman manifest annotate myapp:latest --annotation version=$VERSION registry.mydomain.com/myapp:$VERSION
59podman manifest push myapp:latest registry.mydomain.com/myapp:latest
60```
61
62## Version Management
63
64### Keep Previous Versions
65
66Always push versioned tags alongside `latest`:
67
68```bash
69VERSION=$(git describe --tags)
70docker tag myapp registry.mydomain.com/myapp:$VERSION
71docker tag myapp registry.mydomain.com/myapp:latest
72docker push registry.mydomain.com/myapp:$VERSION
73docker push registry.mydomain.com/myapp:latest
74```
75
76### Semantic Versioning
77
78Use semantic versions for clear rollback targets:
79
80```
81v2.1.0  ← Current (broken)
82v2.0.0  ← Rollback target
83v1.9.0  ← Older stable
84```
85
86### Git SHA Tags
87
88Tag with commit SHA for precise rollbacks:
89
90```bash
91# Deploy
92SHA=$(git rev-parse --short HEAD)
93docker push registry.mydomain.com/myapp:$SHA
94
95# Rollback to specific commit
96docker pull registry.mydomain.com/myapp:abc1234
97docker tag registry.mydomain.com/myapp:abc1234 registry.mydomain.com/myapp:latest
98docker push registry.mydomain.com/myapp:latest
99```
100
101## Rollback Workflow
102
103### Quick Rollback
104
105```bash
106# 1. Identify last working version
107docker image ls registry.mydomain.com/myapp
108
109# 2. Tag as latest
110docker tag registry.mydomain.com/myapp:v2.0.0 registry.mydomain.com/myapp:latest
111
112# 3. Push
113docker push registry.mydomain.com/myapp:latest
114```
115
116### Config Rollback
117
118```bash
119# 1. Edit config
120vim ~/.config/gordon/gordon.toml
121
122# 2. Change version
123# "app.mydomain.com" = "myapp:v2.0.0"
124
125# 3. Reload
126gordon reload
127```
128
129## Automated Rollback
130
131### GitHub Actions
132
133Add rollback capability to your workflow:
134
135```yaml
136name: Rollback
137
138on:
139  workflow_dispatch:
140    inputs:
141      version:
142        description: 'Version to rollback to (e.g., v2.0.0)'
143        required: true
144
145jobs:
146  rollback:
147    runs-on: ubuntu-latest
148    steps:
149      - name: Login to Registry
150        env:
151          GORDON_TOKEN: ${{ secrets.GORDON_TOKEN }}
152          GORDON_USERNAME: ${{ secrets.GORDON_USERNAME }}
153          GORDON_REGISTRY: ${{ secrets.GORDON_REGISTRY }}
154        run: printf '%s' "$GORDON_TOKEN" | docker login -u "$GORDON_USERNAME" --password-stdin "$GORDON_REGISTRY"
155
156      - name: Rollback
157        env:
158          GORDON_REGISTRY: ${{ secrets.GORDON_REGISTRY }}
159          VERSION: ${{ inputs.version }}
160        run: |
161          [[ "$VERSION" =~ ^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$ ]] || exit 1
162          REPOSITORY="$GORDON_REGISTRY/myapp"
163          SOURCE_IMAGE="$REPOSITORY:$VERSION"
164          LATEST_IMAGE="$REPOSITORY:latest"
165          SOURCE_DIGEST="$(docker buildx imagetools inspect "$SOURCE_IMAGE" --format '{{json .Manifest}}' | jq -er '.digest')"
166          IMMUTABLE_IMAGE="$REPOSITORY@$SOURCE_DIGEST"
167          docker buildx imagetools create --tag "$LATEST_IMAGE" "$IMMUTABLE_IMAGE"
168          LATEST_DIGEST="$(docker buildx imagetools inspect "$LATEST_IMAGE" --format '{{json .Manifest}}' | jq -er '.digest')"
169          [[ "$LATEST_DIGEST" == "$SOURCE_DIGEST" ]] || {
170            echo "rollback verification failed: latest resolved to $LATEST_DIGEST, expected $SOURCE_DIGEST" >&2
171            exit 1
172          }
173
174      - name: Summary
175        env:
176          VERSION: ${{ inputs.version }}
177        run: |
178          echo "## Rollback Complete" >> "$GITHUB_STEP_SUMMARY"
179          printf 'Rolled back to version: %s\n' "$VERSION" >> "$GITHUB_STEP_SUMMARY"
180```
181
182### Rollback Script
183
184Create a local rollback script:
185
186```bash
187#!/bin/bash
188# rollback.sh
189
190REGISTRY="registry.mydomain.com"
191IMAGE="myapp"
192VERSION=$1
193
194if [ -z "$VERSION" ]; then
195  echo "Usage: ./rollback.sh <version>"
196  echo "Available versions:"
197  docker image ls "$REGISTRY/$IMAGE" --format "{{.Tag}}"
198  exit 1
199fi
200
201echo "Rolling back to $IMAGE:$VERSION..."
202docker pull "$REGISTRY/$IMAGE:$VERSION"
203docker tag "$REGISTRY/$IMAGE:$VERSION" "$REGISTRY/$IMAGE:latest"
204docker push "$REGISTRY/$IMAGE:latest"
205echo "Rollback complete!"
206```
207
208## Verifying Rollback
209
210After rollback:
211
212```bash
213# Check container is running correct version
214docker inspect gordon-app-mydomain-com | grep Image
215
216# Check application responds
217curl -I https://app.mydomain.com
218
219# Check logs
220gordon logs -f
221```
222
223## Best Practices
224
2251. **Always tag versions** - Don't rely solely on `latest`
2262. **Keep N previous versions** - Maintain rollback options
2273. **Test before deploy** - Reduce need for rollbacks
2284. **Document known-good versions** - Track stable releases
2295. **Automate rollback** - Reduce time to recovery
230
231## Related
232
233- [Deployment Overview](./index.md)
234- [GitHub Actions](./github-actions.md)
235- [Routes Configuration](../config/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