feat: apt-based deployment via Gitea Debian registry

Deklarix now ships as a .deb package instead of a raw binary, matching
the enconf-webpanel infrastructure standard: scripts/build.sh assembles
a real .deb (systemd unit, env template, postinst/prerm), scripts/release.sh
uploads it to Gitea's built-in Debian package registry after a green
test run. Target servers add one apt source and get updates via
`apt upgrade` from then on.

postinst only starts the service once DATABASE_URL is actually set in
/etc/deklarix/deklarix.env — the shipped template ships it commented out
on purpose, since an uncommented but unfilled placeholder URL is
syntactically indistinguishable from a real one and caused exactly that
crash-loop during verification.

Verified end-to-end against the real test server and Gitea registry:
upload -> apt-get update -> apt-cache policy -> apt-get install -> a
service that stays down until configured, then runs migrations and
serves /health once a real database is set.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
noroot
2026-08-27 13:34:58 +02:00
parent e929e5bf26
commit 8b08b39725
9 changed files with 255 additions and 37 deletions

View File

@@ -0,0 +1 @@
/etc/deklarix/deklarix.env.example

View File

@@ -2,6 +2,10 @@ Package: deklarix
Version: VERSION
Architecture: ARCH
Maintainer: NetCell IT <team@netcell-it.de>
Description: Deklarix — deklarix.de / deklarix.com
Deklarix Software Package.
Depends:
Homepage: https://deklarix.de
Section: web
Priority: optional
Depends: ca-certificates
Description: Deklarix — Prüfung und Nachweis für Werbe-Content
Pre-Publish-Kennzeichnungsprüfung und revisionssichere Archivierung
veröffentlichter Beiträge für Creator, Agenturen, Marken und Kanzleien.

65
packaging/DEBIAN/postinst Executable file
View File

@@ -0,0 +1,65 @@
#!/bin/bash
# Deklarix — postinst
set -e
SERVICE_USER="deklarix"
CONFIG_DIR="/etc/deklarix"
DATA_DIR="/var/lib/deklarix"
LOG_DIR="/var/log/deklarix"
case "$1" in
configure)
# ─── apt-Quelle einrichten/aktualisieren ────────────────────
# Gleiches Muster wie enconf: Gitea-Debian-Registry, Suite =
# OS-Codename, Komponente = Kanal (aktuell nur "testing"). Ein
# bereits gewählter Kanal bleibt über Upgrades hinweg erhalten.
mkdir -p /etc/apt/keyrings
curl -fsSL "https://git.netcell-it.de/api/packages/projekte/debian/repository.key" \
-o /etc/apt/keyrings/deklarix-gitea.asc 2>/dev/null || true
if [ -f /etc/apt/keyrings/deklarix-gitea.asc ]; then
DX_CODENAME="$(. /etc/os-release 2>/dev/null; echo "${VERSION_CODENAME:-}")"
case "$DX_CODENAME" in bookworm|trixie) ;; *) DX_CODENAME="trixie" ;; esac
DX_CHANNEL="$(grep -oE 'projekte/debian[[:space:]]+[a-z]+[[:space:]]+(stable|testing)' \
/etc/apt/sources.list.d/deklarix.list 2>/dev/null | awk '{print $NF}' | head -1)"
case "$DX_CHANNEL" in stable|testing) ;; *) DX_CHANNEL="testing" ;; esac
echo "deb [signed-by=/etc/apt/keyrings/deklarix-gitea.asc] https://git.netcell-it.de/api/packages/projekte/debian $DX_CODENAME $DX_CHANNEL" \
> /etc/apt/sources.list.d/deklarix.list
fi
# ─── System-User + Verzeichnisse ────────────────────────────
if ! id -u "$SERVICE_USER" >/dev/null 2>&1; then
useradd -r -s /usr/sbin/nologin -d "$DATA_DIR" "$SERVICE_USER"
fi
mkdir -p "$DATA_DIR" "$LOG_DIR" "$CONFIG_DIR"
chown "$SERVICE_USER:$SERVICE_USER" "$DATA_DIR" "$LOG_DIR"
# ─── Konfiguration ───────────────────────────────────────────
# Erstinstall: Vorlage kopieren, nicht scharf schalten (Secrets
# fehlen noch). Upgrade: bestehende deklarix.env bleibt unberührt.
if [ ! -f "$CONFIG_DIR/deklarix.env" ]; then
cp "$CONFIG_DIR/deklarix.env.example" "$CONFIG_DIR/deklarix.env"
chmod 640 "$CONFIG_DIR/deklarix.env"
chown "root:$SERVICE_USER" "$CONFIG_DIR/deklarix.env"
fi
systemctl daemon-reload 2>/dev/null || true
systemctl enable deklarix.service >/dev/null 2>&1 || true
# Nicht blind starten — ohne gesetzte DATABASE_URL würde der Dienst
# nur in eine Restart-Schleife laufen (main.go bricht sonst bewusst
# mit log.Fatal ab, siehe CLAUDE.md "keine stillen Fallbacks"). Die
# Vorlage liefert DATABASE_URL auskommentiert aus — ein Treffer hier
# bedeutet also wirklich "vom Admin gesetzt", nicht den Platzhalter.
if grep -qE '^DATABASE_URL=.+' "$CONFIG_DIR/deklarix.env" 2>/dev/null; then
systemctl restart deklarix.service
else
echo ""
echo " → Deklarix installiert, aber noch nicht gestartet."
echo " DATABASE_URL in $CONFIG_DIR/deklarix.env setzen, dann:"
echo " systemctl start deklarix"
echo ""
fi
;;
esac
exit 0

11
packaging/DEBIAN/prerm Executable file
View File

@@ -0,0 +1,11 @@
#!/bin/bash
# Deklarix — prerm
set -e
case "$1" in
remove|deconfigure)
systemctl stop deklarix.service 2>/dev/null || true
;;
esac
exit 0

View File

@@ -0,0 +1,15 @@
# Deklarix — Konfiguration
# Wird bei der Erstinstallation nach /etc/deklarix/deklarix.env kopiert.
# Diese Datei selbst wird von apt-Updates verwaltet — Anpassungen gehören
# in deklarix.env, nicht hierhin.
PORT=8080
# Pflicht — der Dienst startet nicht ohne gültige DATABASE_URL. Auskommentiert
# lassen, bis eine echte Postgres-Verbindung eingetragen ist: postinst prüft
# genau diese Zeile, um den Dienst nicht blind in eine Restart-Schleife gegen
# einen Platzhalter-Host laufen zu lassen.
#DATABASE_URL=postgres://user:password@host:5432/deklarix?sslmode=require
# Für internal/extract (Claude-API-Extraktion), sobald angebunden.
#ANTHROPIC_API_KEY=

View File

@@ -0,0 +1,23 @@
[Unit]
Description=Deklarix
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=deklarix
Group=deklarix
EnvironmentFile=/etc/deklarix/deklarix.env
ExecStart=/usr/bin/deklarix
WorkingDirectory=/var/lib/deklarix
Restart=on-failure
RestartSec=5
NoNewPrivileges=true
ProtectSystem=strict
ProtectHome=true
PrivateTmp=true
ReadWritePaths=/var/lib/deklarix /var/log/deklarix
[Install]
WantedBy=multi-user.target