diff --git a/deploy/scripts/install.sh b/deploy/scripts/install.sh new file mode 100755 index 0000000..ff4dc69 --- /dev/null +++ b/deploy/scripts/install.sh @@ -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" diff --git a/deploy/systemd/mcns-backup.service b/deploy/systemd/mcns-backup.service new file mode 100644 index 0000000..f3f3841 --- /dev/null +++ b/deploy/systemd/mcns-backup.service @@ -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 diff --git a/deploy/systemd/mcns-backup.timer b/deploy/systemd/mcns-backup.timer new file mode 100644 index 0000000..3edbcf5 --- /dev/null +++ b/deploy/systemd/mcns-backup.timer @@ -0,0 +1,10 @@ +[Unit] +Description=MCNS Daily Database Backup + +[Timer] +OnCalendar=*-*-* 02:00:00 UTC +RandomizedDelaySec=300 +Persistent=true + +[Install] +WantedBy=timers.target diff --git a/deploy/systemd/mcns.service b/deploy/systemd/mcns.service new file mode 100644 index 0000000..af261c0 --- /dev/null +++ b/deploy/systemd/mcns.service @@ -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