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
+36 -9
View File
@@ -2,11 +2,12 @@
## Managed server deployment checkpoint
The .NET server preserves protocol v2 and the native schema/credentials. Publish the
Windows self-contained executable (no installed .NET runtime required):
The .NET server preserves protocol v2 and the native schema/credentials. Publish a
self-contained executable (no installed .NET runtime required):
```powershell
./dotnet/publish-server.ps1
./dotnet/publish-server.ps1 -Runtime linux-x64
./dotnet/artifacts/server/win-x64/VoiceCat.Server.exe --help
./dotnet/artifacts/server/win-x64/VoiceCat.Server.exe account add Operator --admin --data-dir ./voicecat-data
./dotnet/artifacts/server/win-x64/VoiceCat.Server.exe --data-dir ./voicecat-data --allow-guests false
@@ -42,6 +43,8 @@ Bind accepts IP literals; IPv6 listeners are IPv6-only. Open/forward both protoc
An exclusive data-directory instance lock prevents duplicate managed server processes.
Ctrl+C and Unix SIGINT/SIGTERM stop all transport tasks; shutdown has a ten-second deadline.
Fatal listener/media/reaper failure exits the host rather than leaving a broken listener.
`--health-check HOST:PORT` performs a real protocol TLS 1.3 handshake and emits JSON.
Automation can add `--expect-fingerprint SHA256` to verify the persisted certificate.
Password authentication is limited before Argon2 by source address and username across
connections: burst 5, refill one attempt per ten seconds. Starting at three failed attempts,
@@ -49,11 +52,32 @@ backoff grows from one to thirty seconds. Success clears backoff but does not re
tokens. State is bounded to 4096 keys; idle entries retire after ten minutes when full.
Throttle and credential failures share the generic auth error. Limits are process-local.
The publish script uses separate runtime lock files so deployment and development restore
graphs remain reproducible. The checked deployment target is currently Windows x64;
Linux container publishing, service packaging, TOML/reload support and long-running
operational validation remain before broad production rollout. The native deployment
paths and planned operational features below remain available as the migration oracle.
The publish script uses separate per-RID lock files so deployment and development restore
graphs remain reproducible. Windows x64 and Linux x64 self-contained outputs are checked.
The Linux smoke starts the published ELF, validates TLS health and the pin, checks mode 0700
data creation, sends SIGTERM and requires a clean exit:
```bash
sh deploy/linux/smoke.sh dotnet/artifacts/server/linux-x64/VoiceCat.Server
```
`deploy/linux/voicecat.service` runs under a systemd dynamic user with a private state
directory, no capabilities and filesystem/kernel hardening. Install a published binary and
the unit from `deploy/linux/` as root, or use the helper there. The default Dockerfile now
builds the managed server with locked packages and runs it as UID 1654 in Microsoft's
chiseled .NET runtime-dependencies image. Compose drops all capabilities, sets the root
filesystem read-only and persists only `/data`.
For operational endurance against an already running server:
```powershell
./dotnet/soak-server.ps1 -HostName 127.0.0.1 -Port 8384 -Minutes 30 -Pairs 4
```
Every cycle creates independent managed processes that exchange text and decoded voice.
A short 16-session published-server soak is part of this checkpoint. A release candidate
still needs the long soak on its target host. TOML/reload and signed image publication remain
before broad production rollout.
The product goal: someone looks at this and thinks *"oh, I (or my agent) can stand this up
in a few minutes."* Everything below is in service of that. Three install paths, all
@@ -64,11 +88,14 @@ in a few minutes."* Everything below is in service of that. Three install paths,
### A. Docker (recommended)
```bash
docker build -t voicecat:local .
docker run -d --name voicecat \
-p 8384:8384/tcp \ # control (TLS 1.3)
-p 8384:8384/udp \ # media (encrypted)
-v voicecat-data:/data \
ghcr.io/<org>/voicecat:latest
--read-only --tmpfs /tmp:rw,noexec,nosuid,size=16m \
--cap-drop ALL --security-opt no-new-privileges \
voicecat:local
```
That's the whole thing. On first start it generates its Ed25519 identity + self-signed
@@ -192,7 +219,7 @@ enabled).
## 5. Operational niceties (planned, not blocking v1)
- `voicecat-server --print-fingerprint` and a `/healthz` TCP check.
- Signed, multi-architecture image publication.
- Graceful reload of `server.toml` on `SIGHUP`.
- `voicecat-admin` (see §3a) also handles bans and channel admin, talking to the same SQLite
file or a running server.