107 lines
4.6 KiB
Desktop File
107 lines
4.6 KiB
Desktop File
[Unit]
|
|
Description=Morphit matrix-bot — tails journalctl, classifies operator alerts by tier, DMs to operator MXID via Matrix
|
|
Documentation=https://git.agorise.net/agorise/morphit
|
|
After=network-online.target morphit-indexer.service morphit-relay.service
|
|
Wants=network-online.target
|
|
|
|
[Service]
|
|
Type=simple
|
|
User=morphit-matrix-bot
|
|
Group=morphit-matrix-bot
|
|
WorkingDirectory=/opt/morphit/apps/matrix-bot
|
|
|
|
# Environment file — NEVER commit a populated version. Operator
|
|
# fills MORPHIT_MATRIX_BOT_HOMESERVER, MORPHIT_MATRIX_BOT_ACCESS_TOKEN,
|
|
# and MORPHIT_MATRIX_BOT_ALERT_MXID at deploy time. This file is the
|
|
# bot's ONLY config source — it does NOT read morphit.config.env (the
|
|
# operator-config loader). The MXID it reads is the one written here by
|
|
# `morphit-ops matrix set <mxid>`, which also enables + starts this unit;
|
|
# `morphit-ops matrix clear` empties it and stops the unit; and
|
|
# `morphit-ops upgrade` re-checks it on every upgrade.
|
|
#
|
|
# Leading `-` makes the file OPTIONAL — systemd won't refuse to
|
|
# start the unit if /etc/morphit/matrix-bot.env doesn't exist.
|
|
# In that case the bot exits 0 cleanly because no Matrix surfaces
|
|
# are configured (see apps/matrix-bot/src/main.ts opt-in gate).
|
|
EnvironmentFile=-/etc/morphit/matrix-bot.env
|
|
|
|
# tsx — same pattern as indexer/relay; no build step.
|
|
ExecStart=/usr/bin/env node --enable-source-maps \
|
|
/opt/morphit/node_modules/tsx/dist/cli.mjs src/main.ts
|
|
|
|
KillSignal=SIGTERM
|
|
TimeoutStopSec=15
|
|
|
|
# Restart on crash, BUT NOT on clean exit 0. The bot exits 0 when
|
|
# the operator hasn't configured Matrix surfaces (see main.ts opt-in
|
|
# gate) — that's the documented default state for instances not using
|
|
# Matrix. Using `on-failure` here makes the unit cleanly inert in
|
|
# that case instead of restart-looping.
|
|
Restart=on-failure
|
|
RestartSec=10
|
|
|
|
StandardOutput=journal
|
|
StandardError=journal
|
|
|
|
# ─── Hardening ──────────────────────────────────────────────────
|
|
# Mirrors the indexer/relay hardening posture.
|
|
ProtectSystem=strict
|
|
ProtectHome=true
|
|
# The bot logs to the journal (StandardOutput/StandardError=journal),
|
|
# so it only needs its state dir writable. (It does NOT write to
|
|
# /var/log/morphit — that path was previously listed here by analogy
|
|
# with the indexer/relay, but the bot has no file logging, and listing
|
|
# a non-existent path makes systemd fail unit start with 226/NAMESPACE
|
|
# on hosts where the indexer/relay haven't created /var/log/morphit.)
|
|
ReadWritePaths=/var/lib/morphit-matrix-bot
|
|
PrivateTmp=true
|
|
|
|
NoNewPrivileges=true
|
|
ProtectKernelTunables=true
|
|
ProtectKernelModules=true
|
|
ProtectKernelLogs=true
|
|
ProtectControlGroups=true
|
|
ProtectClock=true
|
|
RestrictRealtime=true
|
|
RestrictSUIDSGID=true
|
|
LockPersonality=true
|
|
# Node's V8 JIT needs W+X
|
|
MemoryDenyWriteExecute=false
|
|
|
|
LimitCORE=0
|
|
ProtectProc=invisible
|
|
# NOTE: deliberately NOT setting `ProcSubset=pid` here, even though the
|
|
# indexer/relay units do. Those are *monitored* services; the matrix-bot's
|
|
# job is to RUN `journalctl --follow`, and journalctl reads the boot id from
|
|
# /proc/sys/kernel/random/boot_id. ProcSubset=pid mounts /proc with
|
|
# subset=pid, which hides /proc/sys — making journalctl fail with
|
|
# "Failed to get boot id: No such file or directory" and the bot crash-loop.
|
|
# /proc/sys remains read-only via ProtectKernelTunables=true (journalctl
|
|
# only needs to read it), so dropping ProcSubset costs little hardening here.
|
|
|
|
# Network — egress only to the Matrix homeserver. Healthcheck
|
|
# binds loopback only.
|
|
RestrictAddressFamilies=AF_INET AF_INET6 AF_UNIX
|
|
|
|
# ─── journalctl read access ─────────────────────────────────────
|
|
# The bot needs to read journald to tail morphit-indexer + morphit-relay
|
|
# units. Two equivalent approaches:
|
|
#
|
|
# (a) Add the bot user to `systemd-journal` group (recommended —
|
|
# least-privilege, no capabilities needed):
|
|
# sudo usermod -aG systemd-journal morphit-matrix-bot
|
|
#
|
|
# (b) Grant the unit CAP_SYSLOG via AmbientCapabilities (if you
|
|
# don't want group membership):
|
|
# AmbientCapabilities=CAP_SYSLOG
|
|
# CapabilityBoundingSet=CAP_SYSLOG
|
|
#
|
|
# Default below is (a) — group membership. Set up the user with:
|
|
# sudo useradd --system --no-create-home --shell /usr/sbin/nologin \
|
|
# --groups systemd-journal morphit-matrix-bot
|
|
# sudo mkdir -p /var/lib/morphit-matrix-bot
|
|
# sudo chown morphit-matrix-bot:morphit-matrix-bot /var/lib/morphit-matrix-bot
|
|
# sudo chmod 0750 /var/lib/morphit-matrix-bot
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|