Package managed server for Linux production
.NET port / test (macos-latest) (push) Canceled after 0s
.NET port / test (ubuntu-24.04) (push) Canceled after 0s
.NET port / test (windows-latest) (push) Canceled after 0s
.NET port / cpp-conformance (push) Canceled after 0s

This commit is contained in:
2026-09-16 17:08:17 +02:00
parent 48c754aed9
commit 7be93e81a1
15 changed files with 384 additions and 119 deletions
+7
View File
@@ -0,0 +1,7 @@
#!/bin/sh
set -eu
install -d -m 0755 /usr/local/lib/voicecat
install -m 0755 VoiceCat.Server /usr/local/lib/voicecat/VoiceCat.Server
install -m 0644 voicecat.service /etc/systemd/system/voicecat.service
systemctl daemon-reload
systemctl enable --now voicecat.service
+23
View File
@@ -0,0 +1,23 @@
#!/bin/sh
set -eu
server=${1:-./VoiceCat.Server}
work=$(mktemp -d)
pid=
cleanup() { if [ -n "${pid}" ] && kill -0 "$pid" 2>/dev/null; then kill -TERM "$pid"; wait "$pid" || true; fi; rm -rf "$work"; }
trap cleanup EXIT INT TERM
"$server" --data-dir "$work/data" --bind 127.0.0.1 --port 0 >"$work/server.log" 2>"$work/server.err" &
pid=$!
i=0
while ! grep -q '"event":"ready"' "$work/server.log"; do
if ! kill -0 "$pid" 2>/dev/null; then cat "$work/server.err" >&2; exit 1; fi
i=$((i + 1)); [ "$i" -lt 100 ] || { echo "server readiness timeout" >&2; exit 1; }
sleep 0.1
done
port=$(sed -n 's/.*"port":\([0-9][0-9]*\).*/\1/p' "$work/server.log" | head -n 1)
fingerprint=$(sed -n 's/.*"certificate_fingerprint":"\([0-9A-F]*\)".*/\1/p' "$work/server.log" | head -n 1)
"$server" --health-check "127.0.0.1:$port" --expect-fingerprint "$fingerprint" | grep -q '"status":"healthy"'
[ "$(stat -c '%a' "$work/data")" = 700 ]
kill -TERM "$pid"
wait "$pid"
pid=
echo "Linux publish startup, TLS health, private data permissions and SIGTERM shutdown passed."
+29 -13
View File
@@ -1,23 +1,39 @@
[Unit]
Description=VoiceCat Voice & Text Server
Documentation=https://github.com/org/voicecat
After=network.target
Description=VoiceCat encrypted voice server
Documentation=https://github.com/Talon/voice-cat/blob/main/docs/deployment.md
Wants=network-online.target
After=network-online.target
[Service]
Type=simple
User=voicecat
Group=voicecat
ExecStart=/usr/local/bin/voicecat-server --data-dir /var/lib/voicecat
DynamicUser=yes
StateDirectory=voicecat
StateDirectoryMode=0700
ExecStart=/usr/local/lib/voicecat/VoiceCat.Server --data-dir /var/lib/voicecat
Restart=on-failure
RestartSec=5s
# Allow binding port 8384 without running as root
AmbientCapabilities=CAP_NET_BIND_SERVICE
# Harden the process
NoNewPrivileges=true
TimeoutStopSec=15s
NoNewPrivileges=yes
PrivateDevices=yes
PrivateTmp=yes
ProtectSystem=strict
ProtectHome=true
ReadWritePaths=/var/lib/voicecat
PrivateTmp=true
ProtectHome=yes
ProtectKernelTunables=yes
ProtectKernelModules=yes
ProtectKernelLogs=yes
ProtectControlGroups=yes
ProtectClock=yes
ProtectHostname=yes
ProtectProc=invisible
ProcSubset=pid
RestrictSUIDSGID=yes
RestrictRealtime=yes
LockPersonality=yes
MemoryDenyWriteExecute=yes
SystemCallArchitectures=native
CapabilityBoundingSet=
AmbientCapabilities=
UMask=0077
[Install]
WantedBy=multi-user.target