Deploy Node products to your own server.
No dependencies.
Set up a server once. Then launch each product with one command, and every push that passes CI deploys it.
npm install -g modest-deploy
$ modest-deploy launch shop shop.example.org --server myserver
Made the repository example/shop.
Added shop on myserver.
Gave GitHub the read-only deploy key, and the webhook.
$ git push
shop: running 3f2a9c1
Signed · main · CI passed · answered
- 0runtime dependencies
- ~1,800lines of source
- 1command per product
- 7nights of database copies
Approach
No server key in GitHub
Deploying from CI usually means the workflow signs in to the server over SSH, so the key is stored in GitHub. With modest-deploy, GitHub only sends a signed message when CI passes. The server checks it, then fetches and builds the code itself.
Deploying over SSH from CI
- A key to the server is stored in GitHub
- The workflow runs commands on the server
- Often a container registry as well
modest-deploy
- No key to the server is stored in GitHub
- The server decides what runs
- Uses Node, git, systemd, and Caddy
Deploying
What happens when you push
When CI passes on main:
- GitHub sends a signed messageSigned with a secret that only the server and GitHub have.
- The server checks itIt has to be signed, from the product's own repository, for a CI run on main that passed. Anything else is ignored.
- It fetches and buildsOnly the newest commit on main, with the product's own read-only key. Dependencies come from the lockfile, with install scripts off.
- It switches overIf the new version doesn't respond, the previous one is restored.
Features
What it does
One command to launch
Creates the GitHub repository, sets the product up on the server with its domain and HTTPS certificate, and connects the two.
Signed deploys
Only the newest commit on main is deployed, so an old message sent again can't roll a product back.
A user per product
Each product runs as its own user in a systemd sandbox. It can read its own code and write only to its own data folder.
Rollback
If a new version doesn't respond, the previous one is restored.
Nightly backups
Each product's SQLite databases are copied every night with SQLite's backup API, and kept for 7 nights.
Server checks
Before installing, it checks the SSH settings, automatic updates, and open ports, and tells you what to change.
$ sh test/e2e/run.sh
== a stand-in GitHub that isn't GitHub is refused
ok: nothing deployed: GitHub's real host keys are pinned
== a signed message for a passed CI run deploys
ok: shop v1 is running, with modest-auth installed from npm
== each product is sandboxed
ok: it can write its own data, and nothing else
== a version that doesn't start is switched back
ok: v2 is running again
End to end: every step passed.
Compatibility
Runs on Ubuntu with systemd and Caddy
Products need Node 24 or later.
- Ubuntu 26.04 LTS
- systemd
- Caddy
- Node 24
- GitHub
Getting started
npm install -g modest-deploy
This is an early release, and it hasn't had an independent security review yet.