hardening: angie config layout (_on/targets/modules) + sane root config + enable/disable helpers
This commit is contained in:
parent
247d33ae8a
commit
0116ac60b3
@ -2,7 +2,7 @@
|
||||
# 50-hardening — system defaults. Each sub-step y/N, all idempotent.
|
||||
|
||||
step_name="hardening"
|
||||
step_desc="ssh(ufw-safe), ufw, updates, unattended, tz, hostname, swap, locale, fail2ban"
|
||||
step_desc="ssh, ufw, updates, unattended, tz, hostname, swap, locale, fail2ban, angie config"
|
||||
step_run="run_hardening"
|
||||
|
||||
run_hardening() {
|
||||
@ -14,6 +14,7 @@ run_hardening() {
|
||||
_h_swap
|
||||
_h_locale
|
||||
_h_fail2ban
|
||||
_h_angie_config
|
||||
ok "hardening pass complete"
|
||||
}
|
||||
|
||||
@ -185,4 +186,185 @@ EOF
|
||||
sudo_ systemctl enable --now fail2ban 2>/dev/null || warn "could not enable fail2ban"
|
||||
fi
|
||||
ok "fail2ban installed + sshd jail enabled"
|
||||
}
|
||||
|
||||
# ── angie config: _on/ targets/ modules/ + sane root config ────────────────
|
||||
_h_angie_config() {
|
||||
if ! command -v angie >/dev/null 2>&1; then
|
||||
echo " skip angie config (angie not installed — run the angie step first)"; return
|
||||
fi
|
||||
if ! yn "Set up Angie config layout (/etc/angie/_on targets modules) + sane root config?" y; then
|
||||
echo " skip angie config"; return
|
||||
fi
|
||||
|
||||
local d=/etc/angie
|
||||
sudo_ install -d -m 0755 "$d/_on" "$d/targets" "$d/modules" "$d/modules/http"
|
||||
|
||||
# ── extract packaging-specific values from the stock angie.conf ──
|
||||
# Angie packages set user/pid/error_log differently per distro; preserve them.
|
||||
local oldcfg="$d/angie.conf" angie_user angie_pid angie_err angie_modules=""
|
||||
if [[ -f "$oldcfg" ]]; then
|
||||
angie_user=$(grep -E '^\s*user\s+' "$oldcfg" | head -1 | awk '{print $2}' | tr -d ';')
|
||||
angie_pid=$(grep -E '^\s*pid\s+' "$oldcfg" | head -1 | awk '{print $2}' | tr -d ';')
|
||||
angie_err=$(grep -E '^\s*error_log\s+' "$oldcfg" | head -1 | awk '{print $2}' | tr -d ';')
|
||||
# collect any load_module lines (dynamic modules)
|
||||
angie_modules=$(grep -E '^\s*load_module\s+' "$oldcfg" || true)
|
||||
fi
|
||||
# sane defaults if not found
|
||||
[[ -z "$angie_user" ]] && angie_user=$({ [[ "$DISTRO" == "arch" ]] && echo http || echo angie; })
|
||||
[[ -z "$angie_pid" ]] && angie_pid=/run/angie.pid
|
||||
[[ -z "$angie_err" ]] && angie_err=/var/log/angie/error.log
|
||||
|
||||
# backup the original once
|
||||
if [[ -f "$oldcfg" && ! -f "$oldcfg.orig.bootstrap" ]]; then
|
||||
sudo_ cp -a "$oldcfg" "$oldcfg.orig.bootstrap"
|
||||
fi
|
||||
|
||||
# ── write our root angie.conf (once — guarded, won't clobber later edits) ──
|
||||
if grep -q '# managed by bootstrap' "$oldcfg" 2>/dev/null; then
|
||||
ok "$oldcfg already bootstrap-managed — leaving it (keeps your edits)"
|
||||
else
|
||||
sudo_ tee "$oldcfg" >/dev/null <<EOF
|
||||
# angie.conf — managed by bootstrap. Original backup: angie.conf.orig.bootstrap
|
||||
# Edit freely; re-running the hardening step will NOT overwrite (it writes once).
|
||||
|
||||
user $angie_user;
|
||||
worker_processes auto;
|
||||
pid $angie_pid;
|
||||
error_log $angie_err warn;
|
||||
|
||||
# dynamic modules carried over from the original package config (if any)
|
||||
$angie_modules
|
||||
# top-level context snippets (stream{}, env, etc.)
|
||||
include /etc/angie/modules/*.conf;
|
||||
|
||||
events {
|
||||
worker_connections 1024;
|
||||
}
|
||||
|
||||
http {
|
||||
include /etc/angie/mime.types;
|
||||
default_type application/octet-stream;
|
||||
|
||||
log_format main '\$remote_addr - \$remote_user [\$time_local] "\$request" '
|
||||
'\$status \$body_bytes_sent "\$http_referer" "\$http_user_agent"';
|
||||
access_log /var/log/angie/access.log main;
|
||||
|
||||
sendfile on;
|
||||
tcp_nopush on;
|
||||
tcp_nodelay on;
|
||||
keepalive_timeout 65;
|
||||
types_hash_max_size 2048;
|
||||
|
||||
server_tokens off;
|
||||
client_max_body_size 16m;
|
||||
|
||||
gzip on;
|
||||
gzip_vary on;
|
||||
gzip_proxied any;
|
||||
gzip_comp_level 5;
|
||||
gzip_min_length 256;
|
||||
gzip_types text/plain text/css application/json application/javascript
|
||||
text/xml application/xml application/xml+rss text/javascript;
|
||||
|
||||
# http-level snippets: upstreams, maps, real_ip, proxy defaults
|
||||
include /etc/angie/modules/http/*.conf;
|
||||
|
||||
# enabled hosts (symlinks from targets/*). _on/*.conf only — targets/ is staging.
|
||||
include /etc/angie/_on/*.conf;
|
||||
}
|
||||
EOF
|
||||
fi
|
||||
|
||||
# ── http-level common snippet (real_ip + proxy defaults) ──
|
||||
if [[ ! -f "$d/modules/http/00-common.conf" ]]; then
|
||||
sudo_ tee "$d/modules/http/00-common.conf" >/dev/null <<'EOF'
|
||||
# real_ip — trust private ranges + (commented Cloudflare). Uncomment/edit for your upstream.
|
||||
set_real_ip_from 10.0.0.0/8;
|
||||
set_real_ip_from 172.16.0.0/12;
|
||||
set_real_ip_from 192.168.0.0/16;
|
||||
set_real_ip_from 169.254.0.0/16;
|
||||
# set_real_ip_from 173.245.48.0/20; # Cloudflare, see https://www.cloudflare.com/ips/
|
||||
real_ip_header X-Forwarded-For;
|
||||
real_ip_recursive on;
|
||||
|
||||
# proxy defaults (inherited by every server/location unless overridden)
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
EOF
|
||||
fi
|
||||
|
||||
# ── default catch-all server: unmatched Host -> drop ──
|
||||
if [[ ! -f "$d/_on/00-default.conf" ]]; then
|
||||
sudo_ tee "$d/_on/00-default.conf" >/dev/null <<'EOF'
|
||||
# default_server: drop requests that match no enabled host (drive-by scanners, bare-IP)
|
||||
server {
|
||||
listen 80 default_server;
|
||||
listen [::]:80 default_server;
|
||||
listen 443 default_server;
|
||||
listen [::]:443 default_server;
|
||||
server_name _;
|
||||
return 444;
|
||||
}
|
||||
EOF
|
||||
fi
|
||||
|
||||
# ── angie-enable / angie-disable helpers ──
|
||||
_angie_helpers
|
||||
|
||||
# validate + (best-effort) reload
|
||||
if sudo_ angie -t 2>&1; then
|
||||
ok "angie config valid"
|
||||
if command -v systemctl >/dev/null 2>&1 && systemctl is-active angie >/dev/null 2>&1; then
|
||||
sudo_ systemctl reload angie 2>/dev/null && ok "angie reloaded"
|
||||
else
|
||||
echo " start angie when ready: sudo systemctl enable --now angie"
|
||||
fi
|
||||
else
|
||||
err "angie -t failed — review $d/angie.conf (backup at $oldcfg.orig.bootstrap)"
|
||||
fi
|
||||
|
||||
ok "angie layout ready: $d/{angie.conf,_on/,targets/,modules/,modules/http/}"
|
||||
echo " enable a site: angie-enable <name> (after writing $d/targets/<name>.conf)"
|
||||
echo " disable a site: angie-disable <name>"
|
||||
|
||||
# ufw already opened 80/443 in _h_ufw
|
||||
}
|
||||
|
||||
_angie_helpers() {
|
||||
sudo_ tee /usr/local/bin/angie-enable >/dev/null <<'EOF'
|
||||
#!/usr/bin/env bash
|
||||
# angie-enable <name> — symlink targets/<name>.conf into _on/ and validate.
|
||||
set -euo pipefail
|
||||
name="${1:-}"
|
||||
[ -n "$name" ] || { echo "usage: angie-enable <name>" >&2; exit 2; }
|
||||
target="/etc/angie/targets/${name}.conf"
|
||||
link="/etc/angie/_on/${name}.conf"
|
||||
[ -f "$target" ] || { echo "no such target: $target" >&2; exit 1; }
|
||||
ln -sfn "../targets/${name}.conf" "$link"
|
||||
echo "enabled: $name -> $link"
|
||||
if command -v angie >/dev/null 2>&1; then
|
||||
sudo angie -t || { echo "config invalid — review before reload" >&2; exit 1; }
|
||||
sudo systemctl reload angie && echo "reloaded"
|
||||
fi
|
||||
EOF
|
||||
sudo_ tee /usr/local/bin/angie-disable >/dev/null <<'EOF'
|
||||
#!/usr/bin/env bash
|
||||
# angie-disable <name> — remove the _on/<name>.conf symlink and reload.
|
||||
set -euo pipefail
|
||||
name="${1:-}"
|
||||
[ -n "$name" ] || { echo "usage: angie-disable <name>" >&2; exit 2; }
|
||||
link="/etc/angie/_on/${name}.conf"
|
||||
[ -L "$link" ] || [ -e "$link" ] || { echo "$name not enabled ($link missing)" >&2; exit 1; }
|
||||
rm -f "$link"
|
||||
echo "disabled: $name"
|
||||
if command -v angie >/dev/null 2>&1; then
|
||||
sudo angie -t || true
|
||||
sudo systemctl reload angie && echo "reloaded"
|
||||
fi
|
||||
EOF
|
||||
sudo_ chmod +x /usr/local/bin/angie-enable /usr/local/bin/angie-disable
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user