Backup, upgrade, uninstall
Is it up?
curl -fsS http://127.0.0.1:18254/health{"status":"ok","uptime":147,"version":"0.1.0","agents":6,"install":"a1b2c3d4e5f6","gateways":{"telegram:bot":"connected"}}status is degraded — and the endpoint answers 503 — when a gateway is dead, disconnected or
reconnecting, or when the SQLite WAL has grown past its threshold. issues then lists what is wrong.
install is a hash of the data directory, so a CLI can tell it is talking to the right daemon when two
installs on one machine compete for the port.
Check this, not just the service state. systemctl start returning 0 means a process was
spawned, not that it is serving — a daemon that refuses its config exits after systemd reports
success.
nouride status # agents, gateways, queuenouride doctor # what is wrong, and what to do about itnouride service status # which supervisor, and whether exiting gets you respawnedStart, stop, restart
# Linux / Raspberry Pisudo systemctl restart nouridesudo systemctl stop nouridesudo journalctl -u nouride -f
# macOSlaunchctl unload -w ~/Library/LaunchAgents/tech.nouverse.nouride.plist # stoplaunchctl load -w ~/Library/LaunchAgents/tech.nouverse.nouride.plist # start
# Dockerdocker compose restartdocker compose logs -fnouride restart works on any of them, but it works by asking the daemon to exit so its supervisor
brings it back. With nothing supervising it, that is just a stop — so it refuses with a 409 rather
than silently shutting you down. nouride service status answers for the process actually running
and says plainly whether anything will respawn it.
Inside a container it reports docker and refuses for the same reason: the restart policy lives
outside the container. Use docker restart <container>.
nouride stop is the one command that reaches the daemon without the control API — it reads the lock
file and sends a signal, which is the path that still works when the HTTP server is the thing that
has wedged.
Backup
The daemon snapshots its own database at boot and then daily, and keeps the newest backup_keep
(seven by default) under data/backups/db/. Every snapshot is integrity-checked before it is kept,
and one that fails the check is discarded rather than left where a restore might find it.
nouride db backup # take one now, before you do something riskynouride db list # newest firstnouride db verify [file] # check a snapshot, or the live databasenouride db restore <file> # put one back — the daemon must be stoppedA snapshot is a single ordinary SQLite file with no sidecars, so recovery does not need these
commands: cp it over data/nouride.db with the daemon stopped and delete nouride.db-wal and
nouride.db-shm beside it. nouride db restore does exactly that, plus two things worth having —
it refuses to run while the daemon is up, and it moves the database it replaces to
nouride.db.replaced-<timestamp> so restoring the wrong snapshot is itself undoable.
Why not
cpof the live file? Because it looks like it works. The database is three files, and everything committed since the last checkpoint is innouride.db-wal. A copy of the main file alone opens without complaint and is missing the newest rows — a backup that exists, restores cleanly, and is silently behind. The snapshots use SQLite’s ownVACUUM INTO, which is consistent against a running daemon.
For the whole install rather than the database alone, stop it first:
sudo systemctl stop nouridesudo tar -czf nouride-backup-$(date +%F).tar.gz -C /srv/nouride .nouride .envsudo systemctl start nourideWhat is in there, ranked by how much it would hurt to lose:
agents/ | MEMORY.md above all. Months of accumulated identity, not in git, and the only thing here that cannot be rebuilt |
data/ | conversations, audit log, standing grants, the secret store |
config.toml and .env | how this install differs from a default one |
workspace/ | whatever the agents have built. Output rather than identity — restore it if you want the work back, skip it if you only want the daemon back |
The daemon also keeps dated copies of the persona packs under data/backups/agents/, seven by
default. Those are kilobytes of Markdown and recovery is cp, deliberately — it does not need this
code to still work. They cover an agent corrupting its own memory; they do not cover the directory
being deleted, a bad checkout, or a disk.
Both sets live under data/, which is the directory every deployment shape mounts — so a snapshot
lands wherever you already back up. That also means they are on the same disk as the thing they
protect: copy them somewhere else for the failure that takes the disk with it.
Upgrade
Re-run the installer. It stops the daemon, replaces the binary, and starts it again. Your database,
secrets, agent packs and workspace in .nouride/ are left alone.
Anyone mid-conversation is told. Stopping the daemon while an agent is working — an upgrade does exactly that — used to leave the person who asked waiting for a reply that never came. The daemon now sends one line into each affected conversation before it goes, and stops those turns rather than waiting on them:
The daemon is shutting down, so I stopped in the middle of this. Nothing came of this turn — send it again once I am back.
It cannot tell an upgrade from a shutdown, so the message does not guess. Turns that were not running are unaffected, and a stop with nothing in flight sends nothing.
If the daemon is killed outright instead — kill -9, the OOM killer, a power cut — no message can
be sent at the time, so the next boot reports it to the same conversations once the gateways are
up.
# Linux / Raspberry Picurl -fsSL https://get.nouride.com/install.sh | sudo sh
# macOS — replace the binary, then restart the jobcd ~/nouride && curl -fsSL https://get.nouride.com/latest/nouride-darwin-arm64.tar.gz | tar -xzlaunchctl kickstart -k gui/$(id -u)/tech.nouverse.nouride
# Dockerdocker compose pull && docker compose up -dPin a version with --version v0.1.0.
Migrations run at boot and are compiled into the binary, so there is no separate step and nothing to remember. Check afterwards:
nouride versionnouride doctorMoving it to another machine
One directory, so this is a copy:
- Install the binary on the new box (the installer, with the daemon left stopped).
- Stop the old daemon.
- Copy
.nouride/and.envacross, preserving ownership and modes —data/holds0600files. - Start the new one and run
nouride doctor. - Only then decommission the old one. Two daemons must not run against the same bot token — two Telegram bots polling one token get half the messages each.
workspace_dir can point at another disk if that is where the work belongs; nothing else has to
move.
Renaming a gateway
The one operation that rewrites both the config and the database, so it refuses to run while the daemon is up:
sudo systemctl stop nouridenouride gateway rename telegram:old telegram:new --applysudo systemctl start nourideWithout --apply it shows what it would change.
Uninstall
# Linux / Raspberry Pisudo systemctl disable --now nouridesudo rm /etc/systemd/system/nouride.service /usr/local/bin/nouridesudo systemctl daemon-reloadsudo rm -rf /srv/nouride # this deletes your agents and conversations
# macOSlaunchctl unload -w ~/Library/LaunchAgents/tech.nouverse.nouride.plistrm ~/Library/LaunchAgents/tech.nouverse.nouride.plistrm -rf ~/nouride
# Dockerdocker compose downrm -rf ./nouridenouride service uninstall prints the right commands for whichever supervisor you are on.
Disk, and what grows
.nouride/workspace/ is the only part that grows without bound — it is whatever the agents produce.
Everything else ages out on the schedule in [retention]: audit rows at 30 days, job runs at 14,
attachments and tool output on their own clocks.
The daemon watches its own disk: [health] disk_warn_threshold_mb (1 GB) raises an alert rather than
only logging, and /health reports degraded once the SQLite WAL passes
wal_warn_threshold_mb (100 MB).
Alerts
Set these before you walk away from it:
[alerts]gateway = "telegram:nouva"chat_id = "123456789"Without them a dead gateway is only a line in the log, so you find out when you notice the agent has gone quiet — hours later, looking like a different problem. Boot warns when chat gateways are enabled and this is empty.