For server operators
Maintain a snug server
Health checks, backups, updates, the server's address, and where the admin settings live.
Everything routine goes through snug-ops, from the private snug/ folder
the installer created:
cd /path/to/snug
Check health and logs
./snug-ops status
status shows server health, any interrupted backup, update, or restore, the
release the server is running, and whether this host follows updates or is
pinned. It cannot prove that call ports are reachable, so
after a firewall, router, address, or Docker change, make a real call from
outside the host's network.
./snug-ops license status shows whether the server can admit members,
without printing the certificate. ./snug-ops logs prints recent server
output, and ./snug-ops logs --follow watches it as it arrives.
Stop or start snug
./snug-ops stop
Stopping does not delete server data. ./snug-ops start brings it back, and
./snug-ops restart stops and starts it in one step. Either one reports
success only after snug is healthy over HTTPS.
Move the server to a new address
If you started at the server's IP address and have since bought a domain, point its A record at the host, then:
./snug-ops address chat.example.com
The command records the new address and serves snug there, then proves the address answers before it reports success. It asks first, because members who saved the old address won't reach snug until they open the new one. Run it with the server's IP address to go back.
If the public address calls announce has changed, as it can on a home connection, pass the new one instead. Chat keeps working through the domain; calls follow after one restart:
./snug-ops address --ip 203.0.113.9
Keep backups
snug backs itself up every night, in the same one-hour window it uses for
updates, without stopping. It freezes a copy of the database and uploads
inside its own storage in seconds, packages and verifies that copy while
members keep chatting, and removes the frozen copy. Nobody sees a notice and
nobody is disconnected. On the rare night it cannot take that copy, it
records the miss instead of stopping without warning, and ./snug-ops status
shows it. A night that updated the server skips the backup,
because the update left a verified backup of its own. The newest three nightly
backups stay in state/backups/; ./snug-ops status names the newest one and
how old it is, and says when a night did not happen and what to do about it.
Every backup is a full copy of the database and the uploads, so three nights
take three times the space your members have used, next to the live copy.
Before each night, including the first, snug measures the live data against
the free space. When the disk cannot hold another night, it removes older
nights first and, if that is still not enough, skips the night and says so
in status. A night it cannot measure is skipped and reported the same way. A backup you make by hand gets the same check and refuses
before it takes anything. To keep
backups off the host's own disk, point SNUG_BACKUP_DIR in state/.env at a
mounted disk, and they all land there instead, manual ones included.
A backup that stays on the host is not disaster recovery. Tell snug where each
one should also go by adding one line to state/.env:
SNUG_BACKUP_COPY_TO=/mnt/backup/snug
That copies every backup, nightly, by hand, or left behind by an update,
into that directory, checked byte for byte after copying. For anything else, an rsync target, an rclone
remote, a NAS, name your own program instead (run:/home/alex/copy.sh); it
receives the backup's path as its argument. ./snug-ops status reports when
the last copy succeeded, or why it failed. With copies going off the host,
SNUG_BACKUP_KEEP=1 keeps only the newest night here.
If your provider can snapshot the whole machine, that works too: the disk always holds a verified backup less than a day old.
To make a backup right now, before an upgrade or a move:
./snug-ops backup
To put that backup on a mounted disk, pass one new directory:
./snug-ops backup /mnt/encrypted/snug-before-moving
Backups leave out the license, so keep the original .lic file separately.
Never copy the database files yourself while snug is running; the commands
above take a consistent snapshot for you. Backups you make by hand are yours to keep and yours to remove; snug
never deletes them, and every manual update leaves a safety backup beside
them. Automatic updates keep their newest rollback backup and remove their
older one.
Update snug
A server installed through snug's public installer follows verified releases by default. It checks in the background and updates during the one-hour window chosen in Settings > Admin > Server > Updates. The initial window begins at 04:00 UTC. Five minutes before the server restarts, members see the expected time in the header. The notice does not appear in chat history.
To keep this host on the release it is running:
./snug-ops updates pin
./snug-ops updates status shows the current choice. Run ./snug-ops updates follow when the host should update in the admin's saved window again.
Pinning holds the server, not the people in it. Their desktop apps keep updating on their own, and they work with a server on any release since 3.0.0. Anything that needs a newer server stays hidden in their apps until you update. In a browser, everyone runs the app this server serves.
To update immediately, even when the host is pinned or outside its saved window, run:
./snug-ops upgrade
That one command asks snug.chat for the newest release. If this host already has it, upgrade says so and stops. Otherwise it verifies the newer package, installs it, and hands the update over to it.
To ask without acting on the answer, add --check. That reads the release
metadata and stops: nothing is downloaded, nothing is installed, and the server
keeps running.
Pick a moment when a brief disconnect is fine: the command verifies a safety backup, prints its path, and disconnects members once. Its final check walks a whole member journey on the new version: joining, writing, reading it back, uploading, and taking all of it away again. Nobody using snug sees it happen.
Pass a directory only when the safety backup needs a particular mounted disk:
./snug-ops upgrade /mnt/encrypted/snug-pre-upgrade
A server on a release older than 3.0.0 can't fetch on its own. If upgrade refuses instead of checking snug.chat, install the newest package once with the installer, and the single command works from then on:
(cd .. && curl -fsSL https://snug.chat/install.sh | sh) && ./snug-ops upgrade
If an update is interrupted or leaves the server unavailable, go straight to recover the server.
Change settings
Day-to-day group management lives in the app under Settings > Admin: invites, people, activity, roles, webhooks, and storage.
For host settings, leave state/.env alone. The only supported edit is the
admin setup code recovery. For
everything else, use ./snug-ops help advanced and the shipped RUNBOOK.md.