Finalize nx9-wg production release

This commit is contained in:
thakares committed 2026-08-18 22:27:36 +05:30
1 parent 4dfe42fe68
commit d704c1e131
30 files changed
+2502 -370

No files matched your search

+85
View File
@@ -0,0 +1,85 @@
#!/usr/bin/env bash
# ==============================================================================
# nx9-wg Source Repository Backup Tool
# ==============================================================================
# PURPOSE:
# Creates a timestamped, compressed source code backup archive while strictly
# excluding build artifacts (target/) and temporary databases, while retaining
# the full .git version history for recovery and auditability.
#
# PREREQUISITES:
# - tar
# - xz or gzip
# - sha256sum
#
# BEHAVIOR:
# - Non-destructive to the source tree.
# - Verifies the integrity of the generated archive.
# - Generates a companion .sha256 checksum file.
#
# USAGE:
# bash scripts/backup-source.sh [DESTINATION_DIR]
# ./scripts/backup-source.sh /backup/sources
# ==============================================================================
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
ROOT_DIR="$(cd "${SCRIPT_DIR}/.." && pwd)"
DEST_DIR="${1:-${ROOT_DIR}/..}"
mkdir -p "${DEST_DIR}"
DEST_DIR="$(cd "${DEST_DIR}" && pwd)"
PROJECT_NAME="nx9-wg"
TIMESTAMP="$(date +%Y-%m-%d-%H%M%S)"
ARCHIVE_BASE="${PROJECT_NAME}-source-${TIMESTAMP}"
ARCHIVE_PATH="${DEST_DIR}/${ARCHIVE_BASE}.tar.xz"
log() {
echo -e "\033[1;34m[BACKUP-SRC]\033[0m \033[1;37m$*\033[0m"
}
success() {
echo -e "\033[1;32m[SUCCESS]\033[0m $*"
}
error() {
echo -e "\033[1;31m[ERROR]\033[0m $*" >&2
exit 1
}
log "Creating source backup of ${ROOT_DIR}..."
log "Destination archive: ${ARCHIVE_PATH}"
# Create archive excluding heavy/temporary build outputs
tar --exclude='target' \
--exclude='.cargo' \
--exclude='*.log' \
--exclude='*.tmp' \
--exclude='*.db' \
--exclude='*.db-wal' \
--exclude='*.db-shm' \
--exclude='*.tar.gz' \
--exclude='*.tar.xz' \
-cJf "${ARCHIVE_PATH}" \
-C "$(dirname "${ROOT_DIR}")" "$(basename "${ROOT_DIR}")" || error "Failed to create source archive."
# Verify archive integrity
log "Verifying archive integrity..."
tar -tf "${ARCHIVE_PATH}" >/dev/null || error "Archive verification check failed."
# Generate checksum
(cd "${DEST_DIR}" && sha256sum "$(basename "${ARCHIVE_PATH}")" > "${ARCHIVE_BASE}.sha256")
ARCHIVE_SIZE="$(du -h "${ARCHIVE_PATH}" | cut -f1)"
ARCHIVE_SHA="$(cat "${DEST_DIR}/${ARCHIVE_BASE}.sha256" | awk '{print $1}')"
echo -e "\n================================================================="
echo -e "\033[1;32m SOURCE BACKUP COMPLETED SUCCESSFULLY!\033[0m"
echo -e "================================================================="
echo " Archive Path: ${ARCHIVE_PATH}"
echo " Archive Size: ${ARCHIVE_SIZE}"
echo " SHA-256: ${ARCHIVE_SHA}"
echo " Checksum File:${DEST_DIR}/${ARCHIVE_BASE}.sha256"
echo -e "=================================================================\n"
+85
View File
@@ -0,0 +1,85 @@
#!/usr/bin/env bash
# ==============================================================================
# nx9-wg Production Release Builder
# ==============================================================================
# PURPOSE:
# Runs release quality gates and compiles an optimized release binary:
# 1. Format verification
# 2. Check & Clippy (-D warnings)
# 3. Full workspace test suite
# 4. Release build (cargo build --release --workspace)
# 5. Artifact verification (binary size, permissions, SHA-256)
#
# PREREQUISITES:
# - Rust toolchain (stable)
# - Linux C build tools (libsqlite3 / pkg-config / ldd)
#
# BEHAVIOR:
# - Non-destructive to existing deployments.
# - Does NOT run 'cargo clean' to prevent accidental removal of release artifacts.
# - Produces target/release/nx9-wg.
#
# USAGE:
# bash scripts/build-release.sh
# ./scripts/build-release.sh
# ==============================================================================
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
ROOT_DIR="$(cd "${SCRIPT_DIR}/.." && pwd)"
log() {
echo -e "\n\033[1;34m[RELEASE-BUILD]\033[0m \033[1;37m$*\033[0m"
}
success() {
echo -e "\033[1;32m[PASS]\033[0m $*"
}
error() {
echo -e "\033[1;31m[ERROR]\033[0m $*" >&2
exit 1
}
cd "${ROOT_DIR}"
log "1/4 Verifying code formatting..."
cargo fmt --all -- --check || error "Formatting verification failed."
success "Formatting verified."
log "2/4 Running compiler and Clippy checks..."
cargo check --workspace --all-targets || error "Cargo check failed."
cargo clippy --workspace --all-targets --all-features -- -D warnings || error "Clippy check failed."
success "Lint checks passed with 0 warnings."
log "3/4 Running full workspace test suite..."
cargo test --workspace --all-targets || error "Workspace test suite failed."
success "All unit and integration tests passed."
log "4/4 Compiling optimized release binary (cargo build --release --workspace)..."
cargo build --release --workspace || error "Release build failed."
TARGET_BIN="${ROOT_DIR}/target/release/nx9-wg"
if [[ ! -f "${TARGET_BIN}" ]]; then
error "Expected release binary not found at ${TARGET_BIN}"
fi
if [[ ! -x "${TARGET_BIN}" ]]; then
error "Release binary is not executable at ${TARGET_BIN}"
fi
BIN_SIZE="$(du -h "${TARGET_BIN}" | cut -f1)"
BIN_SHA="$(sha256sum "${TARGET_BIN}" | awk '{print $1}')"
BIN_DATE="$(date -r "${TARGET_BIN}" '+%Y-%m-%d %H:%M:%S')"
echo -e "\n================================================================="
echo -e "\033[1;32m RELEASE BUILD SUCCESSFUL!\033[0m"
echo -e "================================================================="
echo " Binary Path: ${TARGET_BIN}"
echo " Binary Size: ${BIN_SIZE}"
echo " Timestamp: ${BIN_DATE}"
echo " SHA-256: ${BIN_SHA}"
echo " Version: $("${TARGET_BIN}" version | head -n 1)"
echo -e "=================================================================\n"
+216
View File
@@ -0,0 +1,216 @@
#!/usr/bin/env bash
# ==============================================================================
# nx9-wg Production Deployment Tool
# ==============================================================================
# PURPOSE:
# Deploys the compiled release binary target/release/nx9-wg to the production
# system path (/usr/local/bin/nx9-wg) with validated controlled replacement,
# automatic backup of the previous binary, and controlled systemd service management.
#
# PREREQUISITES:
# - Root privileges (or sudo)
# - Pre-compiled release binary at target/release/nx9-wg
# - Linux with systemd
#
# SAFETY INVARIANTS:
# - Never overwrites the existing production binary without creating a timestamped backup.
# - Never modifies or overwrites database files (/var/lib/nx9-wg/nx9-wg.db).
# - Never deletes WireGuard interfaces or kills processes automatically on port conflict.
# - Uses the standard 'install' command for controlled binary replacement and strict permissions.
# - Returns non-zero exit code on failure.
#
# USAGE:
# sudo bash scripts/deploy.sh [OPTIONS]
#
# OPTIONS:
# --no-restart Install binary without restarting nx9-wg.service
# --dry-run Simulate deployment actions without applying changes
# -h, --help Show this help message
# ==============================================================================
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
ROOT_DIR="$(cd "${SCRIPT_DIR}/.." && pwd)"
SOURCE_BIN="${ROOT_DIR}/target/release/nx9-wg"
DEST_BIN="/usr/local/bin/nx9-wg"
CONF_DIR="/etc/nx9-wg"
DATA_DIR="/var/lib/nx9-wg"
BACKUP_DIR="${DATA_DIR}/backups"
LOG_DIR="/var/log/nx9-wg"
SERVICE_DEST="/etc/systemd/system/nx9-wg.service"
SERVICE_SRC="${ROOT_DIR}/nx9-wg.service"
DRY_RUN=0
NO_RESTART=0
usage() {
cat <<EOF
nx9-wg Production Deployment Tool
Usage:
sudo bash scripts/deploy.sh [OPTIONS]
Options:
--no-restart Install binary without restarting nx9-wg.service
--dry-run Simulate deployment actions without applying changes
-h, --help Show this help message
EOF
exit 0
}
while [[ $# -gt 0 ]]; do
case "$1" in
--dry-run)
DRY_RUN=1
shift
;;
--no-restart)
NO_RESTART=1
shift
;;
-h|--help)
usage
;;
*)
echo "Unknown option: $1" >&2
usage
;;
esac
done
log() {
echo -e "\033[1;34m[DEPLOY]\033[0m \033[1;37m$*\033[0m"
}
success() {
echo -e "\033[1;32m[SUCCESS]\033[0m $*"
}
warn() {
echo -e "\033[1;33m[WARN]\033[0m $*"
}
error() {
echo -e "\033[1;31m[ERROR]\033[0m $*" >&2
exit 1
}
# 1. Privilege Verification
if [[ "${EUID}" -ne 0 && "${DRY_RUN}" -eq 0 ]]; then
error "Deployment must be run as root (or via sudo)."
fi
# 2. Source Binary Verification
if [[ ! -f "${SOURCE_BIN}" ]]; then
error "Source binary not found at ${SOURCE_BIN}. Run 'bash scripts/build-release.sh' first."
fi
if [[ ! -x "${SOURCE_BIN}" ]]; then
error "Source binary at ${SOURCE_BIN} is not executable."
fi
SOURCE_SIZE="$(du -h "${SOURCE_BIN}" | cut -f1)"
SOURCE_SHA="$(sha256sum "${SOURCE_BIN}" | awk '{print $1}')"
SOURCE_DATE="$(date -r "${SOURCE_BIN}" '+%Y-%m-%d %H:%M:%S')"
log "Source binary verified:"
echo " Path: ${SOURCE_BIN}"
echo " Size: ${SOURCE_SIZE}"
echo " Timestamp: ${SOURCE_DATE}"
echo " SHA-256: ${SOURCE_SHA}"
# 3. Create Filesystem Layout with Strict Permissions
log "Ensuring directory permissions..."
if [[ "${DRY_RUN}" -eq 0 ]]; then
install -d -m 0750 "${CONF_DIR}"
install -d -m 0700 "${DATA_DIR}"
install -d -m 0700 "${BACKUP_DIR}"
install -d -m 0750 "${LOG_DIR}"
else
echo " [DRY-RUN] install -d directories: ${CONF_DIR}, ${DATA_DIR}, ${BACKUP_DIR}, ${LOG_DIR}"
fi
# 4. Backup Existing Production Binary
if [[ -f "${DEST_BIN}" ]]; then
TIMESTAMP="$(date +%Y%m%d_%H%M%S)"
BACKUP_DEST="${DEST_BIN}.backup.${TIMESTAMP}"
log "Backing up active binary to ${BACKUP_DEST}..."
if [[ "${DRY_RUN}" -eq 0 ]]; then
cp -p "${DEST_BIN}" "${BACKUP_DEST}"
chmod 0755 "${BACKUP_DEST}"
success "Backup created: ${BACKUP_DEST}"
else
echo " [DRY-RUN] cp -p ${DEST_BIN} ${BACKUP_DEST}"
fi
fi
# 5. Controlled Installation of New Binary
log "Installing new release binary to ${DEST_BIN}..."
if [[ "${DRY_RUN}" -eq 0 ]]; then
install -m 0755 "${SOURCE_BIN}" "${DEST_BIN}"
success "Binary installed to ${DEST_BIN}"
else
echo " [DRY-RUN] install -m 0755 ${SOURCE_BIN} ${DEST_BIN}"
fi
# 6. Install or Update systemd Service Unit
if [[ -f "${SERVICE_SRC}" && -d "/etc/systemd/system" ]]; then
log "Installing/updating systemd service unit..."
if [[ "${DRY_RUN}" -eq 0 ]]; then
install -m 0644 "${SERVICE_SRC}" "${SERVICE_DEST}"
if command -v systemctl >/dev/null 2>&1; then
systemctl daemon-reload
fi
success "systemd service unit updated at ${SERVICE_DEST}"
else
echo " [DRY-RUN] install -m 0644 ${SERVICE_SRC} ${SERVICE_DEST}"
fi
fi
# 7. Safe Socket Inspection
if command -v ss >/dev/null 2>&1; then
log "Inspecting active UDP listen sockets without modifying the host..."
ACTIVE_UDP_SOCKETS="$(ss -lunp 2>/dev/null | grep -v '^State' || true)"
if [[ -n "${ACTIVE_UDP_SOCKETS}" ]]; then
echo "${ACTIVE_UDP_SOCKETS}"
else
echo " No UDP listeners reported by ss."
fi
fi
# 8. Service Restart & Verification
if [[ "${NO_RESTART}" -eq 0 && "${DRY_RUN}" -eq 0 ]]; then
if command -v systemctl >/dev/null 2>&1; then
log "Restarting nx9-wg.service..."
systemctl restart nx9-wg || error "Failed to restart nx9-wg service."
sleep 1
if systemctl is-active --quiet nx9-wg; then
success "nx9-wg.service is active and running."
else
warn "nx9-wg.service is not in active state. Inspecting journal..."
journalctl -u nx9-wg -n 20 --no-pager || true
error "Service failed to start."
fi
fi
elif [[ "${NO_RESTART}" -eq 1 ]]; then
log "Skipping service restart as requested (--no-restart)."
fi
# 9. Final Deployment Verification
log "Verifying deployed binary version..."
if [[ "${DRY_RUN}" -eq 0 ]]; then
DEPLOYED_VER="$("${DEST_BIN}" version | head -n 1)"
success "Deployed binary active: ${DEPLOYED_VER}"
fi
echo -e "\n================================================================="
echo -e "\033[1;32m DEPLOYMENT COMPLETED SUCCESSFULLY!\033[0m"
echo -e "================================================================="
echo " Installed Binary: ${DEST_BIN}"
echo " Configuration: ${CONF_DIR}/config.toml"
echo " Database: ${DATA_DIR}/nx9-wg.db"
echo " Service Status: systemctl status nx9-wg"
echo -e "=================================================================\n"
+155
View File
@@ -0,0 +1,155 @@
#!/usr/bin/env bash
# ==============================================================================
# nx9-wg Production Diagnostic Collector
# ==============================================================================
# PURPOSE:
# Collects a comprehensive, non-destructive diagnostic snapshot across both
# desired SQLite state and live Linux kernel networking state:
# - Systemd service & journal log health
# - UDP socket bindings & conflict inspection
# - Kernel IP link, address, and routing status
# - Kernel WireGuard link/interface and peer telemetry (via secret-safe 'wg show')
# - Netfilter / nftables ruleset in 'table inet nx9_wg'
# - Linux sysctl IP packet forwarding
# - Application-level diagnostic subsystem inspections
#
# PREREQUISITES:
# - Root privileges (recommended for kernel/socket inspection, or run via sudo)
#
# SECURITY INVARIANTS:
# - NEVER calls 'wg showconf' (which prints private keys in cleartext).
# - Relies exclusively on 'wg show' which masks private keys.
# - Strictly non-destructive: only performs read-only inspections.
#
# USAGE:
# sudo bash scripts/diagnose.sh
# ./scripts/diagnose.sh
# ==============================================================================
set -uo pipefail
BIN="/usr/local/bin/nx9-wg"
if [[ ! -x "${BIN}" ]]; then
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
ROOT_DIR="$(cd "${SCRIPT_DIR}/.." && pwd)"
if [[ -x "${ROOT_DIR}/target/release/nx9-wg" ]]; then
BIN="${ROOT_DIR}/target/release/nx9-wg"
elif [[ -x "${ROOT_DIR}/target/debug/nx9-wg" ]]; then
BIN="${ROOT_DIR}/target/debug/nx9-wg"
fi
fi
section() {
echo -e "\n================================================================="
echo -e "\033[1;36m>> $*\033[0m"
echo -e "================================================================="
}
subsection() {
echo -e "\n\033[1;33m--- $*\033[0m"
}
section "1. System & Host Runtime Environment"
echo "Timestamp: $(date --iso-8601=seconds)"
echo "Hostname: $(hostname)"
echo "Kernel: $(uname -r)"
echo "Architecture: $(uname -m)"
echo "Uptime: $(uptime -p 2>/dev/null || uptime)"
if [[ -x "${BIN}" ]]; then
echo "nx9-wg: $("${BIN}" version | head -n 1)"
else
echo "nx9-wg: Binary not found"
fi
section "2. Systemd Service & Process State"
if command -v systemctl >/dev/null 2>&1; then
subsection "Service Status (nx9-wg.service)"
systemctl status nx9-wg --no-pager -l || true
subsection "Recent Journalctl Logs (Last 30 entries)"
journalctl -u nx9-wg -n 30 --no-pager || true
else
echo "systemctl not available on this host."
fi
section "3. UDP Sockets & Listen Port Inspection"
if command -v ss >/dev/null 2>&1; then
subsection "Active UDP Listen Sockets (ss -lunp)"
ss -lunp 2>/dev/null || true
else
echo "ss utility not found."
fi
section "4. Linux Network Interfaces & Addresses"
if command -v ip >/dev/null 2>&1; then
subsection "Brief Interface State (ip -br link)"
ip -br link show || true
subsection "Brief IPv4 / IPv6 Addresses (ip -br addr)"
ip -br addr show || true
subsection "WireGuard Interface Addresses"
if command -v wg >/dev/null 2>&1; then
WG_INTERFACES="$(wg show interfaces 2>/dev/null || true)"
if [[ -n "${WG_INTERFACES}" ]]; then
for WG_IFACE in ${WG_INTERFACES}; do
echo "Interface: ${WG_IFACE}"
ip addr show dev "${WG_IFACE}" 2>/dev/null || true
done
else
echo "No WireGuard interfaces reported by the kernel."
fi
else
echo "wg utility not found; WireGuard interface-specific address inspection skipped."
fi
else
echo "ip utility not found."
fi
section "5. Kernel Routing Table"
if command -v ip >/dev/null 2>&1; then
subsection "IPv4 Routes (ip route show)"
ip route show || true
subsection "IPv6 Routes (ip -6 route show)"
ip -6 route show || true
fi
section "6. Kernel WireGuard Telemetry (Secret-Safe 'wg show')"
if command -v wg >/dev/null 2>&1; then
wg show 2>&1 || echo "wg show returned non-zero (may require root privileges)."
else
echo "wg utility not found on host."
fi
section "7. Netfilter / nftables Firewall State (table inet nx9_wg)"
if command -v nft >/dev/null 2>&1; then
nft list table inet nx9_wg 2>/dev/null || echo "nftables table 'inet nx9_wg' not present."
else
echo "nft utility not found on host."
fi
section "8. IP Packet Forwarding (Kernel Sysctl)"
echo -n "net.ipv4.ip_forward: "
cat /proc/sys/net/ipv4/ip_forward 2>/dev/null || echo "Unable to read /proc/sys/net/ipv4/ip_forward"
echo -n "net.ipv6.conf.all.forwarding: "
cat /proc/sys/net/ipv6/conf/all/forwarding 2>/dev/null || echo "Unable to read /proc/sys/net/ipv6/conf/all/forwarding"
section "9. Application Desired State & Health Checks"
if [[ -x "${BIN}" ]]; then
subsection "Appliance Health Check"
"${BIN}" system health 2>&1 || true
subsection "All Subsystems Diagnostics"
"${BIN}" diagnostics all 2>&1 || true
subsection "Reconciliation Drift Status"
"${BIN}" reconcile status 2>&1 || true
subsection "Live WireGuard Interface Status"
"${BIN}" live interface list 2>&1 || true
else
echo "nx9-wg binary not executable; skipping application-level diagnostics."
fi
section "Diagnostic Collection Complete"
Regular → Executable
+1 -1
View File
@@ -161,7 +161,7 @@ fi
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 info >/dev/null 2>&1; then
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..."
Regular → Executable
View File
File mode changed.
+174
View File
@@ -0,0 +1,174 @@
#!/usr/bin/env bash
# ==============================================================================
# nx9-wg Production Rollback Tool
# ==============================================================================
# PURPOSE:
# Rolls back the active production binary (/usr/local/bin/nx9-wg) to the most
# recent (or specified) backup binary created during previous deployments.
#
# PREREQUISITES:
# - Root privileges (or sudo)
# - At least one backup binary at /usr/local/bin/nx9-wg.backup.*
#
# SAFETY INVARIANTS:
# - Never modifies or deletes the SQLite database.
# - Restores executable permissions (0755) and root ownership.
# - Confirms service restoration and binary version after rollback.
#
# USAGE:
# sudo bash scripts/rollback.sh [OPTIONS] [SPECIFIC_BACKUP_PATH]
#
# OPTIONS:
# -y, --yes Skip confirmation prompt
# -l, --list List available backup binaries and exit
# -h, --help Show this help message
# ==============================================================================
set -euo pipefail
BIN_DIR="/usr/local/bin"
ACTIVE_BIN="${BIN_DIR}/nx9-wg"
ASSUME_YES=0
LIST_ONLY=0
SPECIFIED_BACKUP=""
usage() {
cat <<EOF
nx9-wg Production Rollback Tool
Usage:
sudo bash scripts/rollback.sh [OPTIONS] [BACKUP_FILE]
Options:
-y, --yes Skip interactive confirmation prompt
-l, --list List available backup binaries and exit
-h, --help Show this help message
EOF
exit 0
}
while [[ $# -gt 0 ]]; do
case "$1" in
-y|--yes)
ASSUME_YES=1
shift
;;
-l|--list)
LIST_ONLY=1
shift
;;
-h|--help)
usage
;;
-*)
echo "Unknown option: $1" >&2
usage
;;
*)
SPECIFIED_BACKUP="$1"
shift
;;
esac
done
log() {
echo -e "\033[1;34m[ROLLBACK]\033[0m \033[1;37m$*\033[0m"
}
success() {
echo -e "\033[1;32m[SUCCESS]\033[0m $*"
}
warn() {
echo -e "\033[1;33m[WARN]\033[0m $*"
}
error() {
echo -e "\033[1;31m[ERROR]\033[0m $*" >&2
exit 1
}
# 1. Privilege Verification (unless list only)
if [[ "${EUID}" -ne 0 && "${LIST_ONLY}" -eq 0 ]]; then
error "Rollback must be run as root (or via sudo)."
fi
# 2. Discover Available Backups
BACKUPS=($(ls -1t "${ACTIVE_BIN}".backup.* 2>/dev/null || true))
if [[ "${#BACKUPS[@]}" -eq 0 ]]; then
error "No backup binaries found in ${BIN_DIR} matching nx9-wg.backup.*"
fi
if [[ "${LIST_ONLY}" -eq 1 ]]; then
echo "Available production backup binaries in ${BIN_DIR}:"
for b in "${BACKUPS[@]}"; do
SIZE="$(du -h "$b" | cut -f1)"
DATE="$(date -r "$b" '+%Y-%m-%d %H:%M:%S')"
echo " $b (${SIZE}, ${DATE})"
done
exit 0
fi
# 3. Select Target Backup
TARGET_BACKUP=""
if [[ -n "${SPECIFIED_BACKUP}" ]]; then
if [[ -f "${SPECIFIED_BACKUP}" ]]; then
TARGET_BACKUP="${SPECIFIED_BACKUP}"
elif [[ -f "${BIN_DIR}/${SPECIFIED_BACKUP}" ]]; then
TARGET_BACKUP="${BIN_DIR}/${SPECIFIED_BACKUP}"
else
error "Specified backup file not found: ${SPECIFIED_BACKUP}"
fi
else
TARGET_BACKUP="${BACKUPS[0]}"
fi
log "Selected rollback target: ${TARGET_BACKUP}"
BACKUP_SIZE="$(du -h "${TARGET_BACKUP}" | cut -f1)"
BACKUP_DATE="$(date -r "${TARGET_BACKUP}" '+%Y-%m-%d %H:%M:%S')"
echo " Size: ${BACKUP_SIZE}"
echo " Timestamp: ${BACKUP_DATE}"
# 4. Confirmation Prompt
if [[ "${ASSUME_YES}" -eq 0 ]]; then
echo -e "\n\033[1;33mAre you sure you want to replace active binary ${ACTIVE_BIN} with ${TARGET_BACKUP}?\033[0m"
read -r -p "Type 'yes' to proceed with rollback: " CONFIRM
if [[ "${CONFIRM}" != "yes" ]]; then
error "Rollback aborted by user."
fi
fi
# 5. Execute Rollback
if command -v systemctl >/dev/null 2>&1; then
if systemctl is-active --quiet nx9-wg 2>/dev/null; then
log "Stopping nx9-wg service..."
systemctl stop nx9-wg || true
fi
fi
log "Restoring binary from ${TARGET_BACKUP} to ${ACTIVE_BIN}..."
install -m 0755 "${TARGET_BACKUP}" "${ACTIVE_BIN}"
# 6. Restart Service
if command -v systemctl >/dev/null 2>&1; then
log "Starting nx9-wg service..."
systemctl start nx9-wg || error "Failed to restart nx9-wg service after rollback."
sleep 1
if systemctl is-active --quiet nx9-wg; then
success "nx9-wg.service is active and running."
else
warn "nx9-wg.service is not active. Checking logs:"
journalctl -u nx9-wg -n 20 --no-pager || true
error "Service failed to become active after rollback."
fi
fi
# 7. Verify Restored Version
RESTORED_VER="$("${ACTIVE_BIN}" version | head -n 1)"
success "Rollback successful. Active binary version: ${RESTORED_VER}"
echo -e "\n================================================================="
echo -e "\033[1;32m PRODUCTION ROLLBACK COMPLETED SUCCESSFULLY!\033[0m"
echo -e "=================================================================\n"
+7 -2
View File
@@ -154,9 +154,14 @@ log_pass "Pre-flight baseline captured in ${BASELINE_DIR}"
# ----------------------------------------------------------------------------
section "02 — SQLite Store Initialization"
TEMP_ADMIN_PW="$(head -c 24 /dev/urandom | base64 | tr -dc 'A-Za-z0-9!@#%^&*_-' | head -c 20)"
PW_FILE="${TEST_ROOT}/admin_pw.txt"
echo -n "${TEMP_ADMIN_PW}" > "${PW_FILE}"
chmod 0600 "${PW_FILE}"
"${BIN}" --data-dir "${DATA_DIR}" --database "${DB_PATH}" init \
--username "admin" \
--password "AdminPassword123!" >/dev/null
--password-file "${PW_FILE}" >/dev/null
if [[ -f "${DB_PATH}" ]]; then
log_pass "SQLite authoritative store created and migrated"
@@ -288,7 +293,7 @@ all_dumps="${TEST_ROOT}/all_dumps.txt"
"${BIN}" --data-dir "${DATA_DIR}" --database "${DB_PATH}" --json reconcile plan >> "${all_dumps}" 2>&1 || true
"${BIN}" --data-dir "${DATA_DIR}" --database "${DB_PATH}" --json diagnostics all >> "${all_dumps}" 2>&1 || true
if grep -q "AdminPassword123!" "${all_dumps}"; then
if grep -F -q "${TEMP_ADMIN_PW}" "${all_dumps}"; then
log_fail "Plaintext administrator password found in command output"
else
log_pass "Zero plaintext passwords leaked in CLI/diagnostics output"
Regular → Executable
-1
View File
@@ -119,4 +119,3 @@ else
fi
log "nx9-wg uninstalled successfully."
EOF
+83
View File
@@ -0,0 +1,83 @@
#!/usr/bin/env bash
# ==============================================================================
# nx9-wg Development Verification Gate
# ==============================================================================
# PURPOSE:
# Executes the full development and release quality gate suite in sequence:
# 1. Formatting verification (cargo fmt --all -- --check)
# 2. Workspace compilation (cargo check --workspace --all-targets)
# 3. Strict Clippy linting (cargo clippy --workspace --all-targets --all-features -- -D warnings)
# 4. Complete workspace unit & integration tests (cargo test --workspace --all-targets)
# 5. Comprehensive CLI verification (scripts/test-cli-comprehensive.sh)
#
# PREREQUISITES:
# - Rust toolchain (cargo, rustc, rustfmt, clippy)
#
# BEHAVIOR:
# - 100% Non-destructive.
# - Returns exit code 0 if all checks pass.
# - Returns non-zero exit code immediately on any failure.
#
# USAGE:
# bash scripts/verify.sh
# ./scripts/verify.sh
# ==============================================================================
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
ROOT_DIR="$(cd "${SCRIPT_DIR}/.." && pwd)"
log() {
echo -e "\n\033[1;34m[VERIFY]\033[0m \033[1;37m$*\033[0m"
}
success() {
echo -e "\033[1;32m[PASS]\033[0m $*"
}
error() {
echo -e "\033[1;31m[FAIL]\033[0m $*" >&2
exit 1
}
cd "${ROOT_DIR}"
log "1/5 Checking code formatting..."
if cargo fmt --all -- --check; then
success "Code formatting is clean."
else
error "Formatting check failed. Run 'cargo fmt --all' to fix."
fi
log "2/5 Compiling workspace targets..."
if cargo check --workspace --all-targets; then
success "Workspace compilation check passed."
else
error "Compilation check failed."
fi
log "3/5 Running Clippy with -D warnings..."
if cargo clippy --workspace --all-targets --all-features -- -D warnings; then
success "Clippy linting passed with 0 warnings."
else
error "Clippy check failed."
fi
log "4/5 Running complete workspace test suite..."
if cargo test --workspace --all-targets; then
success "All workspace unit and integration tests passed."
else
error "Workspace test suite failed."
fi
log "5/5 Running comprehensive CLI verification..."
if bash "${SCRIPT_DIR}/test-cli-comprehensive.sh"; then
success "CLI comprehensive verification suite passed."
else
error "CLI verification failed."
fi
echo -e "\n================================================================="
echo -e "\033[1;32m ALL VERIFICATION QUALITY GATES PASSED SUCCESSFULLY!\033[0m"
echo -e "=================================================================\n"