netOrk deploy
Deploys netOrk to one or more Docker hosts in parallel, from pre-built images in a container registry.
The machine running the deploy needs this repository, ssh, and a deploy.env. It does
not need a netOrk checkout. Each server pulls the images itself. The compose files come
out of the engine image for the tag being deployed, so they always match the images they
start, and database migrations run from that same image.
Requirements
On the machine running the deploy:
- bash
sshwith key-based access to every target
On every target server:
- Docker with the compose plugin
- a directory
~/netork/with netOrk's.env, which holds the database and application settings the compose file reads (env_file: .env)
Images: netork/engine and netork/ui must be published in the registry under the
tag you deploy. The engine image must carry its compose files under /app/deploy/.
Tags built before that change are refused with a clear message.
Setup
cp deploy.env.example deploy.env
$EDITOR deploy.env
deploy.env is gitignored. Point DEPLOY_ENV_FILE at another file to keep it
elsewhere.
| Variable | Meaning |
|---|---|
DEPLOY_SERVERS |
Space-separated default targets |
UI_SERVER |
Targets that also run netork-ui |
REGISTRY_HOST |
Registry to pull from; required |
NETORK_VERSION |
Tag to deploy (default latest) |
REGISTRY_USER, REGISTRY_PASSWORD |
Registry login used on every server |
REGISTRY_USER_<server>, REGISTRY_PASSWORD_<server>, NETORK_VERSION_<server> |
Per-server overrides. <server> has its dots replaced by underscores, e.g. _10_0_0_2 |
Usage
./deploy.sh # every server in DEPLOY_SERVERS
./deploy.sh 10.0.0.1 # one server
./deploy.sh 10.0.0.1 10.0.0.2 # several, in parallel
./deploy.sh --version=main-1a2b3c4 10.0.0.1 # one-off tag, this run only
Only tags netOrk's CI publishes are accepted:
latestlatest-devmain-<sha>feature-<branch>X.Y.Z
Anything else is refused before any server is touched.
If you deploy a branch build, wait until its CI run has published the images. A deploy started earlier pulls whatever image the registry held before, which is stale.
What a deploy does, per server
- Logs in to the registry. The password travels over ssh's stdin, never on a command line.
- Pulls the engine image and copies
docker-compose.ymlanddocker-compose.registry.ymlout of it into~/netork/. - Pulls the netOrk images, then force-recreates the API, the workers,
netork-beat,flowerand, on UI servers,netork-ui. - Reconciles
registry,apt-cacher-ngandsignal-api: each is recreated only if its definition changed. It never touchespostgresorredis. - Verifies that the containers run exactly the image that was pulled. If they don't, the deploy fails.
- Records
REGISTRY_HOSTandNETORK_VERSIONin~/netork/.env, so that a hand-typeddocker composeon the host uses the same images. - Runs
alembic upgrade headinsidenetork-api. - Prunes unused images.
A failing step stops that server's deploy with a non-zero exit, and the other servers carry on. The script exits non-zero if any server failed and names those servers.
Operating notes
- Never delete these Docker volumes:
celerybeat_scheduleholds the scheduler state.signal_cli_dataholds netOrk's Signal device link. Losing it means pairing again by QR code.
netork-beatalways rolls out together with the workers. The script does this for you; keep it that way if you deploy by hand.- Always deploy with this script. Do not point a local Docker client at a remote host
(
DOCKER_HOST=ssh://…): it resolves volume paths locally and breaks the remote containers.
Development
pip install pytest ruff shellcheck-py
shellcheck deploy.sh
ruff format --check . && ruff check .
pytest
The tests are static and behavioural checks of deploy.sh. None of them reach a real
host.
License
MIT, see LICENSE.