[Unit] Description=Mnemosyne Telegram bot (webhook receiver) Documentation=https://git.castlehollow.com/rodger/mnemosyne After=network-online.target Wants=network-online.target # Cap restart rate: no more than 5 restarts in 60 seconds StartLimitBurst=5 StartLimitIntervalSec=60 [Service] Type=simple User=mnemosyne Group=mnemosyne WorkingDirectory=/opt/mnemosyne ExecStart=/usr/bin/perl /opt/mnemosyne/bin/mnemosyne-bot \ --config /etc/mnemosyne/mnemosyne.conf Restart=always RestartSec=5 # Logging StandardOutput=journal StandardError=journal SyslogIdentifier=mnemosyne-bot # ── Hardening ──────────────────────────────────────────────────────────────── # Prevent privilege escalation NoNewPrivileges=true # Private /tmp — isolates temp files from other services PrivateTmp=true # Read-only /usr, /boot, /etc (except the config dir we explicitly allow) ProtectSystem=strict # The bot needs to write the SQLite database; allow the data dir ReadWritePaths=/var/lib/mnemosyne # No access to home directories ProtectHome=true # Prevent writing to kernel tunables ProtectKernelTunables=true ProtectKernelModules=true ProtectKernelLogs=true ProtectControlGroups=true # Restrict address families: only IPv4/IPv6 (outbound Telegram API) + Unix sockets RestrictAddressFamilies=AF_INET AF_INET6 AF_UNIX # Syscall filtering — Perl/DBI only needs the basics SystemCallFilter=@system-service SystemCallErrorNumber=EPERM # No realtime scheduling, no raw I/O, no device access RestrictRealtime=true PrivateDevices=true # Tighten /proc view ProtectProc=invisible [Install] WantedBy=multi-user.target