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:

situationcommand
facing the internet, HTTPS via Let’s Encryptcms 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 HTTPcms tune direct --port 80
behind nginx on the same hostcms 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

taskhow
update the binaryreplace /usr/local/bin/cms, then sudo systemctl restart cmsnap — config and data untouched
change the configedit, cms check, then cms reload — zero downtime
watch itjournalctl -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.

← All articles in this group