v3.3.2 9697f9d

README.md RawHistoryFolder

Gordon

[License: GPL-3.0]

Self-hosted container deployment. Push an image, declare an app, deploy it.


What is Gordon?

Gordon is a private image container registry, an app runtime, and a reverse proxy for your VPS.

The flow is explicit: you build an image locally, push it to your registry then declare the app in a standalone TOML file, apply it, deploy and it's live.

Quick Start

# Install the latest stable release to ~/.local/bin
curl -fsSL https://bnema.dev/gordon/install | sh

# Start the server (restart your shell first if the installer updated PATH)
gordon serve

See the installation guide for more.

Config is created at ~/.config/gordon/gordon.toml. See the Getting Started guide for full setup.

Deploy with the CLI

Example of the flow :

# Push the image (OCI transfer only, never deploys)
gordon images push myapp --build --remote prod

# Declare the app (blog.toml references the pushed tag)
gordon apps apply --file blog.toml --remote prod

# Activate it
gordon apps deploy blog --remote prod

# Check status
gordon daemon status
gordon apps status blog --remote prod

Minimal app file (blog.toml):

name = "blog"

[services.web]
image = "gordon.mydomain.com/myapp:v1.2.0"

[[services.web.http]]
host = "blog.mydomain.com"
port = 3000

Manage lifecycle and secrets — all from the command line:

gordon apps restart blog --remote prod   # Restart from pinned digests
gordon apps stop blog --remote prod      # Stop, preserve all data
gordon apps secrets set blog --service web DATABASE_URL=... --remote prod

Deploy from CI/CD

Push to Gordon's registry from any CI pipeline, then apply and deploy with the CLI. Push never triggers a deploy by itself.

GitHub Actions

- uses: bnema/gordon/.github/actions/deploy@main
  with:
    registry: registry.mydomain.com
    username: ${{ secrets.GORDON_USERNAME }}
    password: ${{ secrets.GORDON_TOKEN }}

See the Deploy Action README for multi-platform builds, monorepo support, and all available options.

Docker CLI + Gordon CLI

docker login gordon.mydomain.com
docker build -t gordon.mydomain.com/myapp:v1.0.0 .
docker push gordon.mydomain.com/myapp:v1.0.0
# Then, with the Gordon binary:
gordon apps apply --file blog.toml --remote prod
gordon apps deploy blog --remote prod

CLI Commands

Server

Command Description
gordon serve Start the Gordon server
gordon daemon status Show server and app fleet status
gordon daemon logs Show Gordon process logs
gordon daemon reload Reload installation configuration
gordon daemon config show Display installation configuration

Applications

Command Description
gordon apps apply --file FILE Validate and persist an app manifest
gordon apps deploy APP Activate an app revision
gordon apps list List applications
gordon apps show APP Show desired and active state
gordon apps status APP Show effective vs observed state
gordon apps logs APP Show logs for an app service
gordon apps restart APP Restart from pinned digests
gordon apps stop APP Stop, preserve all data
gordon apps start APP Start a stopped app
gordon apps remove APP Remove workloads (volumes/secrets retained)

Images & Registry

Command Description
gordon images push [image] Tag and push an image (never deploys)
gordon images list List runtime and registry images
gordon images prune Clean up dangling images and old tags
gordon images tags <repo> List registry tags for a repository

Secrets

Command Description
gordon apps secrets list APP List app secret names
gordon apps secrets set APP --service SVC KEY=VAL Set app secret values

Remotes & Auth

Command Description
gordon remotes list List remote Gordon endpoints
gordon remotes add <name> <url> Add a remote
gordon remotes use <name> Set the active remote
gordon auth login Authenticate to a remote
gordon auth token generate Generate a JWT token

