2026-05-19 15:59:07 +02:00
|
|
|
#!/bin/sh
|
|
|
|
|
set -eu
|
|
|
|
|
|
(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.
2026-05-19 16:05:03 +02:00
|
|
|
SOURCE_DIR=${POBSYNC_SOURCE_DIR:-$(CDPATH= cd -- "$(dirname -- "$0")/.." && pwd)}
|
|
|
|
|
APP_DIR=${POBSYNC_APP_DIR:-/opt/pobsync/app}
|
2026-05-19 15:59:07 +02:00
|
|
|
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:-_}
|
(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.
2026-05-19 16:05:03 +02:00
|
|
|
ALLOWED_HOSTS=${POBSYNC_ALLOWED_HOSTS:-localhost,127.0.0.1}
|
|
|
|
|
CSRF_TRUSTED_ORIGINS=${POBSYNC_CSRF_TRUSTED_ORIGINS:-}
|
|
|
|
|
BACKUP_ROOT=${POBSYNC_BACKUP_ROOT:-/backups}
|
2026-05-19 19:25:05 +02:00
|
|
|
BACKUP_ROOT_EXPLICIT=0
|
|
|
|
|
if [ -n "${POBSYNC_BACKUP_ROOT:-}" ]; then
|
|
|
|
|
BACKUP_ROOT_EXPLICIT=1
|
|
|
|
|
fi
|
(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.
2026-05-19 16:05:03 +02:00
|
|
|
WEB_BIND=${POBSYNC_WEB_BIND:-127.0.0.1:8010}
|
|
|
|
|
FORCE_ENV=0
|
2026-05-19 18:15:34 +02:00
|
|
|
INSTALL_OS_PACKAGES=1
|
2026-05-19 15:59:07 +02:00
|
|
|
WITH_NGINX=0
|
2026-05-19 18:52:31 +02:00
|
|
|
VERBOSE=0
|
(feature) Make the native installer interactive
Add an interactive setup flow to the systemd installer with defaults
for install paths, service identity, backup storage, bind address,
allowed hosts, CSRF origins, OS package installation, MariaDB support,
nginx setup, and first superuser creation.
Keep scripted installs supported through non-interactive mode, existing
overrides, environment variables, and explicit superuser flags.
Print a user-facing completion summary with the control panel URL,
Self Check reminder, first setup steps, and useful service log commands.
2026-05-19 18:22:18 +02:00
|
|
|
INTERACTIVE=0
|
|
|
|
|
CREATE_SUPERUSER=ask
|
|
|
|
|
SUPERUSER_USERNAME=${POBSYNC_SUPERUSER_USERNAME:-}
|
|
|
|
|
SUPERUSER_EMAIL=${POBSYNC_SUPERUSER_EMAIL:-}
|
|
|
|
|
SUPERUSER_PASSWORD=${POBSYNC_SUPERUSER_PASSWORD:-}
|
|
|
|
|
|
|
|
|
|
if [ -t 0 ]; then
|
|
|
|
|
INTERACTIVE=1
|
|
|
|
|
fi
|
2026-05-19 15:59:07 +02:00
|
|
|
|
|
|
|
|
while [ "$#" -gt 0 ]; do
|
|
|
|
|
case "$1" in
|
(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.
2026-05-19 16:05:03 +02:00
|
|
|
--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
|
2026-05-19 19:25:05 +02:00
|
|
|
BACKUP_ROOT_EXPLICIT=1
|
(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.
2026-05-19 16:05:03 +02:00
|
|
|
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
|
|
|
|
|
;;
|
2026-05-19 18:52:31 +02:00
|
|
|
--verbose)
|
|
|
|
|
VERBOSE=1
|
|
|
|
|
shift
|
|
|
|
|
;;
|
(feature) Make the native installer interactive
Add an interactive setup flow to the systemd installer with defaults
for install paths, service identity, backup storage, bind address,
allowed hosts, CSRF origins, OS package installation, MariaDB support,
nginx setup, and first superuser creation.
Keep scripted installs supported through non-interactive mode, existing
overrides, environment variables, and explicit superuser flags.
Print a user-facing completion summary with the control panel URL,
Self Check reminder, first setup steps, and useful service log commands.
2026-05-19 18:22:18 +02:00
|
|
|
--interactive)
|
|
|
|
|
INTERACTIVE=1
|
|
|
|
|
shift
|
|
|
|
|
;;
|
|
|
|
|
--non-interactive)
|
|
|
|
|
INTERACTIVE=0
|
|
|
|
|
shift
|
|
|
|
|
;;
|
2026-05-19 18:15:34 +02:00
|
|
|
--no-install-os-packages)
|
|
|
|
|
INSTALL_OS_PACKAGES=0
|
|
|
|
|
shift
|
|
|
|
|
;;
|
|
|
|
|
--install-extras)
|
|
|
|
|
INSTALL_EXTRAS=$2
|
|
|
|
|
shift 2
|
|
|
|
|
;;
|
2026-05-19 15:59:07 +02:00
|
|
|
--with-nginx)
|
|
|
|
|
WITH_NGINX=1
|
|
|
|
|
shift
|
|
|
|
|
;;
|
|
|
|
|
--server-name)
|
|
|
|
|
SERVER_NAME=$2
|
|
|
|
|
shift 2
|
|
|
|
|
;;
|
(feature) Make the native installer interactive
Add an interactive setup flow to the systemd installer with defaults
for install paths, service identity, backup storage, bind address,
allowed hosts, CSRF origins, OS package installation, MariaDB support,
nginx setup, and first superuser creation.
Keep scripted installs supported through non-interactive mode, existing
overrides, environment variables, and explicit superuser flags.
Print a user-facing completion summary with the control panel URL,
Self Check reminder, first setup steps, and useful service log commands.
2026-05-19 18:22:18 +02:00
|
|
|
--create-superuser)
|
|
|
|
|
CREATE_SUPERUSER=1
|
|
|
|
|
shift
|
|
|
|
|
;;
|
|
|
|
|
--no-create-superuser)
|
|
|
|
|
CREATE_SUPERUSER=0
|
|
|
|
|
shift
|
|
|
|
|
;;
|
|
|
|
|
--superuser-username)
|
|
|
|
|
SUPERUSER_USERNAME=$2
|
|
|
|
|
shift 2
|
|
|
|
|
;;
|
|
|
|
|
--superuser-email)
|
|
|
|
|
SUPERUSER_EMAIL=$2
|
|
|
|
|
shift 2
|
|
|
|
|
;;
|
|
|
|
|
--superuser-password)
|
|
|
|
|
SUPERUSER_PASSWORD=$2
|
|
|
|
|
shift 2
|
|
|
|
|
;;
|
2026-05-19 15:59:07 +02:00
|
|
|
*)
|
|
|
|
|
echo "Unknown argument: $1" >&2
|
|
|
|
|
exit 2
|
|
|
|
|
;;
|
|
|
|
|
esac
|
|
|
|
|
done
|
|
|
|
|
|
|
|
|
|
if [ "$(id -u)" -ne 0 ]; then
|
|
|
|
|
echo "Run this installer as root." >&2
|
|
|
|
|
exit 1
|
|
|
|
|
fi
|
|
|
|
|
|
2026-05-19 19:25:05 +02:00
|
|
|
if [ -f "$ENV_FILE" ] && [ "$FORCE_ENV" -ne 1 ] && [ "$BACKUP_ROOT_EXPLICIT" -ne 1 ]; then
|
|
|
|
|
set -a
|
|
|
|
|
# shellcheck disable=SC1090
|
|
|
|
|
. "$ENV_FILE"
|
|
|
|
|
set +a
|
|
|
|
|
if [ -n "${POBSYNC_BACKUP_ROOT:-}" ]; then
|
|
|
|
|
BACKUP_ROOT=$POBSYNC_BACKUP_ROOT
|
|
|
|
|
fi
|
|
|
|
|
fi
|
|
|
|
|
|
2026-05-19 18:52:31 +02:00
|
|
|
run_step() {
|
|
|
|
|
label=$1
|
|
|
|
|
shift
|
|
|
|
|
|
|
|
|
|
if [ "$VERBOSE" -eq 1 ]; then
|
|
|
|
|
echo "==> $label"
|
|
|
|
|
"$@"
|
|
|
|
|
echo "OK: $label"
|
|
|
|
|
return
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
printf '%-48s' "$label"
|
|
|
|
|
log_file=$(mktemp)
|
|
|
|
|
if "$@" >"$log_file" 2>&1; then
|
|
|
|
|
rm -f "$log_file"
|
|
|
|
|
echo "OK"
|
|
|
|
|
return
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
echo "FAILED"
|
|
|
|
|
echo
|
|
|
|
|
echo "Output from failed step '$label':" >&2
|
|
|
|
|
cat "$log_file" >&2
|
|
|
|
|
rm -f "$log_file"
|
|
|
|
|
exit 1
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
note_step() {
|
|
|
|
|
label=$1
|
|
|
|
|
status=$2
|
|
|
|
|
printf '%-48s%s\n' "$label" "$status"
|
|
|
|
|
}
|
|
|
|
|
|
(feature) Make the native installer interactive
Add an interactive setup flow to the systemd installer with defaults
for install paths, service identity, backup storage, bind address,
allowed hosts, CSRF origins, OS package installation, MariaDB support,
nginx setup, and first superuser creation.
Keep scripted installs supported through non-interactive mode, existing
overrides, environment variables, and explicit superuser flags.
Print a user-facing completion summary with the control panel URL,
Self Check reminder, first setup steps, and useful service log commands.
2026-05-19 18:22:18 +02:00
|
|
|
prompt_value() {
|
|
|
|
|
prompt=$1
|
|
|
|
|
default=$2
|
|
|
|
|
if [ "$INTERACTIVE" -ne 1 ]; then
|
|
|
|
|
printf '%s\n' "$default"
|
|
|
|
|
return
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
printf '%s [%s]: ' "$prompt" "$default" >&2
|
|
|
|
|
read -r answer
|
|
|
|
|
if [ -n "$answer" ]; then
|
|
|
|
|
printf '%s\n' "$answer"
|
|
|
|
|
else
|
|
|
|
|
printf '%s\n' "$default"
|
|
|
|
|
fi
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
prompt_yes_no() {
|
|
|
|
|
prompt=$1
|
|
|
|
|
default=$2
|
|
|
|
|
if [ "$INTERACTIVE" -ne 1 ]; then
|
|
|
|
|
printf '%s\n' "$default"
|
|
|
|
|
return
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
if [ "$default" -eq 1 ]; then
|
|
|
|
|
suffix=Y/n
|
|
|
|
|
else
|
|
|
|
|
suffix=y/N
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
while :; do
|
|
|
|
|
printf '%s [%s]: ' "$prompt" "$suffix" >&2
|
|
|
|
|
read -r answer
|
|
|
|
|
case "$answer" in
|
|
|
|
|
"")
|
|
|
|
|
printf '%s\n' "$default"
|
|
|
|
|
return
|
|
|
|
|
;;
|
|
|
|
|
y|Y|yes|YES|Yes)
|
|
|
|
|
printf '1\n'
|
|
|
|
|
return
|
|
|
|
|
;;
|
|
|
|
|
n|N|no|NO|No)
|
|
|
|
|
printf '0\n'
|
|
|
|
|
return
|
|
|
|
|
;;
|
|
|
|
|
esac
|
|
|
|
|
done
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
prompt_secret() {
|
|
|
|
|
prompt=$1
|
|
|
|
|
if [ "$INTERACTIVE" -ne 1 ]; then
|
|
|
|
|
printf '\n'
|
|
|
|
|
return
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
printf '%s: ' "$prompt" >&2
|
|
|
|
|
stty -echo
|
|
|
|
|
read -r secret
|
|
|
|
|
stty echo
|
|
|
|
|
printf '\n' >&2
|
|
|
|
|
printf '%s\n' "$secret"
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if [ "$INTERACTIVE" -eq 1 ]; then
|
|
|
|
|
echo "pobsync native installer"
|
|
|
|
|
echo
|
|
|
|
|
echo "Press Enter to accept defaults. Existing command-line flags are already applied as defaults."
|
|
|
|
|
echo
|
|
|
|
|
|
|
|
|
|
SOURCE_DIR=$(prompt_value "Source checkout" "$SOURCE_DIR")
|
|
|
|
|
APP_DIR=$(prompt_value "Install app directory" "$APP_DIR")
|
|
|
|
|
VENV_DIR=$(prompt_value "Python virtualenv directory" "$VENV_DIR")
|
|
|
|
|
ENV_FILE=$(prompt_value "Environment file" "$ENV_FILE")
|
|
|
|
|
SERVICE_USER=$(prompt_value "Service user" "$SERVICE_USER")
|
|
|
|
|
SERVICE_GROUP=$(prompt_value "Service group" "$SERVICE_GROUP")
|
|
|
|
|
BACKUP_ROOT=$(prompt_value "Backup storage path" "$BACKUP_ROOT")
|
|
|
|
|
WEB_BIND=$(prompt_value "Gunicorn bind address" "$WEB_BIND")
|
|
|
|
|
ALLOWED_HOSTS=$(prompt_value "Allowed hosts" "$ALLOWED_HOSTS")
|
|
|
|
|
CSRF_TRUSTED_ORIGINS=$(prompt_value "CSRF trusted origins, comma-separated or blank" "$CSRF_TRUSTED_ORIGINS")
|
|
|
|
|
INSTALL_OS_PACKAGES=$(prompt_yes_no "Install required OS packages with apt-get" "$INSTALL_OS_PACKAGES")
|
|
|
|
|
|
|
|
|
|
use_mariadb=0
|
|
|
|
|
if [ "$INSTALL_EXTRAS" = "mariadb" ] || [ "$INSTALL_EXTRAS" = "[mariadb]" ] || [ "$INSTALL_EXTRAS" = ".[mariadb]" ]; then
|
|
|
|
|
use_mariadb=1
|
|
|
|
|
fi
|
|
|
|
|
use_mariadb=$(prompt_yes_no "Install MariaDB Python/client support" "$use_mariadb")
|
|
|
|
|
if [ "$use_mariadb" -eq 1 ]; then
|
|
|
|
|
INSTALL_EXTRAS=mariadb
|
|
|
|
|
else
|
|
|
|
|
INSTALL_EXTRAS=
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
WITH_NGINX=$(prompt_yes_no "Install starter nginx reverse proxy config" "$WITH_NGINX")
|
|
|
|
|
if [ "$WITH_NGINX" -eq 1 ]; then
|
|
|
|
|
SERVER_NAME=$(prompt_value "Nginx server_name" "$SERVER_NAME")
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
if [ "$CREATE_SUPERUSER" = "ask" ]; then
|
|
|
|
|
CREATE_SUPERUSER=$(prompt_yes_no "Create first Django superuser after install" 1)
|
|
|
|
|
fi
|
|
|
|
|
if [ "$CREATE_SUPERUSER" -eq 1 ]; then
|
|
|
|
|
SUPERUSER_USERNAME=$(prompt_value "Superuser username" "${SUPERUSER_USERNAME:-admin}")
|
|
|
|
|
SUPERUSER_EMAIL=$(prompt_value "Superuser email, blank allowed" "$SUPERUSER_EMAIL")
|
|
|
|
|
if [ -z "$SUPERUSER_PASSWORD" ]; then
|
|
|
|
|
SUPERUSER_PASSWORD=$(prompt_secret "Superuser password, leave blank to run createsuperuser interactively later")
|
|
|
|
|
fi
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
echo
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
if [ "$CREATE_SUPERUSER" = "ask" ]; then
|
|
|
|
|
if [ -n "$SUPERUSER_USERNAME" ] && [ -n "$SUPERUSER_PASSWORD" ]; then
|
|
|
|
|
CREATE_SUPERUSER=1
|
|
|
|
|
else
|
|
|
|
|
CREATE_SUPERUSER=0
|
|
|
|
|
fi
|
|
|
|
|
fi
|
|
|
|
|
|
2026-05-19 18:15:34 +02:00
|
|
|
install_os_packages() {
|
|
|
|
|
if [ "$INSTALL_OS_PACKAGES" -ne 1 ]; then
|
2026-05-19 18:52:31 +02:00
|
|
|
note_step "Install OS packages" "SKIPPED"
|
2026-05-19 18:15:34 +02:00
|
|
|
return
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
if command -v apt-get >/dev/null 2>&1; then
|
|
|
|
|
packages="python3 python3-venv python3-pip rsync openssh-client"
|
|
|
|
|
if [ "$WITH_NGINX" -eq 1 ]; then
|
|
|
|
|
packages="$packages nginx"
|
|
|
|
|
fi
|
|
|
|
|
if [ "$INSTALL_EXTRAS" = "mariadb" ] || [ "$INSTALL_EXTRAS" = "[mariadb]" ] || [ "$INSTALL_EXTRAS" = ".[mariadb]" ]; then
|
|
|
|
|
packages="$packages default-libmysqlclient-dev build-essential pkg-config"
|
|
|
|
|
fi
|
2026-05-19 18:52:31 +02:00
|
|
|
run_step "Install OS packages" sh -c "apt-get update && apt-get install -y --no-install-recommends $packages"
|
2026-05-19 18:15:34 +02:00
|
|
|
return
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
echo "No supported package manager found; install python3, python3-venv, rsync, and openssh-client manually." >&2
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
install_os_packages
|
|
|
|
|
|
2026-05-19 15:59:07 +02:00
|
|
|
if ! command -v python3 >/dev/null 2>&1; then
|
|
|
|
|
echo "python3 is required." >&2
|
|
|
|
|
exit 1
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
if ! command -v rsync >/dev/null 2>&1; then
|
|
|
|
|
echo "rsync is required." >&2
|
|
|
|
|
exit 1
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
if ! command -v ssh >/dev/null 2>&1; then
|
|
|
|
|
echo "openssh-client is required." >&2
|
|
|
|
|
exit 1
|
|
|
|
|
fi
|
|
|
|
|
|
(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.
2026-05-19 16:05:03 +02:00
|
|
|
if [ ! -f "$SOURCE_DIR/manage.py" ]; then
|
|
|
|
|
echo "Source directory does not look like a pobsync checkout: $SOURCE_DIR" >&2
|
|
|
|
|
exit 1
|
|
|
|
|
fi
|
|
|
|
|
|
2026-05-19 15:59:07 +02:00
|
|
|
if ! getent group "$SERVICE_GROUP" >/dev/null 2>&1; then
|
2026-05-19 18:52:31 +02:00
|
|
|
run_step "Create service group" groupadd --system "$SERVICE_GROUP"
|
|
|
|
|
else
|
|
|
|
|
note_step "Create service group" "OK"
|
2026-05-19 15:59:07 +02:00
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
if ! id "$SERVICE_USER" >/dev/null 2>&1; then
|
2026-05-19 18:52:31 +02:00
|
|
|
run_step "Create service user" useradd --system --home /var/lib/pobsync --shell /usr/sbin/nologin --gid "$SERVICE_GROUP" "$SERVICE_USER"
|
|
|
|
|
else
|
|
|
|
|
note_step "Create service user" "OK"
|
2026-05-19 15:59:07 +02:00
|
|
|
fi
|
|
|
|
|
|
2026-05-19 19:25:05 +02:00
|
|
|
grant_journal_access() {
|
|
|
|
|
for group in systemd-journal adm; do
|
|
|
|
|
if getent group "$group" >/dev/null 2>&1; then
|
|
|
|
|
usermod -a -G "$group" "$SERVICE_USER"
|
|
|
|
|
fi
|
|
|
|
|
done
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
run_step "Grant journal access" grant_journal_access
|
2026-05-19 18:52:31 +02:00
|
|
|
run_step "Prepare directories" mkdir -p /etc/pobsync /var/lib/pobsync /var/log/pobsync "$(dirname "$VENV_DIR")" "$APP_DIR" "$BACKUP_ROOT"
|
2026-05-19 19:11:57 +02:00
|
|
|
run_step "Set state directory permissions" chown "$SERVICE_USER:$SERVICE_GROUP" /var/lib/pobsync /var/log/pobsync "$BACKUP_ROOT"
|
2026-05-19 19:25:05 +02:00
|
|
|
run_step "Set private directory modes" chmod 0750 /var/lib/pobsync /var/log/pobsync "$BACKUP_ROOT"
|
2026-05-19 15:59:07 +02:00
|
|
|
|
(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.
2026-05-19 16:05:03 +02:00
|
|
|
if [ "$SOURCE_DIR" != "$APP_DIR" ]; then
|
2026-05-19 18:52:31 +02:00
|
|
|
run_step "Sync application files" rsync -a --delete \
|
(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.
2026-05-19 16:05:03 +02:00
|
|
|
--exclude .git \
|
|
|
|
|
--exclude .venv \
|
|
|
|
|
--exclude __pycache__ \
|
|
|
|
|
--exclude .pytest_cache \
|
|
|
|
|
--exclude .mypy_cache \
|
|
|
|
|
--exclude var \
|
|
|
|
|
"$SOURCE_DIR"/ "$APP_DIR"/
|
2026-05-19 18:52:31 +02:00
|
|
|
else
|
|
|
|
|
note_step "Sync application files" "SKIPPED"
|
(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.
2026-05-19 16:05:03 +02:00
|
|
|
fi
|
|
|
|
|
|
2026-05-19 18:52:31 +02:00
|
|
|
run_step "Create Python virtualenv" python3 -m venv "$VENV_DIR"
|
|
|
|
|
run_step "Upgrade pip" "$VENV_DIR/bin/python" -m pip install --upgrade pip
|
2026-05-19 18:15:34 +02:00
|
|
|
case "$INSTALL_EXTRAS" in
|
|
|
|
|
"")
|
|
|
|
|
pip_target=$APP_DIR
|
|
|
|
|
;;
|
|
|
|
|
mariadb)
|
|
|
|
|
pip_target="$APP_DIR[mariadb]"
|
|
|
|
|
;;
|
|
|
|
|
\[*\])
|
|
|
|
|
pip_target="$APP_DIR$INSTALL_EXTRAS"
|
|
|
|
|
;;
|
|
|
|
|
.\[*\])
|
|
|
|
|
pip_target="$APP_DIR${INSTALL_EXTRAS#.}"
|
|
|
|
|
;;
|
|
|
|
|
*)
|
|
|
|
|
echo "Unsupported install extras: $INSTALL_EXTRAS" >&2
|
|
|
|
|
exit 2
|
|
|
|
|
;;
|
|
|
|
|
esac
|
2026-05-19 18:52:31 +02:00
|
|
|
run_step "Install Python package" "$VENV_DIR/bin/python" -m pip install -e "$pip_target"
|
2026-05-19 15:59:07 +02:00
|
|
|
|
(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.
2026-05-19 16:05:03 +02:00
|
|
|
if [ ! -f "$ENV_FILE" ] || [ "$FORCE_ENV" -eq 1 ]; then
|
2026-05-19 15:59:07 +02:00
|
|
|
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
|
(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.
2026-05-19 16:05:03 +02:00
|
|
|
POBSYNC_DJANGO_ALLOWED_HOSTS=$ALLOWED_HOSTS
|
|
|
|
|
POBSYNC_DJANGO_CSRF_TRUSTED_ORIGINS=$CSRF_TRUSTED_ORIGINS
|
2026-05-19 15:59:07 +02:00
|
|
|
|
|
|
|
|
POBSYNC_HOME=/var/lib/pobsync
|
(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.
2026-05-19 16:05:03 +02:00
|
|
|
POBSYNC_BACKUP_ROOT=$BACKUP_ROOT
|
2026-05-19 15:59:07 +02:00
|
|
|
POBSYNC_SQLITE_PATH=/var/lib/pobsync/pobsync.sqlite3
|
|
|
|
|
POBSYNC_STATIC_ROOT=/var/lib/pobsync/static
|
|
|
|
|
|
(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.
2026-05-19 16:05:03 +02:00
|
|
|
POBSYNC_WEB_BIND=$WEB_BIND
|
2026-05-19 15:59:07 +02:00
|
|
|
POBSYNC_GUNICORN_WORKERS=2
|
|
|
|
|
POBSYNC_GUNICORN_TIMEOUT=120
|
|
|
|
|
POBSYNC_WORKER_INTERVAL=15
|
|
|
|
|
POBSYNC_SCHEDULER_INTERVAL=60
|
|
|
|
|
EOF
|
|
|
|
|
chmod 0640 "$ENV_FILE"
|
|
|
|
|
chown "root:$SERVICE_GROUP" "$ENV_FILE"
|
2026-05-19 18:52:31 +02:00
|
|
|
note_step "Write environment file" "OK"
|
(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.
2026-05-19 16:05:03 +02:00
|
|
|
else
|
2026-05-19 18:52:31 +02:00
|
|
|
note_step "Write environment file" "SKIPPED"
|
(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.
2026-05-19 16:05:03 +02:00
|
|
|
echo "Keeping existing $ENV_FILE. Use --force-env to rewrite it."
|
2026-05-19 15:59:07 +02:00
|
|
|
fi
|
|
|
|
|
|
(feature) Make the native installer interactive
Add an interactive setup flow to the systemd installer with defaults
for install paths, service identity, backup storage, bind address,
allowed hosts, CSRF origins, OS package installation, MariaDB support,
nginx setup, and first superuser creation.
Keep scripted installs supported through non-interactive mode, existing
overrides, environment variables, and explicit superuser flags.
Print a user-facing completion summary with the control panel URL,
Self Check reminder, first setup steps, and useful service log commands.
2026-05-19 18:22:18 +02:00
|
|
|
set -a
|
|
|
|
|
# shellcheck disable=SC1090
|
|
|
|
|
. "$ENV_FILE"
|
|
|
|
|
set +a
|
|
|
|
|
|
2026-05-19 15:59:07 +02:00
|
|
|
install_unit() {
|
|
|
|
|
src=$1
|
|
|
|
|
dest=$2
|
|
|
|
|
sed \
|
|
|
|
|
-e "s|@POBSYNC_APP_DIR@|$APP_DIR|g" \
|
|
|
|
|
-e "s|@POBSYNC_VENV_DIR@|$VENV_DIR|g" \
|
|
|
|
|
-e "s|@POBSYNC_ENV_FILE@|$ENV_FILE|g" \
|
|
|
|
|
-e "s|@POBSYNC_USER@|$SERVICE_USER|g" \
|
|
|
|
|
-e "s|@POBSYNC_GROUP@|$SERVICE_GROUP|g" \
|
|
|
|
|
"$src" > "$dest"
|
|
|
|
|
chmod 0644 "$dest"
|
|
|
|
|
}
|
|
|
|
|
|
2026-05-19 18:52:31 +02:00
|
|
|
install_units() {
|
|
|
|
|
install_unit "$APP_DIR/deploy/systemd/pobsync-web.service" /etc/systemd/system/pobsync-web.service
|
|
|
|
|
install_unit "$APP_DIR/deploy/systemd/pobsync-worker.service" /etc/systemd/system/pobsync-worker.service
|
|
|
|
|
install_unit "$APP_DIR/deploy/systemd/pobsync-scheduler.service" /etc/systemd/system/pobsync-scheduler.service
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
run_step "Install systemd units" install_units
|
2026-05-19 15:59:07 +02:00
|
|
|
|
2026-05-19 18:52:31 +02:00
|
|
|
run_step "Reload systemd" systemctl daemon-reload
|
|
|
|
|
run_step "Run database migrations" "$VENV_DIR/bin/python" "$APP_DIR/manage.py" migrate --noinput
|
|
|
|
|
run_step "Collect static files" "$VENV_DIR/bin/python" "$APP_DIR/manage.py" collectstatic --noinput --clear
|
|
|
|
|
run_step "Finalize state permissions" chown -R "$SERVICE_USER:$SERVICE_GROUP" /var/lib/pobsync /var/log/pobsync
|
(feature) Make the native installer interactive
Add an interactive setup flow to the systemd installer with defaults
for install paths, service identity, backup storage, bind address,
allowed hosts, CSRF origins, OS package installation, MariaDB support,
nginx setup, and first superuser creation.
Keep scripted installs supported through non-interactive mode, existing
overrides, environment variables, and explicit superuser flags.
Print a user-facing completion summary with the control panel URL,
Self Check reminder, first setup steps, and useful service log commands.
2026-05-19 18:22:18 +02:00
|
|
|
|
|
|
|
|
superuser_exists=$("$VENV_DIR/bin/python" -c "import os; os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'pobsync_server.settings'); import django; django.setup(); from django.contrib.auth import get_user_model; print('yes' if get_user_model().objects.filter(is_superuser=True).exists() else 'no')")
|
|
|
|
|
if [ "$CREATE_SUPERUSER" -eq 1 ]; then
|
|
|
|
|
if [ "$superuser_exists" = "yes" ]; then
|
2026-05-19 18:52:31 +02:00
|
|
|
note_step "Create Django superuser" "SKIPPED"
|
(feature) Make the native installer interactive
Add an interactive setup flow to the systemd installer with defaults
for install paths, service identity, backup storage, bind address,
allowed hosts, CSRF origins, OS package installation, MariaDB support,
nginx setup, and first superuser creation.
Keep scripted installs supported through non-interactive mode, existing
overrides, environment variables, and explicit superuser flags.
Print a user-facing completion summary with the control panel URL,
Self Check reminder, first setup steps, and useful service log commands.
2026-05-19 18:22:18 +02:00
|
|
|
elif [ -n "$SUPERUSER_USERNAME" ] && [ -n "$SUPERUSER_PASSWORD" ]; then
|
2026-05-19 18:52:31 +02:00
|
|
|
run_step "Create Django superuser" env \
|
|
|
|
|
DJANGO_SUPERUSER_USERNAME="$SUPERUSER_USERNAME" \
|
|
|
|
|
DJANGO_SUPERUSER_EMAIL="$SUPERUSER_EMAIL" \
|
|
|
|
|
DJANGO_SUPERUSER_PASSWORD="$SUPERUSER_PASSWORD" \
|
(feature) Make the native installer interactive
Add an interactive setup flow to the systemd installer with defaults
for install paths, service identity, backup storage, bind address,
allowed hosts, CSRF origins, OS package installation, MariaDB support,
nginx setup, and first superuser creation.
Keep scripted installs supported through non-interactive mode, existing
overrides, environment variables, and explicit superuser flags.
Print a user-facing completion summary with the control panel URL,
Self Check reminder, first setup steps, and useful service log commands.
2026-05-19 18:22:18 +02:00
|
|
|
"$VENV_DIR/bin/python" "$APP_DIR/manage.py" createsuperuser --noinput
|
2026-05-19 18:52:31 +02:00
|
|
|
run_step "Finalize superuser permissions" chown -R "$SERVICE_USER:$SERVICE_GROUP" /var/lib/pobsync /var/log/pobsync
|
(feature) Make the native installer interactive
Add an interactive setup flow to the systemd installer with defaults
for install paths, service identity, backup storage, bind address,
allowed hosts, CSRF origins, OS package installation, MariaDB support,
nginx setup, and first superuser creation.
Keep scripted installs supported through non-interactive mode, existing
overrides, environment variables, and explicit superuser flags.
Print a user-facing completion summary with the control panel URL,
Self Check reminder, first setup steps, and useful service log commands.
2026-05-19 18:22:18 +02:00
|
|
|
else
|
2026-05-19 18:52:31 +02:00
|
|
|
note_step "Create Django superuser" "SKIPPED"
|
(feature) Make the native installer interactive
Add an interactive setup flow to the systemd installer with defaults
for install paths, service identity, backup storage, bind address,
allowed hosts, CSRF origins, OS package installation, MariaDB support,
nginx setup, and first superuser creation.
Keep scripted installs supported through non-interactive mode, existing
overrides, environment variables, and explicit superuser flags.
Print a user-facing completion summary with the control panel URL,
Self Check reminder, first setup steps, and useful service log commands.
2026-05-19 18:22:18 +02:00
|
|
|
echo "No superuser password was provided; create one later with:"
|
|
|
|
|
echo " sudo -u $SERVICE_USER $VENV_DIR/bin/python $APP_DIR/manage.py createsuperuser"
|
|
|
|
|
fi
|
|
|
|
|
elif [ "$superuser_exists" != "yes" ]; then
|
2026-05-19 18:52:31 +02:00
|
|
|
note_step "Create Django superuser" "SKIPPED"
|
(feature) Make the native installer interactive
Add an interactive setup flow to the systemd installer with defaults
for install paths, service identity, backup storage, bind address,
allowed hosts, CSRF origins, OS package installation, MariaDB support,
nginx setup, and first superuser creation.
Keep scripted installs supported through non-interactive mode, existing
overrides, environment variables, and explicit superuser flags.
Print a user-facing completion summary with the control panel URL,
Self Check reminder, first setup steps, and useful service log commands.
2026-05-19 18:22:18 +02:00
|
|
|
echo "No Django superuser exists yet. Create one with:"
|
|
|
|
|
echo " sudo -u $SERVICE_USER $VENV_DIR/bin/python $APP_DIR/manage.py createsuperuser"
|
2026-05-19 18:52:31 +02:00
|
|
|
else
|
|
|
|
|
note_step "Create Django superuser" "SKIPPED"
|
(feature) Make the native installer interactive
Add an interactive setup flow to the systemd installer with defaults
for install paths, service identity, backup storage, bind address,
allowed hosts, CSRF origins, OS package installation, MariaDB support,
nginx setup, and first superuser creation.
Keep scripted installs supported through non-interactive mode, existing
overrides, environment variables, and explicit superuser flags.
Print a user-facing completion summary with the control panel URL,
Self Check reminder, first setup steps, and useful service log commands.
2026-05-19 18:22:18 +02:00
|
|
|
fi
|
|
|
|
|
|
2026-05-19 18:58:41 +02:00
|
|
|
run_step "Enable services" systemctl enable pobsync-web.service pobsync-worker.service pobsync-scheduler.service
|
|
|
|
|
run_step "Restart services" systemctl restart pobsync-web.service pobsync-worker.service pobsync-scheduler.service
|
2026-05-19 15:59:07 +02:00
|
|
|
|
|
|
|
|
if [ "$WITH_NGINX" -eq 1 ]; then
|
|
|
|
|
if ! command -v nginx >/dev/null 2>&1; then
|
2026-05-19 18:52:31 +02:00
|
|
|
note_step "Install nginx config" "SKIPPED"
|
2026-05-19 15:59:07 +02:00
|
|
|
echo "nginx is not installed; skipping nginx config." >&2
|
|
|
|
|
else
|
|
|
|
|
sed "s|@POBSYNC_SERVER_NAME@|$SERVER_NAME|g" "$APP_DIR/deploy/nginx/pobsync.conf" > /etc/nginx/sites-available/pobsync.conf
|
|
|
|
|
ln -sf /etc/nginx/sites-available/pobsync.conf /etc/nginx/sites-enabled/pobsync.conf
|
2026-05-19 18:52:31 +02:00
|
|
|
note_step "Install nginx config" "OK"
|
|
|
|
|
run_step "Validate nginx config" nginx -t
|
|
|
|
|
run_step "Reload nginx" systemctl reload nginx
|
2026-05-19 15:59:07 +02:00
|
|
|
fi
|
2026-05-19 18:52:31 +02:00
|
|
|
else
|
|
|
|
|
note_step "Install nginx config" "SKIPPED"
|
2026-05-19 15:59:07 +02:00
|
|
|
fi
|
|
|
|
|
|
2026-05-19 18:52:31 +02:00
|
|
|
if [ "$VERBOSE" -eq 1 ]; then
|
|
|
|
|
systemctl --no-pager --full status pobsync-web.service pobsync-worker.service pobsync-scheduler.service || true
|
|
|
|
|
fi
|
(feature) Make the native installer interactive
Add an interactive setup flow to the systemd installer with defaults
for install paths, service identity, backup storage, bind address,
allowed hosts, CSRF origins, OS package installation, MariaDB support,
nginx setup, and first superuser creation.
Keep scripted installs supported through non-interactive mode, existing
overrides, environment variables, and explicit superuser flags.
Print a user-facing completion summary with the control panel URL,
Self Check reminder, first setup steps, and useful service log commands.
2026-05-19 18:22:18 +02:00
|
|
|
|
|
|
|
|
echo
|
|
|
|
|
echo "pobsync installation complete."
|
|
|
|
|
echo
|
|
|
|
|
echo "Open the Django control panel at:"
|
|
|
|
|
echo " http://$WEB_BIND/"
|
|
|
|
|
echo
|
|
|
|
|
echo "If pobsync is behind a reverse proxy, use your public hostname instead."
|
|
|
|
|
echo
|
|
|
|
|
echo "Recommended first steps:"
|
|
|
|
|
echo " 1. Log in to the Django control panel."
|
|
|
|
|
echo " 2. Open Self Check and resolve any warnings."
|
|
|
|
|
echo " 3. Configure global settings and backup storage."
|
|
|
|
|
echo " 4. Add an SSH key under SSH Keys."
|
|
|
|
|
echo " 5. Add a host and queue a dry-run backup."
|
|
|
|
|
echo
|
|
|
|
|
echo "Useful commands:"
|
|
|
|
|
echo " systemctl status pobsync-web pobsync-worker pobsync-scheduler"
|
|
|
|
|
echo " journalctl -u pobsync-worker -f"
|