Deploy
Deploying CMSnap is copying one static binary; making it a service is one systemd unit. This version ships no installer script, so below is the manual, auditable path — a few commands, done once.
User, binary, site
sudo useradd --system --home /opt/cmsnap --shell /usr/sbin/nologin cmsnap sudo install -m 755 cms /usr/local/bin/cms sudo mkdir -p /opt/cmsnap && sudo chown cmsnap: /opt/cmsnap cd /opt/cmsnap && sudo -u cmsnap /usr/local/bin/cms def-help # unpack the example, print the admin password
Pick the topology
cms tune rewrites the root settings.json for a deployment shape — atomically and validated, so nested JSON is never edited by shell. Run it in /opt/cmsnap as the cmsnap user, like every cms command:
| situation | command |
|---|---|
| facing the internet, HTTPS via Let’s Encrypt | cms tune direct --port 80 --tls-port 443 --acme example.com,www.example.com — needs A/AAAA pointing here and 80+443 open; the first domain becomes the main site, the rest its redirect aliases |
| facing the internet, plain HTTP | cms tune direct --port 80 |
| behind nginx on the same host | cms tune proxy --port 8080 — localhost bind, trusts the proxy for X-Real-IP; the matching nginx block is in the server article |
The unit
/etc/systemd/system/cmsnap.service — unprivileged user, ports 80/443 via a capability instead of root, filesystem access limited to the site directory:
[Unit] Description=CMSnap-LITE After=network-online.target Wants=network-online.target [Service] User=cmsnap WorkingDirectory=/opt/cmsnap ExecStart=/usr/local/bin/cms Restart=on-failure AmbientCapabilities=CAP_NET_BIND_SERVICE CapabilityBoundingSet=CAP_NET_BIND_SERVICE NoNewPrivileges=true ProtectSystem=strict ProtectHome=true PrivateTmp=true ReadWritePaths=/opt/cmsnap [Install] WantedBy=multi-user.target
sudo systemctl daemon-reload sudo systemctl enable --now cmsnap
Day two
| task | how |
|---|---|
| update the binary | replace /usr/local/bin/cms, then sudo systemctl restart cmsnap — config and data untouched |
| change the config | edit, cms check, then cms reload — zero downtime |
| watch it | journalctl -u cmsnap -f, plus the request log (see the access_log article) |
Removing the service
sudo systemctl disable --now cmsnap sudo rm /etc/systemd/system/cmsnap.service sudo systemctl daemon-reload
This leaves the binary, the cmsnap user and your data in /opt/cmsnap. To remove those too (irreversible — deletes the databases):
sudo userdel cmsnap sudo rm -rf /opt/cmsnap /usr/local/bin/cms
Running in a container instead? See the Docker article.