Add systemd units and install script for MCNS deployment

Ship mcns.service, mcns-backup.service, mcns-backup.timer, and
deploy/scripts/install.sh adapted from MCR's deployment files.
Includes full security hardening block per engineering standards
and AmbientCapabilities=CAP_NET_BIND_SERVICE for DNS port 53.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-03-26 21:02:47 -07:00
parent efd307f7fd
commit 7b11f527f2
4 changed files with 116 additions and 0 deletions

47
deploy/scripts/install.sh Executable file
View File

@@ -0,0 +1,47 @@
#!/bin/sh
set -eu
SERVICE="mcns"
BINARY="/usr/local/bin/mcns"
DATA_DIR="/srv/${SERVICE}"
UNIT_DIR="/etc/systemd/system"
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
REPO_DIR="$(cd "${SCRIPT_DIR}/../.." && pwd)"
# Create system user and group (idempotent).
if ! id -u "${SERVICE}" >/dev/null 2>&1; then
useradd --system --no-create-home --shell /usr/sbin/nologin "${SERVICE}"
echo "Created system user ${SERVICE}."
fi
# Install binary.
install -m 0755 "${REPO_DIR}/mcns" "${BINARY}"
echo "Installed binary."
# Create data directory structure.
install -d -o "${SERVICE}" -g "${SERVICE}" -m 0700 "${DATA_DIR}"
install -d -o "${SERVICE}" -g "${SERVICE}" -m 0700 "${DATA_DIR}/backups"
install -d -o "${SERVICE}" -g "${SERVICE}" -m 0700 "${DATA_DIR}/certs"
echo "Created ${DATA_DIR}/."
# Install example config if none exists.
if [ ! -f "${DATA_DIR}/${SERVICE}.toml" ]; then
install -o "${SERVICE}" -g "${SERVICE}" -m 0600 \
"${REPO_DIR}/deploy/examples/mcns.toml" \
"${DATA_DIR}/${SERVICE}.toml"
echo "Installed example config to ${DATA_DIR}/${SERVICE}.toml — edit before starting."
fi
# Install systemd units.
install -m 0644 "${REPO_DIR}/deploy/systemd/${SERVICE}.service" "${UNIT_DIR}/"
install -m 0644 "${REPO_DIR}/deploy/systemd/${SERVICE}-backup.service" "${UNIT_DIR}/"
install -m 0644 "${REPO_DIR}/deploy/systemd/${SERVICE}-backup.timer" "${UNIT_DIR}/"
systemctl daemon-reload
echo "Installed systemd units."
echo ""
echo "Done. Next steps:"
echo " 1. Edit ${DATA_DIR}/${SERVICE}.toml"
echo " 2. Place TLS certs in ${DATA_DIR}/certs/"
echo " 3. systemctl enable --now ${SERVICE}"
echo " 4. systemctl enable --now ${SERVICE}-backup.timer"

View File

@@ -0,0 +1,25 @@
[Unit]
Description=MCNS Database Backup
[Service]
Type=oneshot
User=mcns
Group=mcns
ExecStart=/usr/local/bin/mcns snapshot --config /srv/mcns/mcns.toml
ExecStartPost=/usr/bin/find /srv/mcns/backups -name 'mcns-*.db' -mtime +30 -delete
# Security hardening
NoNewPrivileges=true
ProtectSystem=strict
ProtectHome=true
PrivateTmp=true
PrivateDevices=true
ProtectKernelTunables=true
ProtectKernelModules=true
ProtectControlGroups=true
RestrictSUIDSGID=true
RestrictNamespaces=true
LockPersonality=true
MemoryDenyWriteExecute=true
RestrictRealtime=true
ReadWritePaths=/srv/mcns

View File

@@ -0,0 +1,10 @@
[Unit]
Description=MCNS Daily Database Backup
[Timer]
OnCalendar=*-*-* 02:00:00 UTC
RandomizedDelaySec=300
Persistent=true
[Install]
WantedBy=timers.target

View File

@@ -0,0 +1,34 @@
[Unit]
Description=MCNS Networking Service
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=mcns
Group=mcns
ExecStart=/usr/local/bin/mcns server --config /srv/mcns/mcns.toml
Restart=on-failure
RestartSec=5
# Security hardening
NoNewPrivileges=true
ProtectSystem=strict
ProtectHome=true
PrivateTmp=true
PrivateDevices=true
ProtectKernelTunables=true
ProtectKernelModules=true
ProtectControlGroups=true
RestrictSUIDSGID=true
RestrictNamespaces=true
LockPersonality=true
MemoryDenyWriteExecute=true
RestrictRealtime=true
ReadWritePaths=/srv/mcns
# Allow binding to privileged ports (DNS port 53)
AmbientCapabilities=CAP_NET_BIND_SERVICE
[Install]
WantedBy=multi-user.target