Features

  • Private Docker/Podman registry on your VPS
  • Declarative apps: one TOML file per app, explicit apply then deploy
  • Domain-to-container routing through a smart TCP edge reverse proxy
  • Zero-downtime replacement of stateless TCP/HTTP services (start, verify readiness, switch traffic, stop the old one); services with volumes, binds, devices, or UDP interfaces are replaced sequentially
  • Remote CLI management (daemon is the sole writer)
  • Declarative per-service volumes, retained across lifecycle operations
  • Per-service secrets in pass, app-wide public env in the manifest
  • Per-app private networks plus opt-in shared networks
  • Single binary

[!NOTE] Gordon exposes public traffic through entrypoints such as [entrypoints.edge] with protocol = "smart_tcp". It can terminate TLS via static certificates, public ACME certificates, or its internal CA. Cloudflare and upstream reverse proxies are optional deployment choices, not requirements. Use Gordon's ownership-aware volume commands; runtime commands such as docker volume prune bypass Gordon's retention checks.

Documentation

Full documentation at bnema.dev/gordon

  • Docs — Installation, configuration, CLI reference
  • Wiki — Tutorials, guides, and examples

Community

License

GPL-3.0 — Use freely, contribute back.

source
1# Gordon
2
3[![License: GPL-3.0](https://img.shields.io/badge/License-GPL%203.0-blue.svg)](https://www.gnu.org/licenses/gpl-3.0)
4
5Self-hosted container deployment. Push an image, declare an app, deploy it.
6
7- Website: https://bnema.dev/gordon
8- Documentation: [Docs](https://bnema.dev/gordon/docs) | [Wiki](https://bnema.dev/gordon/wiki)
9- Discuss: [GitHub Discussions](https://github.com/bnema/gordon/discussions)
10
11---
12
13## What is Gordon?
14
15Gordon is a private image container registry, an app runtime, and a reverse proxy for your VPS.
16
17The flow is explicit: you build an image locally, push it to your registry then declare the app in a standalone TOML file, apply it, deploy and it's live.
18
19## Quick Start
20
21```bash
22# Install the latest stable release to ~/.local/bin
23curl -fsSL https://bnema.dev/gordon/install | sh
24
25# Start the server (restart your shell first if the installer updated PATH)
26gordon serve
27```
28See the [installation guide](https://bnema.dev/gordon/docs/installation#choosing-an-install-channel) for more.
29
30Config is created at `~/.config/gordon/gordon.toml`. See the [Getting Started guide](https://bnema.dev/gordon/docs/getting-started) for full setup.
31
32## Deploy with the CLI
33
34Example of the flow :
35
36```bash
37# Push the image (OCI transfer only, never deploys)
38gordon images push myapp --build --remote prod
39
40# Declare the app (blog.toml references the pushed tag)
41gordon apps apply --file blog.toml --remote prod
42
43# Activate it
44gordon apps deploy blog --remote prod
45
46# Check status
47gordon daemon status
48gordon apps status blog --remote prod
49```
50
51Minimal app file (`blog.toml`):
52
53```toml
54name = "blog"
55
56[services.web]
57image = "gordon.mydomain.com/myapp:v1.2.0"
58
59[[services.web.http]]
60host = "blog.mydomain.com"
61port = 3000
62```
63
64Manage lifecycle and secrets — all from the command line:
65
66```bash
67gordon apps restart blog --remote prod   # Restart from pinned digests
68gordon apps stop blog --remote prod      # Stop, preserve all data
69gordon apps secrets set blog --service web DATABASE_URL=... --remote prod
70```
71
72## Deploy from CI/CD
73
74Push to Gordon's registry from any CI pipeline, then apply and deploy with the CLI. Push never triggers a deploy by itself.
75
76### GitHub Actions
77
78```yaml
79- uses: bnema/gordon/.github/actions/deploy@main
80  with:
81    registry: registry.mydomain.com
82    username: ${{ secrets.GORDON_USERNAME }}
83    password: ${{ secrets.GORDON_TOKEN }}
84```
85
86See the [Deploy Action README](.github/actions/deploy/README.md) for multi-platform builds, monorepo support, and all available options.
87
88### Docker CLI + Gordon CLI
89
90```bash
91docker login gordon.mydomain.com
92docker build -t gordon.mydomain.com/myapp:v1.0.0 .
93docker push gordon.mydomain.com/myapp:v1.0.0
94# Then, with the Gordon binary:
95gordon apps apply --file blog.toml --remote prod
96gordon apps deploy blog --remote prod
97```
98
99## CLI Commands
100
101### Server
102
103| Command | Description |
104|---------|-------------|
105| `gordon serve` | Start the Gordon server |
106| `gordon daemon status` | Show server and app fleet status |
107| `gordon daemon logs` | Show Gordon process logs |
108| `gordon daemon reload` | Reload installation configuration |
109| `gordon daemon config show` | Display installation configuration |
110
111### Applications
112
113| Command | Description |
114|---------|-------------|
115| `gordon apps apply --file FILE` | Validate and persist an app manifest |
116| `gordon apps deploy APP` | Activate an app revision |
117| `gordon apps list` | List applications |
118| `gordon apps show APP` | Show desired and active state |
119| `gordon apps status APP` | Show effective vs observed state |
120| `gordon apps logs APP` | Show logs for an app service |
121| `gordon apps restart APP` | Restart from pinned digests |
122| `gordon apps stop APP` | Stop, preserve all data |
123| `gordon apps start APP` | Start a stopped app |
124| `gordon apps remove APP` | Remove workloads (volumes/secrets retained) |
125
126### Images & Registry
127
128| Command | Description |
129|---------|-------------|
130| `gordon images push [image]` | Tag and push an image (never deploys) |
131| `gordon images list` | List runtime and registry images |
132| `gordon images prune` | Clean up dangling images and old tags |
133| `gordon images tags <repo>` | List registry tags for a repository |
134
135### Secrets
136
137| Command | Description |
138|---------|-------------|
139| `gordon apps secrets list APP` | List app secret names |
140| `gordon apps secrets set APP --service SVC KEY=VAL` | Set app secret values |
141
142### Remotes & Auth
143
144| Command | Description |
145|---------|-------------|
146| `gordon remotes list` | List remote Gordon endpoints |
147| `gordon remotes add <name> <url>` | Add a remote |
148| `gordon remotes use <name>` | Set the active remote |
149| `gordon auth login` | Authenticate to a remote |
150| `gordon auth token generate` | Generate a JWT token |
151
152## Features
153
154- Private Docker/Podman registry on your VPS
155- Declarative apps: one TOML file per app, explicit apply then deploy
156- Domain-to-container routing through a smart TCP edge reverse proxy
157- Zero-downtime replacement of stateless TCP/HTTP services (start, verify readiness, switch traffic, stop the old one); services with volumes, binds, devices, or UDP interfaces are replaced sequentially
158- Remote CLI management (daemon is the sole writer)
159- Declarative per-service volumes, retained across lifecycle operations
160- Per-service secrets in pass, app-wide public env in the manifest
161- Per-app private networks plus opt-in shared networks
162- Single binary
163
164> [!NOTE]
165> Gordon exposes public traffic through entrypoints such as `[entrypoints.edge]` with `protocol = "smart_tcp"`. It can terminate TLS via static certificates, public ACME certificates, or its internal CA. Cloudflare and upstream reverse proxies are optional deployment choices, not requirements. Use Gordon's ownership-aware volume commands; runtime commands such as `docker volume prune` bypass Gordon's retention checks.
166
167## Documentation
168
169Full documentation at **[bnema.dev/gordon](https://bnema.dev/gordon)**
170
171- [Docs](https://bnema.dev/gordon/docs) — Installation, configuration, CLI reference
172- [Wiki](https://bnema.dev/gordon/wiki) — Tutorials, guides, and examples
173
174## Community
175
176- [Report bugs](https://github.com/bnema/gordon/issues)
177- [Discussions](https://github.com/bnema/gordon/discussions)
178- [Submit PRs](https://github.com/bnema/gordon/pulls)
179
180## License
181
182GPL-3.0 — Use freely, contribute back.

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