Early, not yet independently reviewed

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

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:

  1. GitHub sends a signed messageSigned with a secret that only the server and GitHub have.
  2. 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.
  3. 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.
  4. 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.