(refactor) Add native systemd production deployment
Make native systemd services the recommended production path for pobsync while keeping Docker Compose available for development and optional test installs. Add web, worker, and scheduler systemd unit templates, a native environment example, an optional nginx reverse proxy template, and an installer that creates the venv, service user, env file, units, and runs migrations/static collection. Allow native deployments to configure POBSYNC_BACKUP_ROOT directly and document the new production layout and update flow.
This commit is contained in:
123
scripts/install-systemd
Executable file
123
scripts/install-systemd
Executable file
@@ -0,0 +1,123 @@
|
||||
#!/bin/sh
|
||||
set -eu
|
||||
|
||||
APP_DIR=${POBSYNC_APP_DIR:-$(CDPATH= cd -- "$(dirname -- "$0")/.." && pwd)}
|
||||
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:-_}
|
||||
WITH_NGINX=0
|
||||
|
||||
while [ "$#" -gt 0 ]; do
|
||||
case "$1" in
|
||||
--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
|
||||
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
mkdir -p /etc/pobsync /var/lib/pobsync /var/log/pobsync "$(dirname "$VENV_DIR")"
|
||||
chown "$SERVICE_USER:$SERVICE_GROUP" /var/lib/pobsync /var/log/pobsync
|
||||
chmod 0750 /var/lib/pobsync /var/log/pobsync
|
||||
|
||||
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
|
||||
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_HOME=/var/lib/pobsync
|
||||
POBSYNC_BACKUP_ROOT=/backups
|
||||
POBSYNC_SQLITE_PATH=/var/lib/pobsync/pobsync.sqlite3
|
||||
POBSYNC_STATIC_ROOT=/var/lib/pobsync/static
|
||||
|
||||
POBSYNC_WEB_BIND=127.0.0.1:8010
|
||||
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"
|
||||
echo "Created $ENV_FILE. Edit allowed hosts and backup root before exposing the service."
|
||||
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
|
||||
Reference in New Issue
Block a user