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}
|
|
|
|
|
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
|
|
|
|
|
|
|
|
|
|
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
|
|
|
|
|
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: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
|
|
|
|
|
;;
|
|
|
|
|
*)
|
|
|
|
|
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 18:15:34 +02:00
|
|
|
install_os_packages() {
|
|
|
|
|
if [ "$INSTALL_OS_PACKAGES" -ne 1 ]; then
|
|
|
|
|
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
|
|
|
|
|
apt-get update
|
|
|
|
|
apt-get install -y --no-install-recommends $packages
|
|
|
|
|
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
|
|
|
|
|
groupadd --system "$SERVICE_GROUP"
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
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
|
|
|
|
|
|
(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
|
|
|
mkdir -p /etc/pobsync /var/lib/pobsync /var/log/pobsync "$(dirname "$VENV_DIR")" "$APP_DIR" "$BACKUP_ROOT"
|
2026-05-19 15:59:07 +02:00
|
|
|
chown "$SERVICE_USER:$SERVICE_GROUP" /var/lib/pobsync /var/log/pobsync
|
|
|
|
|
chmod 0750 /var/lib/pobsync /var/log/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
|
|
|
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
|
|
|
|
|
|
2026-05-19 15:59:07 +02:00
|
|
|
python3 -m venv "$VENV_DIR"
|
|
|
|
|
"$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
|
|
|
|
|
"$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"
|
(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 "Wrote $ENV_FILE."
|
|
|
|
|
else
|
|
|
|
|
echo "Keeping existing $ENV_FILE. Use --force-env to rewrite it."
|
2026-05-19 15:59:07 +02:00
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
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"
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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
|
|
|
|
|
|
|
|
|
|
systemctl daemon-reload
|
|
|
|
|
"$VENV_DIR/bin/python" "$APP_DIR/manage.py" migrate --noinput
|
|
|
|
|
"$VENV_DIR/bin/python" "$APP_DIR/manage.py" collectstatic --noinput --clear
|
|
|
|
|
systemctl enable --now pobsync-web.service pobsync-worker.service pobsync-scheduler.service
|
|
|
|
|
|
|
|
|
|
if [ "$WITH_NGINX" -eq 1 ]; then
|
|
|
|
|
if ! command -v nginx >/dev/null 2>&1; then
|
|
|
|
|
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
|
|
|
|
|
nginx -t
|
|
|
|
|
systemctl reload nginx
|
|
|
|
|
fi
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
systemctl --no-pager --full status pobsync-web.service pobsync-worker.service pobsync-scheduler.service || true
|