Initial own-git docs, configs, scripts, and hardening pack
This commit is contained in:
@@ -0,0 +1,246 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# One-shot bootstrap для own-git стека:
|
||||
# - устанавливает зависимости;
|
||||
# - разворачивает Gitea через docker compose;
|
||||
# - раскладывает конфиги HAProxy/fail2ban/systemd;
|
||||
# - включает timer бэкапов;
|
||||
# - печатает пост-инсталляционный чеклист.
|
||||
#
|
||||
# ВНИМАНИЕ:
|
||||
# 1) Проверьте и отредактируйте переменные ниже перед запуском.
|
||||
# 2) Скрипт рассчитан на Ubuntu 24.04+.
|
||||
# 3) Запускать от root (sudo).
|
||||
|
||||
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}"
|
||||
INSTALL_UFW="${INSTALL_UFW:-false}"
|
||||
ENABLE_FAIL2BAN="${ENABLE_FAIL2BAN:-true}"
|
||||
ENABLE_BACKUP_TIMER="${ENABLE_BACKUP_TIMER:-true}"
|
||||
DRY_RUN="${DRY_RUN:-false}"
|
||||
|
||||
log() { echo "[INFO] $*"; }
|
||||
ok() { echo "[OK] $*"; }
|
||||
warn() { echo "[WARN] $*"; }
|
||||
err() { echo "[ERR] $*"; }
|
||||
|
||||
usage() {
|
||||
cat <<EOF
|
||||
Usage: $0 [--dry-run]
|
||||
|
||||
Options:
|
||||
--dry-run показать все шаги без изменений в системе
|
||||
-h, --help показать эту справку
|
||||
EOF
|
||||
}
|
||||
|
||||
run_cmd() {
|
||||
if [[ "$DRY_RUN" == "true" ]]; then
|
||||
echo "[DRY] $*"
|
||||
return 0
|
||||
fi
|
||||
"$@"
|
||||
}
|
||||
|
||||
run_sh() {
|
||||
if [[ "$DRY_RUN" == "true" ]]; then
|
||||
echo "[DRY] $*"
|
||||
return 0
|
||||
fi
|
||||
bash -lc "$*"
|
||||
}
|
||||
|
||||
require_root() {
|
||||
if [[ "$DRY_RUN" == "true" ]]; then
|
||||
warn "DRY_RUN=true: проверка root пропущена"
|
||||
return
|
||||
fi
|
||||
if [[ "${EUID:-$(id -u)}" -ne 0 ]]; then
|
||||
err "Запустите через sudo."
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
require_paths() {
|
||||
local missing=0
|
||||
for p in \
|
||||
"$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
|
||||
if [[ ! -f "$p" ]]; then
|
||||
err "Не найден файл: $p"
|
||||
missing=1
|
||||
fi
|
||||
done
|
||||
[[ "$missing" -eq 0 ]] || exit 1
|
||||
}
|
||||
|
||||
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
|
||||
ok "Пакеты установлены"
|
||||
}
|
||||
|
||||
setup_dirs() {
|
||||
log "Создаю рабочие директории..."
|
||||
run_cmd mkdir -p "$GITEA_BASE_DIR/data/gitea/conf"
|
||||
run_cmd mkdir -p /etc/haproxy/certs
|
||||
ok "Директории готовы"
|
||||
}
|
||||
|
||||
deploy_gitea() {
|
||||
log "Разворачиваю Gitea compose..."
|
||||
run_cmd cp -a "$OWGIT_REPO_DIR/gitea/docker-compose.yml" "$GITEA_BASE_DIR/docker-compose.yml"
|
||||
|
||||
if [[ ! -f "$GITEA_BASE_DIR/data/gitea/conf/app.ini" ]]; then
|
||||
run_cmd cp -a "$OWGIT_REPO_DIR/gitea/app.ini.example" "$GITEA_BASE_DIR/data/gitea/conf/app.ini"
|
||||
warn "Создан app.ini из шаблона. Обязательно замените SECRET_KEY и INTERNAL_TOKEN."
|
||||
fi
|
||||
|
||||
run_cmd systemctl enable --now docker
|
||||
run_sh "cd '$GITEA_BASE_DIR' && docker compose up -d"
|
||||
ok "Gitea контейнер запущен"
|
||||
}
|
||||
|
||||
deploy_haproxy() {
|
||||
log "Устанавливаю конфиг HAProxy..."
|
||||
run_cmd cp -a "$OWGIT_REPO_DIR/haproxy/haproxy.cfg" /etc/haproxy/haproxy.cfg
|
||||
|
||||
# Файлы ACL, чтобы конфиг проходил валидацию.
|
||||
run_cmd touch /etc/haproxy/allowed_ips.lst /etc/haproxy/allowed_ips_knock.lst
|
||||
|
||||
# Если сертификат отсутствует, генерируем временный self-signed.
|
||||
if [[ ! -f /etc/haproxy/certs/papatramp.pem ]]; then
|
||||
warn "Не найден /etc/haproxy/certs/papatramp.pem, создаю временный self-signed сертификат."
|
||||
run_cmd openssl req -x509 -nodes -newkey rsa:2048 \
|
||||
-keyout /tmp/owngit-selfsigned.key \
|
||||
-out /tmp/owngit-selfsigned.crt \
|
||||
-days 7 \
|
||||
-subj "/CN=${SERVER_DOMAIN}"
|
||||
run_sh "cat /tmp/owngit-selfsigned.crt /tmp/owngit-selfsigned.key > /etc/haproxy/certs/papatramp.pem"
|
||||
run_cmd rm -f /tmp/owngit-selfsigned.crt /tmp/owngit-selfsigned.key
|
||||
warn "Используется временный сертификат. Замените на боевой Let's Encrypt/PEM."
|
||||
fi
|
||||
|
||||
run_cmd haproxy -c -f /etc/haproxy/haproxy.cfg
|
||||
run_cmd systemctl enable --now haproxy
|
||||
run_cmd systemctl reload haproxy
|
||||
ok "HAProxy применен и перезагружен"
|
||||
}
|
||||
|
||||
deploy_fail2ban() {
|
||||
if [[ "$ENABLE_FAIL2BAN" != "true" ]]; then
|
||||
warn "Fail2ban пропущен (ENABLE_FAIL2BAN=false)"
|
||||
return
|
||||
fi
|
||||
log "Настраиваю fail2ban..."
|
||||
run_cmd apt-get install -y fail2ban
|
||||
run_cmd mkdir -p /etc/fail2ban/jail.d
|
||||
run_cmd cp -a "$OWGIT_REPO_DIR/fail2ban/jail.d/owngit.local" /etc/fail2ban/jail.d/owngit.local
|
||||
run_cmd systemctl enable --now fail2ban
|
||||
ok "Fail2ban включен"
|
||||
}
|
||||
|
||||
deploy_backup_timer() {
|
||||
if [[ "$ENABLE_BACKUP_TIMER" != "true" ]]; then
|
||||
warn "Backup timer пропущен (ENABLE_BACKUP_TIMER=false)"
|
||||
return
|
||||
fi
|
||||
log "Устанавливаю systemd backup timer..."
|
||||
run_cmd cp -a "$OWGIT_REPO_DIR/systemd/gitea-backup.service" /etc/systemd/system/gitea-backup.service
|
||||
run_cmd cp -a "$OWGIT_REPO_DIR/systemd/gitea-backup.timer" /etc/systemd/system/gitea-backup.timer
|
||||
run_cmd systemctl daemon-reload
|
||||
run_cmd systemctl enable --now gitea-backup.timer
|
||||
ok "Backup timer включен"
|
||||
}
|
||||
|
||||
maybe_setup_ufw() {
|
||||
if [[ "$INSTALL_UFW" != "true" ]]; then
|
||||
warn "UFW не применялся (INSTALL_UFW=false)"
|
||||
return
|
||||
fi
|
||||
if [[ ! -x "$OWGIT_REPO_DIR/scripts/setup-ufw.sh" ]]; then
|
||||
run_cmd chmod +x "$OWGIT_REPO_DIR/scripts/setup-ufw.sh"
|
||||
fi
|
||||
log "Применяю UFW..."
|
||||
run_cmd "$OWGIT_REPO_DIR/scripts/setup-ufw.sh"
|
||||
ok "UFW настроен"
|
||||
}
|
||||
|
||||
print_checklist() {
|
||||
cat <<EOF
|
||||
|
||||
==================== POST-INSTALL CHECKLIST ====================
|
||||
1) Отредактируйте:
|
||||
- ${GITEA_BASE_DIR}/data/gitea/conf/app.ini
|
||||
- замените SECRET_KEY / INTERNAL_TOKEN
|
||||
- проверьте ROOT_URL=https://${SERVER_DOMAIN}/
|
||||
|
||||
2) Проверьте DNS:
|
||||
- ${SERVER_DOMAIN} должен резолвиться на HAProxy (WAN/LAN по вашей схеме).
|
||||
|
||||
3) Замените временный TLS сертификат:
|
||||
- /etc/haproxy/certs/papatramp.pem
|
||||
- и reload: systemctl reload haproxy
|
||||
|
||||
4) Проверки:
|
||||
- curl -I http://${GITEA_LAN_IP}:3000
|
||||
- curl -I https://${SERVER_DOMAIN}
|
||||
- nc -zv ${SERVER_DOMAIN} 2222
|
||||
|
||||
5) Запустите preflight:
|
||||
- chmod +x ${OWGIT_REPO_DIR}/scripts/preflight-check.sh
|
||||
- ${OWGIT_REPO_DIR}/scripts/preflight-check.sh
|
||||
|
||||
6) При необходимости примените SSH hardening:
|
||||
- ${OWGIT_REPO_DIR}/scripts/safe-apply-ssh-hardening.sh
|
||||
================================================================
|
||||
EOF
|
||||
}
|
||||
|
||||
main() {
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--dry-run)
|
||||
DRY_RUN=true
|
||||
shift
|
||||
;;
|
||||
-h|--help)
|
||||
usage
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
err "Неизвестный аргумент: $1"
|
||||
usage
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [[ "$DRY_RUN" == "true" ]]; then
|
||||
warn "Запуск в режиме dry-run (изменения не применяются)"
|
||||
fi
|
||||
require_root
|
||||
require_paths
|
||||
install_packages
|
||||
setup_dirs
|
||||
deploy_gitea
|
||||
deploy_haproxy
|
||||
deploy_fail2ban
|
||||
deploy_backup_timer
|
||||
maybe_setup_ufw
|
||||
print_checklist
|
||||
ok "Bootstrap завершен"
|
||||
}
|
||||
|
||||
main "$@"
|
||||
Reference in New Issue
Block a user