Add safe external HAProxy deployment flow.

Make bootstrap skip local HAProxy by default and support remote HAProxy config backup, validation, reload, and rollback over SSH.

Made-with: Cursor
This commit is contained in:
PTah
2026-04-21 22:11:54 +10:00
parent f5899ebc56
commit 57340e1349
2 changed files with 164 additions and 17 deletions
+104 -13
View File
@@ -17,6 +17,12 @@ SERVER_DOMAIN="${SERVER_DOMAIN:-git.papatramp.ru}"
GITEA_LAN_IP="${GITEA_LAN_IP:-192.168.128.100}"
OWGIT_REPO_DIR="${OWGIT_REPO_DIR:-/opt/owngit}"
GITEA_BASE_DIR="${GITEA_BASE_DIR:-/opt/gitea}"
ENABLE_HAPROXY="${ENABLE_HAPROXY:-false}"
ENABLE_REMOTE_HAPROXY_DEPLOY="${ENABLE_REMOTE_HAPROXY_DEPLOY:-false}"
REMOTE_HAPROXY_HOST="${REMOTE_HAPROXY_HOST:-192.168.128.65}"
REMOTE_HAPROXY_PORT="${REMOTE_HAPROXY_PORT:-22}"
REMOTE_HAPROXY_USER="${REMOTE_HAPROXY_USER:-papatramp}"
REMOTE_HAPROXY_PASSWORD="${REMOTE_HAPROXY_PASSWORD:-}"
INSTALL_UFW="${INSTALL_UFW:-false}"
ENABLE_FAIL2BAN="${ENABLE_FAIL2BAN:-true}"
ENABLE_BACKUP_TIMER="${ENABLE_BACKUP_TIMER:-true}"
@@ -66,13 +72,17 @@ require_root() {
require_paths() {
local missing=0
for p in \
local required_paths=(
"$OWGIT_REPO_DIR/gitea/docker-compose.yml" \
"$OWGIT_REPO_DIR/gitea/app.ini.example" \
"$OWGIT_REPO_DIR/haproxy/haproxy.cfg" \
"$OWGIT_REPO_DIR/systemd/gitea-backup.service" \
"$OWGIT_REPO_DIR/systemd/gitea-backup.timer" \
"$OWGIT_REPO_DIR/fail2ban/jail.d/owngit.local"; do
"$OWGIT_REPO_DIR/fail2ban/jail.d/owngit.local"
)
if [[ "$ENABLE_HAPROXY" == "true" || "$ENABLE_REMOTE_HAPROXY_DEPLOY" == "true" ]]; then
required_paths+=("$OWGIT_REPO_DIR/haproxy/haproxy.cfg")
fi
for p in "${required_paths[@]}"; do
if [[ ! -f "$p" ]]; then
err "Не найден файл: $p"
missing=1
@@ -84,17 +94,26 @@ require_paths() {
install_packages() {
log "Устанавливаю зависимости..."
run_cmd apt-get update
run_cmd apt-get install -y \
ca-certificates curl jq git openssl \
docker.io docker-compose-plugin \
haproxy
local packages=(
ca-certificates curl jq git openssl
docker.io docker-compose-plugin openssh-client
)
if [[ "$ENABLE_HAPROXY" == "true" ]]; then
packages+=(haproxy)
fi
if [[ "$ENABLE_REMOTE_HAPROXY_DEPLOY" == "true" && -n "$REMOTE_HAPROXY_PASSWORD" ]]; then
packages+=(sshpass)
fi
run_cmd apt-get install -y "${packages[@]}"
ok "Пакеты установлены"
}
setup_dirs() {
log "Создаю рабочие директории..."
run_cmd mkdir -p "$GITEA_BASE_DIR/data/gitea/conf"
run_cmd mkdir -p /etc/haproxy/certs
if [[ "$ENABLE_HAPROXY" == "true" ]]; then
run_cmd mkdir -p /etc/haproxy/certs
fi
ok "Директории готовы"
}
@@ -113,6 +132,10 @@ deploy_gitea() {
}
deploy_haproxy() {
if [[ "$ENABLE_HAPROXY" != "true" ]]; then
warn "HAProxy пропущен (ENABLE_HAPROXY=false). Используйте существующий внешний HAProxy."
return
fi
log "Устанавливаю конфиг HAProxy..."
run_cmd cp -a "$OWGIT_REPO_DIR/haproxy/haproxy.cfg" /etc/haproxy/haproxy.cfg
@@ -138,6 +161,66 @@ deploy_haproxy() {
ok "HAProxy применен и перезагружен"
}
remote_ssh_cmd() {
local cmd="$1"
local ssh_target="${REMOTE_HAPROXY_USER}@${REMOTE_HAPROXY_HOST}"
local ssh_opts=(-p "$REMOTE_HAPROXY_PORT" -o StrictHostKeyChecking=accept-new -o ConnectTimeout=10)
if [[ "$DRY_RUN" == "true" ]]; then
echo "[DRY] ssh ${ssh_target} ${cmd}"
return 0
fi
if [[ -n "$REMOTE_HAPROXY_PASSWORD" ]]; then
SSHPASS="$REMOTE_HAPROXY_PASSWORD" sshpass -e ssh "${ssh_opts[@]}" "$ssh_target" "$cmd"
else
ssh "${ssh_opts[@]}" "$ssh_target" "$cmd"
fi
}
remote_scp_upload() {
local src="$1"
local dst="$2"
local ssh_target="${REMOTE_HAPROXY_USER}@${REMOTE_HAPROXY_HOST}"
local scp_opts=(-P "$REMOTE_HAPROXY_PORT" -o StrictHostKeyChecking=accept-new -o ConnectTimeout=10)
if [[ "$DRY_RUN" == "true" ]]; then
echo "[DRY] scp ${src} ${ssh_target}:${dst}"
return 0
fi
if [[ -n "$REMOTE_HAPROXY_PASSWORD" ]]; then
SSHPASS="$REMOTE_HAPROXY_PASSWORD" sshpass -e scp "${scp_opts[@]}" "$src" "${ssh_target}:${dst}"
else
scp "${scp_opts[@]}" "$src" "${ssh_target}:${dst}"
fi
}
deploy_remote_haproxy() {
if [[ "$ENABLE_REMOTE_HAPROXY_DEPLOY" != "true" ]]; then
warn "Удаленный деплой HAProxy пропущен (ENABLE_REMOTE_HAPROXY_DEPLOY=false)"
return
fi
log "Обновляю HAProxy удаленно на ${REMOTE_HAPROXY_HOST}:${REMOTE_HAPROXY_PORT}..."
local ts backup_cfg remote_tmp
ts="$(date +%Y%m%d-%H%M%S)"
backup_cfg="/etc/haproxy/haproxy.cfg.bak.${ts}"
remote_tmp="/tmp/owngit-haproxy.cfg.${ts}"
remote_ssh_cmd "sudo cp -a /etc/haproxy/haproxy.cfg '${backup_cfg}'"
remote_scp_upload "$OWGIT_REPO_DIR/haproxy/haproxy.cfg" "$remote_tmp"
remote_ssh_cmd "sudo mv '${remote_tmp}' /etc/haproxy/haproxy.cfg && sudo chown root:root /etc/haproxy/haproxy.cfg && sudo chmod 644 /etc/haproxy/haproxy.cfg"
remote_ssh_cmd "sudo touch /etc/haproxy/allowed_ips.lst /etc/haproxy/allowed_ips_knock.lst"
if remote_ssh_cmd "sudo haproxy -c -f /etc/haproxy/haproxy.cfg"; then
remote_ssh_cmd "sudo systemctl reload haproxy"
ok "Удаленный HAProxy обновлен, backup: ${backup_cfg}"
else
warn "Валидация удаленного конфига не прошла, выполняю откат..."
remote_ssh_cmd "sudo cp -a '${backup_cfg}' /etc/haproxy/haproxy.cfg"
remote_ssh_cmd "sudo haproxy -c -f /etc/haproxy/haproxy.cfg && sudo systemctl reload haproxy"
err "Откат выполнен. Проверьте haproxy/haproxy.cfg перед повтором."
exit 1
fi
}
deploy_fail2ban() {
if [[ "$ENABLE_FAIL2BAN" != "true" ]]; then
warn "Fail2ban пропущен (ENABLE_FAIL2BAN=false)"
@@ -178,6 +261,12 @@ maybe_setup_ufw() {
}
print_checklist() {
local haproxy_host_hint
if [[ "$ENABLE_HAPROXY" == "true" ]]; then
haproxy_host_hint="локальном сервере"
else
haproxy_host_hint="внешнем HAProxy"
fi
cat <<EOF
==================== POST-INSTALL CHECKLIST ====================
@@ -189,14 +278,15 @@ print_checklist() {
2) Проверьте DNS:
- ${SERVER_DOMAIN} должен резолвиться на HAProxy (WAN/LAN по вашей схеме).
3) Замените временный TLS сертификат:
- /etc/haproxy/certs/papatramp.pem
- и reload: systemctl reload haproxy
3) HAProxy/TLS:
- если ENABLE_HAPROXY=true: замените /etc/haproxy/certs/papatramp.pem и выполните systemctl reload haproxy
- если ENABLE_HAPROXY=false: обновите backend/SSH-proxy на ${haproxy_host_hint}
- если ENABLE_REMOTE_HAPROXY_DEPLOY=true: удаленный /etc/haproxy/haproxy.cfg уже обновлен с backup/rollback
4) Проверки:
- curl -I http://${GITEA_LAN_IP}:3000
- curl -I https://${SERVER_DOMAIN}
- nc -zv ${SERVER_DOMAIN} 2222
- после обновления внешнего HAProxy: curl -I https://${SERVER_DOMAIN}
- после обновления внешнего HAProxy: nc -zv ${SERVER_DOMAIN} 2222
5) Запустите preflight:
- chmod +x ${OWGIT_REPO_DIR}/scripts/preflight-check.sh
@@ -236,6 +326,7 @@ main() {
setup_dirs
deploy_gitea
deploy_haproxy
deploy_remote_haproxy
deploy_fail2ban
deploy_backup_timer
maybe_setup_ufw