Hosting for small Node products.
No dependencies.
Set up a server once. Then each product is one command to launch, and every push that passes CI deploys itself. GitHub never holds a key to your server.
$ modest-host 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 to launch
- 0keys to your server in GitHub
Approach
GitHub sends a message, not commands
Many deploy setups store a key to the server in GitHub, so anyone who gets into the repository or a workflow gets into the server too. modest-host turns that around: the server fetches and builds for itself, and GitHub can only tell it that CI passed.
A usual deploy
- An SSH key to the server, stored in GitHub
- A workflow that logs in and runs commands
- A container registry, and more tools to trust
- Products sharing one user
modest-host
- No key to the server anywhere but the server
- A signed message, checked, that runs nothing
- Node, git, systemd, and Caddy: already there
- Each product fenced off from the others
Deploying
What happens when you push
Nothing runs between pushes. When CI passes on main:
- GitHub sends a signed messageSigned with a secret only the server and GitHub know.
- The server checks itThe signature, the branch, the workflow, the repository, and that CI passed. Anything else is refused.
- It fetches and buildsOnly main's newest commit, with its own read-only key; dependencies exactly as the lockfile says, with install scripts off.
- It switches, and checksIf the new version doesn't answer, the one before comes back.
Features
What it does
One command to launch
Makes the GitHub repository, sets the product up on the server with its domain and HTTPS, and connects the two.
Signed deploys
Only a signed message for a passed CI run on main deploys, and only main's newest commit, so an old message sent again can't roll it back.
Products fenced off
Each runs as its own user, sandboxed by systemd: read-only code, its own data folder, and none of the server's keys.
Goes back if it fails
A version that doesn't answer is switched back to the one before, so a bad push doesn't take a product down.
Nightly copies
Every product's SQLite databases are copied each night with SQLite's own backup, safe while they're in use.
Checks the server
Before it does anything, it checks SSH, automatic updates, and what's listening, and says plainly what to fix.
$ 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 it tried
== 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
On one server you've set up, with products written for Node 24 or later.
- Ubuntu 24.04
- systemd
- Caddy
- Node 24
- GitHub
Getting started
It's in development, and not yet on npm. The docs describe it as it's being built, and the repository has everything so far.