#!/usr/bin/env bash set -euo pipefail # --------------------------- # Config # --------------------------- REPO_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" NGINX_ETC="/etc/nginx" SITES_AVAIL="$NGINX_ETC/sites-available" SITES_ENABLED="$NGINX_ETC/sites-enabled" SNIPPETS="$NGINX_ETC/snippets" CONFD="$NGINX_ETC/conf.d" # Static file deploy targets (match your current layout) WEB_HTML="/var/www/html" WEB_ERRORS="/var/www/errors" ENABLE_SITES=( "default" "nik4nao.home.arpa" "nik4nao.xyz" "prv-api.nik4nao.xyz" ) BACKUP_BASE="/var/backups/nginx-conf-deploy" # --------------------------- # Helpers # --------------------------- usage() { cat <<'EOF' Usage: sudo ./deploy-nginx.sh [--dry-run] EOF } log() { echo "==> $*"; } need_root() { if [[ "${EUID}" -ne 0 ]]; then echo "ERROR: run as root (use sudo)." >&2 exit 1 fi } DRY_RUN=0 if [[ "${1:-}" == "--dry-run" ]]; then DRY_RUN=1 elif [[ "${1:-}" == "-h" || "${1:-}" == "--help" ]]; then usage exit 0 elif [[ -n "${1:-}" ]]; then echo "Unknown option: $1" >&2 usage exit 1 fi need_root timestamp="$(date +%Y%m%d-%H%M%S)" backup_dir="${BACKUP_BASE}/${timestamp}" backup_tar="${backup_dir}/backup.tar.gz" mkdir_p() { if (( DRY_RUN )); then log "[dry-run] mkdir -p $*" else mkdir -p "$@" fi } copy_file() { local src="$1" local dst="$2" if [[ ! -f "$src" ]]; then echo "ERROR: missing source file: $src" >&2 exit 1 fi if (( DRY_RUN )); then log "[dry-run] install -m 0644 $src -> $dst" else install -m 0644 -D "$src" "$dst" fi } make_symlink() { local target="$1" local linkpath="$2" if (( DRY_RUN )); then log "[dry-run] ln -sfn $target $linkpath" else ln -sfn "$target" "$linkpath" fi } sync_selected_http_files() { # Copy only the files you actually use, into the two target dirs local src_dir="$REPO_DIR/http" # /var/www/html for f in index.html index.nginx-debian.html nik4nao-xyz-landing.html; do if [[ -f "$src_dir/$f" ]]; then copy_file "$src_dir/$f" "$WEB_HTML/$f" fi done # /var/www/errors for f in 404.html 50x.html; do if [[ -f "$src_dir/$f" ]]; then copy_file "$src_dir/$f" "$WEB_ERRORS/$f" fi done } backup_paths=() add_backup_path() { local p="$1" if [[ -e "$p" || -L "$p" ]]; then backup_paths+=("$p") fi } do_backup() { mkdir_p "$backup_dir" # nginx files we touch add_backup_path "$NGINX_ETC/nginx.conf" add_backup_path "$CONFD/upstreams.conf" add_backup_path "$SNIPPETS/proxy-common.conf" for s in "${ENABLE_SITES[@]}"; do add_backup_path "$SITES_AVAIL/$s" add_backup_path "$SITES_ENABLED/$s" done # static files we touch (only the known ones) for f in index.html index.nginx-debian.html nik4nao-xyz-landing.html robots.txt; do add_backup_path "$WEB_HTML/$f" done for f in 404.html 50x.html; do add_backup_path "$WEB_ERRORS/$f" done if (( DRY_RUN )); then log "[dry-run] tar -czf $backup_tar -P ${backup_paths[*]:-}" return fi if ((${#backup_paths[@]} == 0)); then log "No existing paths found to backup (first deploy?)." return fi log "Creating backup: $backup_tar" tar -czf "$backup_tar" -P "${backup_paths[@]}" } restore_backup() { if (( DRY_RUN )); then log "[dry-run] restore from $backup_tar" return fi if [[ -f "$backup_tar" ]]; then log "Restoring from backup..." tar -xzf "$backup_tar" -P else log "No backup tar found to restore: $backup_tar" fi } nginx_test() { if (( DRY_RUN )); then log "[dry-run] nginx -t" return 0 fi nginx -t } nginx_reload() { if (( DRY_RUN )); then log "[dry-run] systemctl reload nginx" return 0 fi systemctl reload nginx } # --------------------------- # Deploy # --------------------------- log "Repo: $REPO_DIR" do_backup mkdir_p "$SITES_AVAIL" "$SITES_ENABLED" "$SNIPPETS" "$CONFD" "$WEB_HTML" "$WEB_ERRORS" # Copy core config/snippets copy_file "$REPO_DIR/nginx.conf" "$NGINX_ETC/nginx.conf" copy_file "$REPO_DIR/upstreams.conf" "$CONFD/upstreams.conf" copy_file "$REPO_DIR/proxy-common.conf" "$SNIPPETS/proxy-common.conf" # Copy site configs (repo *.conf -> /etc/nginx/sites-available/) copy_file "$REPO_DIR/default.conf" "$SITES_AVAIL/default" copy_file "$REPO_DIR/nik4nao.home.arpa.conf" "$SITES_AVAIL/nik4nao.home.arpa" copy_file "$REPO_DIR/nik4nao.xyz.conf" "$SITES_AVAIL/nik4nao.xyz" copy_file "$REPO_DIR/prv-api.nik4nao.xyz.conf" "$SITES_AVAIL/prv-api.nik4nao.xyz" # Enable sites for s in "${ENABLE_SITES[@]}"; do make_symlink "$SITES_AVAIL/$s" "$SITES_ENABLED/$s" done # Static files sync_selected_http_files if [[ -f "$REPO_DIR/robots.txt" ]]; then copy_file "$REPO_DIR/robots.txt" "$WEB_HTML/robots.txt" fi # Test + reload (rollback on failure) log "Testing nginx config..." if nginx_test; then log "Reloading nginx..." nginx_reload log "Done ✅" else log "nginx -t failed ❌" log "Rolling back..." restore_backup log "Re-testing after rollback..." nginx_test || true exit 2 fi