#!/usr/bin/env bash # ============================================================================= # Linux Patch Manager — Initial Host Setup Script # ============================================================================= # Run as root on the Ubuntu 24.04 Patch Manager host. # This script: # - Creates the service user/group # - Creates required directories with correct permissions # - Installs PostgreSQL if not present # - Creates the database and user # - Copies configuration and binaries # - Installs systemd units # - Generates initial Ed25519 JWT keys # ============================================================================= set -euo pipefail RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' NC='\033[0m' info() { echo -e "${GREEN}[INFO]${NC} $*"; } warn() { echo -e "${YELLOW}[WARN]${NC} $*"; } error() { echo -e "${RED}[ERROR]${NC} $*" >&2; exit 1; } [[ $EUID -ne 0 ]] && error "This script must be run as root." SERVICE_USER="patch-manager" SERVICE_GROUP="patch-manager" CONFIG_DIR="/etc/patch-manager" LOG_DIR="/var/log/patch-manager" DATA_DIR="/opt/patch-manager" FRONTEND_DIR="/usr/share/patch-manager/frontend" BIN_DIR="/usr/local/bin" BACKUP_DIR="/var/backups/patch-manager" DB_NAME="patch_manager" DB_USER="patch_manager" SYSTEMD_DIR="/etc/systemd/system" info "=== Linux Patch Manager Setup ===" # ----------------------------------------------------------------------- # 1. Create service user # ----------------------------------------------------------------------- info "Creating service user '${SERVICE_USER}'..." if ! id "${SERVICE_USER}" &>/dev/null; then useradd --system --no-create-home --shell /usr/sbin/nologin \ --comment "Linux Patch Manager service account" \ "${SERVICE_USER}" info "User '${SERVICE_USER}' created." else warn "User '${SERVICE_USER}' already exists, skipping." fi # ----------------------------------------------------------------------- # 2. Create required directories # ----------------------------------------------------------------------- info "Creating directories..." mkdir -p \ "${CONFIG_DIR}/ca" \ "${CONFIG_DIR}/certs" \ "${CONFIG_DIR}/jwt" \ "${CONFIG_DIR}/tls" \ "${LOG_DIR}" \ "${DATA_DIR}" \ "${FRONTEND_DIR}" \ "${BACKUP_DIR}" chown -R "${SERVICE_USER}:${SERVICE_GROUP}" \ "${CONFIG_DIR}" \ "${LOG_DIR}" \ "${DATA_DIR}" \ "${FRONTEND_DIR}" chmod 750 "${CONFIG_DIR}/ca" "${CONFIG_DIR}/jwt" chmod 700 "${BACKUP_DIR}" info "Directories created." # ----------------------------------------------------------------------- # 3. Install PostgreSQL 16 if not present # ----------------------------------------------------------------------- if ! command -v psql &>/dev/null; then info "Installing PostgreSQL 16..." apt-get update -qq apt-get install -y postgresql-16 systemctl enable --now postgresql else info "PostgreSQL already installed: $(psql --version)" fi # ----------------------------------------------------------------------- # 4. Create database and user # ----------------------------------------------------------------------- info "Creating database '${DB_NAME}' and user '${DB_USER}'..." DB_PASSWORD=$(openssl rand -base64 32) sudo -u postgres psql -v ON_ERROR_STOP=1 </dev/null || \ warn "Seed migration already applied or failed (may be idempotent)." else warn "Seed migration not found: ${SEED_MIGRATION}" fi # ----------------------------------------------------------------------- # 9. Install backup cron job # ----------------------------------------------------------------------- CRON_LINE="0 2 * * * /usr/local/bin/backup.sh >> /var/log/patch-manager/backup.log 2>&1" if crontab -l 2>/dev/null | grep -qF "backup.sh"; then warn "Backup cron job already installed, skipping." else (crontab -l 2>/dev/null; echo "${CRON_LINE}") | crontab - info "Nightly backup cron installed (02:00 daily)." fi # ----------------------------------------------------------------------- # Done # ----------------------------------------------------------------------- info "=== Setup complete ===" info "Next steps:" echo " 1. Build and install binaries: cargo build --release" echo " cp target/release/pm-web target/release/pm-worker ${BIN_DIR}/" echo " 2. Build and install frontend: scripts/build-frontend.sh" echo " 3. Review ${CONFIG_DEST}" echo " 4. Enable services:" echo " systemctl enable --now patch-manager-web patch-manager-worker" echo " 5. (Optional) Set GPG_RECIPIENT in backup.sh for encrypted backups"