diff --git a/ROADMAP.md b/ROADMAP.md index 1f8f8c7..ba6c9c0 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -35,13 +35,12 @@ - [x] Client-side TLS (accept TLS from clients) - [x] Channel key support (JOIN #channel key) - [x] Hot config reload (SIGHUP) -- [ ] Systemd service file +- [x] Systemd service file ## v0.4.0 - [ ] Per-client backlog tracking (multi-user) - [ ] Web status page -- [ ] DCC passthrough - [ ] Containerfile for podman deployment ## v1.0.0 diff --git a/TASKS.md b/TASKS.md index 38b3b4e..df4e64e 100644 --- a/TASKS.md +++ b/TASKS.md @@ -28,5 +28,5 @@ - [x] P2: Client-side TLS support - [x] P2: Channel key support - [x] P2: Hot config reload (SIGHUP + REHASH refactor) -- [ ] P3: Systemd service file +- [x] P3: Systemd service file - [ ] P3: Containerfile for podman deployment diff --git a/TODO.md b/TODO.md index fc3a2c5..3488cff 100644 --- a/TODO.md +++ b/TODO.md @@ -3,14 +3,12 @@ ## Features - [ ] Web status dashboard -- [ ] DCC passthrough - [ ] Per-client backlog tracking (multi-user) - [ ] Farm: configurable ephemeral deadline - [ ] Farm: per-network enable/disable override ## Infrastructure -- [ ] Systemd unit file - [ ] Containerfile for podman deployment - [ ] PyPI packaging diff --git a/config/bouncer.service b/config/bouncer.service new file mode 100644 index 0000000..a049f30 --- /dev/null +++ b/config/bouncer.service @@ -0,0 +1,36 @@ +[Unit] +Description=IRC bouncer with stealth connect and multi-network multiplexing +After=network-online.target +Wants=network-online.target + +[Service] +Type=simple +User=user +Group=user + +ExecStart=%h/git/bouncer/.venv/bin/bouncer -c %h/git/bouncer/config/bouncer.toml +ExecReload=kill -HUP $MAINPID + +Restart=on-failure +RestartSec=10 + +# Logging (stdout/stderr -> journal) +StandardOutput=journal +StandardError=journal +SyslogIdentifier=bouncer + +# Hardening +NoNewPrivileges=yes +ProtectSystem=strict +ProtectHome=tmpfs +BindPaths=%h/git/bouncer +PrivateTmp=yes +ProtectKernelTunables=yes +ProtectKernelModules=yes +ProtectControlGroups=yes +RestrictNamespaces=yes +RestrictRealtime=yes +MemoryDenyWriteExecute=yes + +[Install] +WantedBy=default.target diff --git a/docs/CHEATSHEET.md b/docs/CHEATSHEET.md index a52eb26..6743ce1 100644 --- a/docs/CHEATSHEET.md +++ b/docs/CHEATSHEET.md @@ -9,6 +9,18 @@ bouncer --version # version bouncer --help # help ``` +## Systemd + +```bash +systemctl --user enable bouncer # enable at boot +systemctl --user start bouncer # start +systemctl --user stop bouncer # stop +systemctl --user restart bouncer # restart +systemctl --user reload bouncer # hot reload (SIGHUP) +systemctl --user status bouncer # status +journalctl --user -u bouncer -f # follow logs +``` + ## Podman ```bash @@ -219,6 +231,7 @@ password # optional, IRC server PASS |------|---------| | `config/bouncer.toml` | Active config (gitignored) | | `config/bouncer.example.toml` | Example template | +| `config/bouncer.service` | Systemd user service unit | | `config/bouncer.db` | SQLite backlog (auto-created) | | `{data_dir}/bouncer.pem` | Listener TLS cert (auto-created) | | `{data_dir}/certs/{net}/{nick}.pem` | Client certificates (auto-created) | diff --git a/docs/INSTALL.md b/docs/INSTALL.md index 69b1cfa..ecbb225 100644 --- a/docs/INSTALL.md +++ b/docs/INSTALL.md @@ -68,6 +68,45 @@ Verify: which bouncer ``` +## Systemd (User Service) + +Install and enable the bouncer as a user service (no root required): + +```bash +mkdir -p ~/.config/systemd/user +cp config/bouncer.service ~/.config/systemd/user/bouncer.service +``` + +Edit `ExecStart=` paths if your install differs from the defaults: + +```bash +$EDITOR ~/.config/systemd/user/bouncer.service +``` + +Enable and start: + +```bash +systemctl --user daemon-reload +systemctl --user enable bouncer +systemctl --user start bouncer +``` + +Enable lingering so the service runs without an active login session: + +```bash +sudo loginctl enable-linger $USER +``` + +### Management + +```bash +systemctl --user status bouncer # check status +systemctl --user restart bouncer # restart +systemctl --user stop bouncer # stop +journalctl --user -u bouncer -f # follow logs +systemctl --user reload bouncer # hot reload config (SIGHUP) +``` + ## Dependencies Installed automatically by `make dev`: diff --git a/docs/USAGE.md b/docs/USAGE.md index 050ad82..1f99a03 100644 --- a/docs/USAGE.md +++ b/docs/USAGE.md @@ -684,6 +684,20 @@ Results are sent back as NOTICE messages. | farm_enabled, farm_interval, etc. | Farm started/stopped | | bind, port, password, client_tls | Warning logged (restart required) | +## Systemd + +The bouncer ships with a systemd user service file. See [INSTALL.md](INSTALL.md) +for setup. Key operations: + +```bash +systemctl --user start bouncer # start +systemctl --user stop bouncer # stop +systemctl --user reload bouncer # hot reload (SIGHUP) +journalctl --user -u bouncer -f # follow logs +``` + +The service restarts automatically on failure (`RestartSec=10`). + ## Stopping Press `Ctrl+C` or send `SIGTERM`. The bouncer shuts down gracefully, closing