#!/usr/bin/env bash # ============================================================================== # nx9-wg Production Installer # ============================================================================== # Installs nx9-wg binary, systemd service, configuration template, and # state directories with strict Linux filesystem permissions. # ============================================================================== set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" RELEASE_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)" # Target installation paths BIN_DIR="/usr/local/bin" CONF_DIR="/etc/nx9-wg" DATA_DIR="/var/lib/nx9-wg" BACKUP_DIR="${DATA_DIR}/backups" LOG_DIR="/var/log/nx9-wg" SYSTEMD_DIR="/etc/systemd/system" DRY_RUN=0 NO_SERVICE=0 NO_INIT=0 usage() { cat <&2 usage ;; esac done log() { echo -e "\033[1;34m[INFO]\033[0m $*" } warn() { echo -e "\033[1;33m[WARN]\033[0m $*" } error() { echo -e "\033[1;31m[ERROR]\033[0m $*" >&2 exit 1 } run_cmd() { if [[ "${DRY_RUN}" -eq 1 ]]; then echo " [DRY-RUN] $*" else "$@" fi } # 1. Privilege Verification if [[ "${EUID}" -ne 0 && "${DRY_RUN}" -eq 0 ]]; then error "This installer must be run as root (or via sudo)." fi # 2. Host Architecture & Kernel Verification ARCH="$(uname -m)" OS="$(uname -s)" if [[ "${OS}" != "Linux" ]]; then error "nx9-wg production deployment requires Linux (detected: ${OS})." fi log "Detected platform: ${OS} (${ARCH})" # 3. Locate nx9-wg release binary BIN_SOURCE="" if [[ -f "${SCRIPT_DIR}/nx9-wg" ]]; then BIN_SOURCE="${SCRIPT_DIR}/nx9-wg" elif [[ -f "${RELEASE_ROOT}/nx9-wg" ]]; then BIN_SOURCE="${RELEASE_ROOT}/nx9-wg" elif [[ -f "${RELEASE_ROOT}/target/release/nx9-wg" ]]; then BIN_SOURCE="${RELEASE_ROOT}/target/release/nx9-wg" else error "Could not find nx9-wg binary in package or target/release." fi log "Using binary source: ${BIN_SOURCE}" # 4. Dependency Checks log "Verifying runtime dependencies..." if ! command -v ldd >/dev/null 2>&1; then warn "ldd utility not found, skipping dynamic link check." else if ldd "${BIN_SOURCE}" 2>&1 | grep -q "not found"; then warn "Missing dynamic dependencies detected in ldd check:" ldd "${BIN_SOURCE}" | grep "not found" || true warn "Please ensure libnftables.so.1 is installed on this system." else log "All dynamic linkages resolved successfully." fi fi # 5. Create Filesystem Layout log "Creating filesystem layout with secure permissions..." run_cmd install -d -m 0750 "${CONF_DIR}" run_cmd install -d -m 0700 "${DATA_DIR}" run_cmd install -d -m 0700 "${BACKUP_DIR}" run_cmd install -d -m 0750 "${LOG_DIR}" # 6. Install Binary log "Installing binary to ${BIN_DIR}/nx9-wg..." run_cmd install -m 0755 "${BIN_SOURCE}" "${BIN_DIR}/nx9-wg" # 7. Install Configuration Template CONF_SOURCE="" if [[ -f "${RELEASE_ROOT}/config.example.toml" ]]; then CONF_SOURCE="${RELEASE_ROOT}/config.example.toml" elif [[ -f "${SCRIPT_DIR}/config.example.toml" ]]; then CONF_SOURCE="${SCRIPT_DIR}/config.example.toml" fi if [[ -f "${CONF_DIR}/config.toml" ]]; then log "Existing configuration found at ${CONF_DIR}/config.toml (preserving)." else if [[ -n "${CONF_SOURCE}" && -f "${CONF_SOURCE}" ]]; then log "Installing configuration template to ${CONF_DIR}/config.toml..." run_cmd install -m 0640 "${CONF_SOURCE}" "${CONF_DIR}/config.toml" else warn "Configuration template config.example.toml not found, skipping." fi fi # 8. Bootstrap Initial Administrator (if not already initialized) if [[ "${NO_INIT}" -eq 0 && "${DRY_RUN}" -eq 0 ]]; then PW_FILE="${DATA_DIR}/admin-initial-password" log "Checking administrator account initialization..." if "${BIN_DIR}/nx9-wg" --config "${CONF_DIR}/config.toml" --data-dir "${DATA_DIR}" admin status >/dev/null 2>&1; then log "Administrator account already initialized in database." else log "Initializing administrator account with secure random credentials..." "${BIN_DIR}/nx9-wg" --config "${CONF_DIR}/config.toml" --data-dir "${DATA_DIR}" init --generate-password --write-password-file "${PW_FILE}" || true if [[ -f "${PW_FILE}" ]]; then chmod 0600 "${PW_FILE}" log "Initial administrator password written to: ${PW_FILE} (mode 0600)" fi fi fi # 9. Install systemd Service if [[ "${NO_SERVICE}" -eq 0 && -d "${SYSTEMD_DIR}" ]]; then SERVICE_SOURCE="" if [[ -f "${RELEASE_ROOT}/nx9-wg.service" ]]; then SERVICE_SOURCE="${RELEASE_ROOT}/nx9-wg.service" elif [[ -f "${SCRIPT_DIR}/nx9-wg.service" ]]; then SERVICE_SOURCE="${SCRIPT_DIR}/nx9-wg.service" fi if [[ -n "${SERVICE_SOURCE}" && -f "${SERVICE_SOURCE}" ]]; then log "Installing systemd service unit to ${SYSTEMD_DIR}/nx9-wg.service..." run_cmd install -m 0644 "${SERVICE_SOURCE}" "${SYSTEMD_DIR}/nx9-wg.service" if command -v systemctl >/dev/null 2>&1 && [[ "${DRY_RUN}" -eq 0 ]]; then log "Reloading systemd daemon..." systemctl daemon-reload log "Enabling and starting nx9-wg service..." systemctl enable --now nx9-wg || warn "Could not start nx9-wg.service automatically." fi else warn "nx9-wg.service unit file not found, skipping service installation." fi fi log "=================================================================" log "nx9-wg installation completed successfully!" log " Binary: ${BIN_DIR}/nx9-wg" log " Configuration: ${CONF_DIR}/config.toml" log " Database & Data:${DATA_DIR}/nx9-wg.db" log " Backups: ${BACKUP_DIR}" log "================================================================="