(feature) Add full native installer and self-check page

Expand the systemd installer so it can perform a complete native
installation with sensible defaults: copy the checkout into the target
app directory, create runtime directories, write the environment file,
install dependencies, configure systemd units, and optionally configure
nginx.

Add a staff-only Django self-check page that verifies runtime settings,
required binaries, writable paths, database connectivity, global config
state, and systemd service status when available.

Document installer overrides and expose the self-check from the main
navigation.
This commit is contained in:
2026-05-19 16:05:03 +02:00
parent b93e19a7c8
commit 372a857f15
8 changed files with 370 additions and 13 deletions

View File

@@ -1,17 +1,67 @@
#!/bin/sh
set -eu
APP_DIR=${POBSYNC_APP_DIR:-$(CDPATH= cd -- "$(dirname -- "$0")/.." && pwd)}
SOURCE_DIR=${POBSYNC_SOURCE_DIR:-$(CDPATH= cd -- "$(dirname -- "$0")/.." && pwd)}
APP_DIR=${POBSYNC_APP_DIR:-/opt/pobsync/app}
VENV_DIR=${POBSYNC_VENV_DIR:-/opt/pobsync/venv}
ENV_FILE=${POBSYNC_ENV_FILE:-/etc/pobsync/pobsync.env}
SERVICE_USER=${POBSYNC_SERVICE_USER:-pobsync}
SERVICE_GROUP=${POBSYNC_SERVICE_GROUP:-pobsync}
INSTALL_EXTRAS=${POBSYNC_INSTALL_EXTRAS:-}
SERVER_NAME=${POBSYNC_SERVER_NAME:-_}
ALLOWED_HOSTS=${POBSYNC_ALLOWED_HOSTS:-localhost,127.0.0.1}
CSRF_TRUSTED_ORIGINS=${POBSYNC_CSRF_TRUSTED_ORIGINS:-}
BACKUP_ROOT=${POBSYNC_BACKUP_ROOT:-/backups}
WEB_BIND=${POBSYNC_WEB_BIND:-127.0.0.1:8010}
FORCE_ENV=0
WITH_NGINX=0
while [ "$#" -gt 0 ]; do
case "$1" in
--source-dir)
SOURCE_DIR=$2
shift 2
;;
--app-dir)
APP_DIR=$2
shift 2
;;
--venv-dir)
VENV_DIR=$2
shift 2
;;
--env-file)
ENV_FILE=$2
shift 2
;;
--service-user)
SERVICE_USER=$2
shift 2
;;
--service-group)
SERVICE_GROUP=$2
shift 2
;;
--backup-root)
BACKUP_ROOT=$2
shift 2
;;
--allowed-hosts)
ALLOWED_HOSTS=$2
shift 2
;;
--csrf-trusted-origins)
CSRF_TRUSTED_ORIGINS=$2
shift 2
;;
--web-bind)
WEB_BIND=$2
shift 2
;;
--force-env)
FORCE_ENV=1
shift
;;
--with-nginx)
WITH_NGINX=1
shift
@@ -47,6 +97,11 @@ if ! command -v ssh >/dev/null 2>&1; then
exit 1
fi
if [ ! -f "$SOURCE_DIR/manage.py" ]; then
echo "Source directory does not look like a pobsync checkout: $SOURCE_DIR" >&2
exit 1
fi
if ! getent group "$SERVICE_GROUP" >/dev/null 2>&1; then
groupadd --system "$SERVICE_GROUP"
fi
@@ -55,28 +110,39 @@ if ! id "$SERVICE_USER" >/dev/null 2>&1; then
useradd --system --home /var/lib/pobsync --shell /usr/sbin/nologin --gid "$SERVICE_GROUP" "$SERVICE_USER"
fi
mkdir -p /etc/pobsync /var/lib/pobsync /var/log/pobsync "$(dirname "$VENV_DIR")"
mkdir -p /etc/pobsync /var/lib/pobsync /var/log/pobsync "$(dirname "$VENV_DIR")" "$APP_DIR" "$BACKUP_ROOT"
chown "$SERVICE_USER:$SERVICE_GROUP" /var/lib/pobsync /var/log/pobsync
chmod 0750 /var/lib/pobsync /var/log/pobsync
if [ "$SOURCE_DIR" != "$APP_DIR" ]; then
rsync -a --delete \
--exclude .git \
--exclude .venv \
--exclude __pycache__ \
--exclude .pytest_cache \
--exclude .mypy_cache \
--exclude var \
"$SOURCE_DIR"/ "$APP_DIR"/
fi
python3 -m venv "$VENV_DIR"
"$VENV_DIR/bin/python" -m pip install --upgrade pip
"$VENV_DIR/bin/python" -m pip install -e "$APP_DIR$INSTALL_EXTRAS"
if [ ! -f "$ENV_FILE" ]; then
if [ ! -f "$ENV_FILE" ] || [ "$FORCE_ENV" -eq 1 ]; then
secret=$("$VENV_DIR/bin/python" -c "import secrets; print(secrets.token_urlsafe(48))")
cat > "$ENV_FILE" <<EOF
POBSYNC_DJANGO_DEBUG=0
POBSYNC_DJANGO_SECRET_KEY=$secret
POBSYNC_DJANGO_ALLOWED_HOSTS=localhost,127.0.0.1
POBSYNC_DJANGO_CSRF_TRUSTED_ORIGINS=
POBSYNC_DJANGO_ALLOWED_HOSTS=$ALLOWED_HOSTS
POBSYNC_DJANGO_CSRF_TRUSTED_ORIGINS=$CSRF_TRUSTED_ORIGINS
POBSYNC_HOME=/var/lib/pobsync
POBSYNC_BACKUP_ROOT=/backups
POBSYNC_BACKUP_ROOT=$BACKUP_ROOT
POBSYNC_SQLITE_PATH=/var/lib/pobsync/pobsync.sqlite3
POBSYNC_STATIC_ROOT=/var/lib/pobsync/static
POBSYNC_WEB_BIND=127.0.0.1:8010
POBSYNC_WEB_BIND=$WEB_BIND
POBSYNC_GUNICORN_WORKERS=2
POBSYNC_GUNICORN_TIMEOUT=120
POBSYNC_WORKER_INTERVAL=15
@@ -84,7 +150,9 @@ POBSYNC_SCHEDULER_INTERVAL=60
EOF
chmod 0640 "$ENV_FILE"
chown "root:$SERVICE_GROUP" "$ENV_FILE"
echo "Created $ENV_FILE. Edit allowed hosts and backup root before exposing the service."
echo "Wrote $ENV_FILE."
else
echo "Keeping existing $ENV_FILE. Use --force-env to rewrite it."
fi
install_unit() {