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:
+104
-13
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user