# Persistent Daemon
_Mothership and peer, running in the background, surviving reboots and network changes._
## Overview
A Mothership started with `aura mothership start` in a terminal is fine for development. For production — or for any team that expects the Mothership to be reachable on Monday morning — it needs to run as a persistent daemon. Same applies to the peer side: developers should not have to remember to run `aura` after every reboot.
This page covers daemonization on the three platforms we support (Linux with systemd, macOS with launchd, and Windows — via WSL or NSSM), network-change handling, log locations, and rotation.
## Linux: systemd
Systemd is the default on every Linux distribution Aura supports. The idiomatic setup uses a single unit file with a user-level service for peers and a system-level service for Motherships.
### Mothership as a system service
Create `/etc/systemd/system/aura-mothership.service`:
```text
[Unit]
Description=Aura Mothership
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=aura
Group=aura
ExecStart=/usr/local/bin/aura mothership start --foreground
Restart=on-failure
RestartSec=5s
LimitNOFILE=65536
# Sandboxing
NoNewPrivileges=true
ProtectSystem=strict
ProtectHome=true
ReadWritePaths=/var/lib/aura /var/log/aura
PrivateTmp=true
ProtectKernelTunables=true
[Install]
WantedBy=multi-user.target
```
Then:
```bash
sudo useradd --system --home /var/lib/aura --shell /usr/sbin/nologin aura
sudo mkdir -p /var/lib/aura /var/log/aura
sudo chown aura:aura /var/lib/aura /var/log/aura
sudo systemctl daemon-reload
sudo systemctl enable --now aura-mothership
```
Verify:
```bash
systemctl status aura-mothership
journalctl -u aura-mothership -f
```
The `--foreground` flag tells Aura not to fork; systemd wants to own the process. `Restart=on-failure` ensures a crash is not fatal.
### Peer as a user service
Peers should run under the developer's own account, not as a system daemon. Create `~/.config/systemd/user/aura-peer.service`:
```text
[Unit]
Description=Aura peer sync
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
ExecStart=/usr/local/bin/aura sync --foreground
Restart=on-failure
RestartSec=10s
[Install]
WantedBy=default.target
```
Enable:
```bash
systemctl --user daemon-reload
systemctl --user enable --now aura-peer
loginctl enable-linger "$USER"
```
`loginctl enable-linger` ensures the user service keeps running when the developer is not logged in. Without it, the service stops when they log out.
## macOS: launchd
On macOS, launchd is the equivalent of systemd. There are two scopes: _LaunchDaemons_ (system-wide, run as root or a specified user) and _LaunchAgents_ (per-user).
### Mothership as a LaunchDaemon
Create `/Library/LaunchDaemons/com.aura.mothership.plist`:
```text
Label
com.aura.mothership
ProgramArguments
/usr/local/bin/aura
mothership
start
--foreground
RunAtLoad
KeepAlive
UserName
_aura
StandardOutPath
/var/log/aura/mothership.log
StandardErrorPath
/var/log/aura/mothership.err
```
Load:
```bash
sudo launchctl bootstrap system /Library/LaunchDaemons/com.aura.mothership.plist
sudo launchctl enable system/com.aura.mothership
```
Create the `_aura` user via System Settings or `dscl`. This is more fiddly on macOS than Linux; many teams run their Mothership on a Mac mini as a regular user with a LaunchAgent instead, which is fine for small teams.
### Peer as a LaunchAgent
Create `~/Library/LaunchAgents/com.aura.peer.plist`:
```text
Label
com.aura.peer
ProgramArguments
/usr/local/bin/aura
sync
--foreground
RunAtLoad
KeepAlive
```
Load:
```bash
launchctl bootstrap gui/$UID ~/Library/LaunchAgents/com.aura.peer.plist
launchctl enable gui/$UID/com.aura.peer
```
## Windows
Windows is not a first-class deployment target for Mothership hosts — we recommend Linux or macOS for any Mothership. But developers on Windows can run peers.
Easiest path: use WSL2 and follow the Linux instructions. Aura's WSL install works out of the box.
If you must run native Windows, NSSM (the Non-Sucking Service Manager) wraps `aura sync` as a Windows service:
```bash
nssm install AuraPeer "C:\Program Files\Aura\aura.exe" "sync --foreground"
nssm set AuraPeer AppStdout "C:\ProgramData\Aura\logs\peer.log"
nssm set AuraPeer AppStderr "C:\ProgramData\Aura\logs\peer.err"
nssm start AuraPeer
```
This works. It is not our happiest path. File paths, signals, and the WAL's fsync semantics are subtly different on Windows. Test carefully.
## Auto-Reconnect on Network Change
A laptop that moves from WiFi to Ethernet to WiFi-again should not need manual intervention to stay connected. Aura handles this by subscribing to OS-level network change notifications.
- **Linux**: netlink socket. Reacts to interface up/down, IP changes, route changes.
- **macOS**: SystemConfiguration framework notifications. Reacts to WiFi association changes, VPN up/down.
- **Windows**: `NotifyIPInterfaceChange`. Similar semantics.
When a network change is detected:
1. Aura drops existing peer and Mothership connections (their underlying sockets may already be dead but haven't timed out).
2. It waits up to 2 seconds for the new network to stabilize.
3. It re-resolves the Mothership's hostname (in case DNS answers differently on the new network).
4. It reconnects, going through the normal peer certificate authentication.
5. It triggers a WAL reconcile (see [offline mode](/offline-mode)).
The whole dance usually completes in under 5 seconds. You will see:
```text
[netchange] interface state changed
[sync] connection dropped, reconnecting
[sync] reconnected to mship_7fcd21a9
[sync] reconcile: pulled 3 events, pushed 0 events
```
> **Gotcha.** Captive portals (hotel WiFi) will pass the network-change check but return HTTPS redirects for the Mothership hostname. Aura detects this and surfaces a `captive portal suspected` warning in the log. Open a browser, sign in, and Aura will reconnect on the next retry cycle.
## Log Locations
| Platform | Location |
|---|---|
| Linux (systemd) | `journalctl -u aura-mothership`, `journalctl --user -u aura-peer` |
| Linux (non-systemd) | `~/.local/state/aura/log/` |
| macOS (daemon) | `/var/log/aura/` |
| macOS (agent) | `~/Library/Logs/aura/` |
| Windows | `%ProgramData%\Aura\logs\` or `%LOCALAPPDATA%\Aura\logs\` |
Log format is structured JSON by default. Toggle to plain text:
```toml
[logging]
format = "text"
level = "info" # trace, debug, info, warn, error
```
## Log Rotation
Aura does not rotate its own logs when using systemd or launchd — it delegates to the platform.
**systemd / journald** already rotates. To bound size:
```text
# /etc/systemd/journald.conf
SystemMaxUse=500M
MaxRetentionSec=30d
```
**launchd** does not rotate plain files. Pair with `newsyslog`:
```text
# /etc/newsyslog.d/aura.conf
/var/log/aura/mothership.log _aura:_aura 644 5 10000 * GZ
```
**Plain files** on Linux without systemd: use `logrotate`:
```text
# /etc/logrotate.d/aura
/var/log/aura/*.log {
daily
rotate 14
compress
delaycompress
missingok
notifempty
copytruncate
}
```
## Health Checks for Monitoring Systems
Plug Mothership into your monitoring stack by hitting the health endpoint:
```bash
curl -sf https://mothership.acme.internal:7777/healthz || exit 1
```
Every 30 seconds from Prometheus / Datadog / your monitoring tool of choice. A non-200 response or a connect failure means the Mothership is not answering.
For deeper metrics:
```bash
curl -k https://mothership.acme.internal:7777/metrics
```
Returns Prometheus-format metrics: connected peers, WAL size, push/pull rates, handshake counts by result, TLS cert expiry seconds remaining. Scrape every 60s.
> **Security callout.** `/metrics` is unauthenticated by default for local scraping. Bind Mothership to a non-public interface, or put it behind your monitoring VPN. You can require bearer-token auth for metrics:
```toml
[metrics]
require_token = true
token_file = "/etc/aura/metrics-token"
```
## Upgrading a Running Daemon
Aura binaries are designed for drop-in replacement. On systemd:
```bash
sudo cp aura-new /usr/local/bin/aura
sudo systemctl restart aura-mothership
```
Restart takes a few seconds. During the gap:
- Peers briefly enter offline mode.
- Existing peer-to-peer direct connections keep working.
- On reconnect, peers reconcile normally.
There is no in-place reload of the Mothership binary yet. Plan restarts outside critical windows, or run a [mesh topology](/team-topology#mesh) where a sibling Mothership covers the gap.
## Startup Ordering and Dependencies
A Mothership that starts before the network is up will fail on bind and respawn. A peer that starts before the VPN has come up will fail to reach the Mothership and respawn. In both cases systemd/launchd handle the respawn for you, but it makes for noisy logs and a minute-long cold start.
Avoid this with explicit dependencies.
**systemd.** Both units above already include `After=network-online.target`. If you're on Tailscale:
```text
[Unit]
After=network-online.target tailscaled.service
Wants=network-online.target tailscaled.service
```
**launchd.** Does not have a dependency system in the systemd sense, but `KeepAlive = true` combined with a short retry is effectively equivalent. If you need precise ordering, wrap the start in a script that blocks on a network reachability check.
## Running as Non-Root
Treat the Mothership host like any other server. The Aura binary does not need root to do its job, and running as a dedicated user limits blast radius. The systemd example above creates an `aura` user; the macOS example uses `_aura`. Keep doing this.
The one exception is binding to privileged ports (below 1024) on Linux. We covered `setcap` above. Capability preferred over running as root.
Home directory for the Mothership user should not be `/home/aura` but something like `/var/lib/aura`. This signals "service, not person" to anyone reading your `/etc/passwd`.
## Observability in Production
A Mothership without monitoring is a Mothership waiting to surprise you. The minimum:
- Scrape `/metrics` into Prometheus or equivalent. Alert on `aura_sync_backlog > 1000` sustained, `aura_tls_cert_not_after_seconds < 30d`, and `aura_connected_peers` dropping by more than 20% from baseline.
- Ship `journalctl` output to a log aggregator. Alert on any `ERROR`-level message.
- Health check `/healthz` every 30s from an external monitor.
- Daily back up of the data directory. Verify restores monthly.
These are not Aura-specific practices; they are server operation table stakes. Mothership is a server. Operate it like one.
## Next Steps
- [Scale your Mothership hardware appropriately](/scaling-mothership)
- [Set up health checks and monitoring](/mothership-troubleshooting)
- [Harden TLS for production](/tls-and-jwt)