#!/usr/bin/env bash set -euo pipefail REMOTE_HOST="${REMOTE_HOST:-${VPS_HOST:-}}" REMOTE_USER="${REMOTE_USER:-${VPS_USER:-}}" if [ -z "$REMOTE_HOST" ]; then echo "Set REMOTE_HOST to the SSH host or IP address, for example a local NAS hostname." >&2 exit 2 fi if [ -z "$REMOTE_USER" ]; then echo "Set REMOTE_USER to the non-root sudo SSH user." >&2 exit 2 fi APP_USER="${APP_USER:-mailcat}" SERVICE_NAME="${SERVICE_NAME:-mailcat-sort-backup}" ACCOUNT="${ACCOUNT:-backup}" REMOTE_PATH="${REMOTE_PATH:-/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin}" SERVICE_MANAGER="${SERVICE_MANAGER:-systemd}" MAILCAT_HOME="${MAILCAT_HOME:-/share/homes/$APP_USER}" SUDO="${SUDO:-/usr/bin/sudo}" USERADD="${USERADD:-/usr/local/bin/useradd}" INSTALL="${INSTALL:-/usr/bin/install}" SED="${SED:-/bin/sed}" TAR="${TAR:-/bin/tar}" MKDIR="${MKDIR:-/bin/mkdir}" CHOWN="${CHOWN:-/bin/chown}" CHMOD="${CHMOD:-/bin/chmod}" RM="${RM:-/bin/rm}" SYSTEMCTL="${SYSTEMCTL:-/bin/systemctl}" if [ -z "${APP_DIR:-}" ]; then if [ "$SERVICE_MANAGER" = "plain" ]; then APP_DIR="$MAILCAT_HOME/mailcat" else APP_DIR="/opt/mailcat" fi fi if [ "$SERVICE_MANAGER" = "plain" ]; then STATE_DIR="${STATE_DIR:-$APP_DIR/state}" LOG_DIR="${LOG_DIR:-$APP_DIR/log}" RUN_DIR="${RUN_DIR:-$APP_DIR/run}" PID_FILE="${PID_FILE:-$RUN_DIR/mailcat.pid}" PYTHON="${PYTHON:-/opt/bin/python3}" else STATE_DIR="${STATE_DIR:-/var/lib/mailcat}" LOG_DIR="${LOG_DIR:-/var/log/mailcat}" RUN_DIR="${RUN_DIR:-/run/mailcat}" PID_FILE="${PID_FILE:-$RUN_DIR/mailcat.pid}" PYTHON="${PYTHON:-/usr/bin/python3}" fi ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" ARCHIVE="$(mktemp -t mailcat-deploy.XXXXXX.tar.gz)" REMOTE_SCRIPT="$(mktemp -t mailcat-remote-deploy.XXXXXX.sh)" cleanup() { rm -f "$ARCHIVE" rm -f "$REMOTE_SCRIPT" } trap cleanup EXIT tar \ --exclude ".git" \ --exclude "__pycache__" \ --exclude "mailbox" \ --exclude "config.json" \ --exclude "*.log" \ --exclude "backup_log.json" \ --exclude "verplaats_log*.json" \ --exclude "sort_mail_daemon_state.json" \ --exclude "mailing_lists_cache*.json" \ --exclude "*.pyc" \ -C "$ROOT_DIR" \ -czf "$ARCHIVE" . cat > "$REMOTE_SCRIPT" <<'REMOTE' set -eu export PATH="$REMOTE_PATH:$PATH" "$SUDO" -v find_command() { name="$1" shift if command -v "$name" >/dev/null 2>&1; then command -v "$name" return 0 fi for candidate in "$@"; do if [ -x "$candidate" ]; then printf '%s\n' "$candidate" return 0 fi done return 1 } if ! id "$APP_USER" >/dev/null 2>&1; then if [ -x "$USERADD" ] || USERADD="$(find_command useradd /usr/local/bin/useradd /usr/local/sbin/useradd /usr/sbin/useradd /sbin/useradd)"; then NOLOGIN="$(find_command nologin /usr/local/bin/nologin /usr/local/sbin/nologin /usr/sbin/nologin /sbin/nologin || true)" if [ -n "$NOLOGIN" ]; then "$SUDO" "$USERADD" -d "$MAILCAT_HOME" -s "$NOLOGIN" "$APP_USER" else "$SUDO" "$USERADD" -d "$MAILCAT_HOME" "$APP_USER" fi else APP_USER="$(id -un)" echo "useradd not found on remote host; using existing SSH user '$APP_USER' for the service." >&2 fi fi APP_GROUP="$(id -gn "$APP_USER")" "$SUDO" "$MKDIR" -p "$APP_DIR" "$STATE_DIR" "$LOG_DIR" "$RUN_DIR" "$APP_DIR/bin" "$SUDO" "$TAR" -xzf /tmp/mailcat-deploy.tar.gz -C "$APP_DIR" "$SUDO" "$CHOWN" -R "$APP_USER:$APP_GROUP" "$MAILCAT_HOME" "$APP_DIR" "$STATE_DIR" "$LOG_DIR" "$RUN_DIR" "$SUDO" "$CHMOD" 750 "$APP_DIR" if [ ! -f "$APP_DIR/config.json" ]; then echo "Missing $APP_DIR/config.json on remote host. Create it with mode 600 before starting the service." >&2 fi "$SUDO" "$CHMOD" 600 "$APP_DIR/config.json" 2>/dev/null || true "$SUDO" "$CHOWN" "$APP_USER:$APP_GROUP" "$APP_DIR/config.json" 2>/dev/null || true if [ "$SERVICE_MANAGER" = "plain" ]; then cat > /tmp/mailcat-start.sh </dev/null; then echo "mailcat already running: \$old_pid" exit 0 fi fi cd "\$APP_DIR" "\$PYTHON" "\$APP_DIR/sort_mail_daemon.py" --account "\$ACCOUNT" --folder INBOX --state-file "\$STATE_DIR/sort_mail_daemon_state.json" --log-file "\$LOG_DIR/sort_mail_daemon.log" >> "\$LOG_DIR/daemon.out" 2>&1 & pid="\$!" echo "\$pid" > "\$PID_FILE" echo "mailcat started: \$pid" START_SCRIPT cat > /tmp/mailcat-stop.sh </dev/null; then kill "\$pid" sleep 2 if kill -0 "\$pid" 2>/dev/null; then echo "mailcat still running after SIGTERM: \$pid" exit 1 fi fi "\$RM" -f "\$PID_FILE" echo "mailcat stopped" STOP_SCRIPT cat > /tmp/mailcat-status.sh </dev/null; then echo "mailcat running: \$pid" exit 0 fi echo "mailcat not running: stale pid file (\$pid)" exit 1 fi echo "mailcat not running" echo "logs: \$LOG_DIR" exit 1 STATUS_SCRIPT "$SUDO" "$INSTALL" -m 0755 /tmp/mailcat-start.sh "$APP_DIR/bin/start_mailcat.sh" "$SUDO" "$INSTALL" -m 0755 /tmp/mailcat-stop.sh "$APP_DIR/bin/stop_mailcat.sh" "$SUDO" "$INSTALL" -m 0755 /tmp/mailcat-status.sh "$APP_DIR/bin/status_mailcat.sh" "$SUDO" "$CHOWN" "$APP_USER:$APP_GROUP" "$APP_DIR/bin/start_mailcat.sh" "$APP_DIR/bin/stop_mailcat.sh" "$APP_DIR/bin/status_mailcat.sh" "$RM" -f /tmp/mailcat-start.sh /tmp/mailcat-stop.sh /tmp/mailcat-status.sh else "$SUDO" "$INSTALL" -m 0644 "$APP_DIR/systemd/mailcat-sort.service" "/etc/systemd/system/$SERVICE_NAME.service" "$SUDO" "$SED" -i \ -e "s#__APP_USER__#$APP_USER#g" \ -e "s#__APP_GROUP__#$APP_GROUP#g" \ -e "s#__APP_DIR__#$APP_DIR#g" \ -e "s#__ACCOUNT__#$ACCOUNT#g" \ -e "s#__PYTHON__#$PYTHON#g" \ -e "s#__STATE_DIR__#$STATE_DIR#g" \ -e "s#__LOG_DIR__#$LOG_DIR#g" \ "/etc/systemd/system/$SERVICE_NAME.service" "$SUDO" "$SYSTEMCTL" daemon-reload "$SUDO" "$SYSTEMCTL" enable "$SERVICE_NAME.service" fi "$RM" -f /tmp/mailcat-deploy.tar.gz /tmp/mailcat-remote-deploy.sh echo "Deployment complete." echo "Create/check $APP_DIR/config.json, then run:" if [ "$SERVICE_MANAGER" = "plain" ]; then echo " sudo -u $APP_USER $APP_DIR/bin/start_mailcat.sh" echo " sudo -u $APP_USER $APP_DIR/bin/status_mailcat.sh" echo " tail -f $LOG_DIR/sort_mail_daemon.log" else echo " sudo systemctl start $SERVICE_NAME.service" echo " sudo journalctl -u $SERVICE_NAME.service -f" fi REMOTE scp "$ARCHIVE" "$REMOTE_USER@$REMOTE_HOST:/tmp/mailcat-deploy.tar.gz" scp "$REMOTE_SCRIPT" "$REMOTE_USER@$REMOTE_HOST:/tmp/mailcat-remote-deploy.sh" REMOTE_COMMAND=$(printf "APP_USER=%q APP_DIR=%q SERVICE_NAME=%q ACCOUNT=%q REMOTE_PATH=%q SERVICE_MANAGER=%q MAILCAT_HOME=%q STATE_DIR=%q LOG_DIR=%q RUN_DIR=%q PID_FILE=%q PYTHON=%q SUDO=%q USERADD=%q INSTALL=%q SED=%q TAR=%q MKDIR=%q CHOWN=%q CHMOD=%q RM=%q SYSTEMCTL=%q /bin/sh /tmp/mailcat-remote-deploy.sh" "$APP_USER" "$APP_DIR" "$SERVICE_NAME" "$ACCOUNT" "$REMOTE_PATH" "$SERVICE_MANAGER" "$MAILCAT_HOME" "$STATE_DIR" "$LOG_DIR" "$RUN_DIR" "$PID_FILE" "$PYTHON" "$SUDO" "$USERADD" "$INSTALL" "$SED" "$TAR" "$MKDIR" "$CHOWN" "$CHMOD" "$RM" "$SYSTEMCTL") ssh -tt "$REMOTE_USER@$REMOTE_HOST" "$REMOTE_COMMAND"