OwnGit: свой "аналог GitHub" на Ubuntu 24.04
Готовый комплект для поднятия собственного git-сервера (Gitea/Forgejo) за HAProxy:
- reverse proxy и TLS на HAProxy;
- Gitea внутри сети;
- SSH для
git push/pull; - миграция репозиториев с GitHub (public + private).
Состав репозитория
haproxy/haproxy.cfg— полный конфиг HAProxy (с Gitea, Zabbix, Synology, RDP, SMTP).docs/haproxy-kalinamall.cfg— периметровый HAProxy kalinamall.ru (TCP+SNI:443, Exchange/RDS/ERP/SMTP) и Giteagit.kalinamall.ru→192.168.160.129:443, SSH:2222.docs/haproxy-kalinamall.md— описание схемы kalinamall.ru,git.kalinamall.ru, DNS иapp.ini.gitea/docker-compose.yml— запуск Gitea в Docker.gitea/app.ini.example— шаблон конфигурации Gitea.scripts/migrate-github-to-gitea.sh— массовая миграция репозиториев GitHub в Gitea.scripts/preflight-check.sh— быстрая проверка DNS/портов/healthz/SSH.scripts/postinstall-check.sh— post-install тесты Gitea + внешний HAProxy + SSH.scripts/backup-gitea.sh— бэкап данных Gitea с ротацией.scripts/restore-gitea.sh— восстановление Gitea из архива бэкапа.scripts/setup-ufw.sh— базовая настройка UFW под эту схему портов.scripts/safe-apply-ssh-hardening.sh— безопасное применение SSH hardening.scripts/safe-apply-ssh-lockdown.sh— безопасное применение строгого SSH lockdown-профиля.scripts/bootstrap-own-git.sh— one-shot установка стека (deps + Gitea + опционально HAProxy + fail2ban + timer)..env.example— шаблон переменных окружения для миграции.Makefile— быстрые команды установки/проверки/миграции.docs/troubleshooting.md— типовые проблемы и диагностика.docs/security-hardening.md— чеклист усиления безопасности (P0/P1/P2)..github/workflows/haproxy-lint.yml— CI-проверка синтаксисаhaproxy.cfg..github/workflows/scripts-and-docs-check.yml—shellcheckи проверка markdown-ссылок.systemd/— unit/timer для ежедневных бэкапов через systemd.fail2ban/jail.d/owngit.local— готовый профиль fail2ban (sshd + recidive).ssh/sshd_config.d/90-owngit-hardening.conf— шаблон безопасных SSH-настроек.ssh/sshd_config.d/95-owngit-lockdown.conf.example— опциональный строгий профиль (AllowUsers/Match Address).
Архитектура
- Публичный домен Gitea:
git.papatramp.ru. - TLS-сертификат хранится и завершается на HAProxy (
:443). - Внутренний доступ к Gitea:
192.168.128.100:3000. - Git SSH: внешний
:2222на HAProxy -> внутренний192.168.128.100:2222.
Отдельный контур kalinamall.ru: TLS на бэкендах (GlobalSign wildcard); HAProxy только маршрутизирует по SNI на :443. Подробнее — docs/haproxy-kalinamall.md, конфиг — docs/haproxy-kalinamall.cfg. На Gitea в app.ini: ROOT_URL=https://git.kalinamall.ru/ и настройки SSH-домена/порта под внешний :2222.
1) Установка Gitea
sudo apt update
sudo apt install -y docker.io docker-compose-plugin
sudo systemctl enable --now docker
Если apt сообщает Unable to locate package docker-compose-plugin, см. раздел 10 в docs/troubleshooting.md.
sudo mkdir -p /opt/gitea/data/gitea/conf
sudo cp gitea/docker-compose.yml /opt/gitea/docker-compose.yml
cd /opt/gitea
sudo docker compose up -d
Или one-shot bootstrap (без локального HAProxy, если он уже есть отдельно):
cd /путь/к/клону/owngit
chmod +x scripts/bootstrap-own-git.sh
sudo OWGIT_REPO_DIR="$(pwd)" ENABLE_HAPROXY=false ./scripts/bootstrap-own-git.sh
Переменная OWGIT_REPO_DIR должна указывать на реальный каталог с этим репозиторием (где есть gitea/docker-compose.yml). Если вы задали /opt/owngit, но клон лежит в /tmp/owngit, файлы не найдутся — используйте $(pwd) из каталога клона или склонируйте в /opt/owngit.
Вариант из /opt после git clone … /opt/owngit:
sudo OWGIT_REPO_DIR=/opt/owngit ENABLE_HAPROXY=false ./scripts/bootstrap-own-git.sh
Сначала безопасная проверка шагов без изменений:
cd /путь/к/owngit
sudo OWGIT_REPO_DIR="$(pwd)" ENABLE_HAPROXY=false ./scripts/bootstrap-own-git.sh --dry-run
Полезные переменные bootstrap:
SERVER_DOMAIN=git.papatramp.ru
GITEA_LAN_IP=192.168.128.100
ENABLE_HAPROXY=false
ENABLE_REMOTE_HAPROXY_DEPLOY=false
REMOTE_HAPROXY_HOST=192.168.128.65
REMOTE_HAPROXY_PORT=22
REMOTE_HAPROXY_USER=papatramp
# REMOTE_HAPROXY_PASSWORD='ваш_пароль_ssh'
INSTALL_UFW=false
ENABLE_FAIL2BAN=true
ENABLE_BACKUP_TIMER=true
Безопасный порядок для чистого Ubuntu 24.04
sudo mkdir -p /opt && cd /opt
sudo git clone https://github.com/PTah/owngit.git
cd /opt/owngit && sudo chmod +x scripts/bootstrap-own-git.sh
Сначала прогон без изменений:
cd /opt/owngit
sudo OWGIT_REPO_DIR=/opt/owngit ENABLE_HAPROXY=false ./scripts/bootstrap-own-git.sh --dry-run
Потом реальный запуск:
cd /opt/owngit
sudo OWGIT_REPO_DIR=/opt/owngit ENABLE_HAPROXY=false ./scripts/bootstrap-own-git.sh
После установки быстрая проверка:
docker ps
sudo systemctl status haproxy --no-pager
curl -sS -o /dev/null -w "%{http_code}\n" http://127.0.0.1:3000/api/healthz
Если HAProxy у вас на отдельном узле (например, 192.168.128.65), проверяйте его сервис на этом узле и обновите там backend на новый IP Gitea (:3000) и SSH proxy (:2222).
Автообновление удаленного HAProxy по SSH
bootstrap-own-git.sh умеет подключаться к удаленному HAProxy-серверу, делать backup текущего /etc/haproxy/haproxy.cfg, загружать новый конфиг, валидировать его и делать reload (с откатом при ошибке).
Пример запуска для вашего случая:
cd /opt/owngit
sudo OWGIT_REPO_DIR=/opt/owngit \
ENABLE_HAPROXY=false \
ENABLE_REMOTE_HAPROXY_DEPLOY=true \
REMOTE_HAPROXY_HOST=192.168.128.65 \
REMOTE_HAPROXY_USER=papatramp \
REMOTE_HAPROXY_PASSWORD='ваш_пароль_ssh' \
./scripts/bootstrap-own-git.sh
Рекомендуется сначала сделать dry-run с теми же переменными.
Post-install тест-скрипт (рекомендуется)
После bootstrap можно прогнать единый тест-скрипт:
chmod +x scripts/postinstall-check.sh
sudo SERVER_DOMAIN=git.papatramp.ru \
CHECK_REMOTE_HAPROXY=true \
REMOTE_HAPROXY_HOST=192.168.128.65 \
REMOTE_HAPROXY_USER=papatramp \
REMOTE_HAPROXY_PASSWORD='ваш_пароль_ssh' \
scripts/postinstall-check.sh
Скрипт проверяет:
- контейнер
giteaна текущем сервере; - локальный ответ
http://127.0.0.1:3000; - публичный
https://git.papatramp.ru; - доступность SSH порта
:2222; - валидность и статус сервиса HAProxy на удаленном узле;
- наличие backup-файлов
haproxy.cfg.bak.*на удаленном узле.
Положить app.ini:
sudo cp gitea/app.ini.example /opt/gitea/data/gitea/conf/app.ini
sudo nano /opt/gitea/data/gitea/conf/app.ini
sudo docker compose restart gitea
Сгенерировать секреты и прописать их в app.ini, секция [security]:
| Параметр | Назначение |
|---|---|
SECRET_KEY |
Подпись сессий и cookie веб-интерфейса; должен быть длинным случайным значением и не меняться без необходимости. |
INTERNAL_TOKEN |
Внутренние вызовы API между компонентами Gitea; тоже случайная длинная строка, храните в секрете. |
В gitea/app.ini.example они заданы как плейсхолдеры CHANGE_ME_*. Если при первом запуске Gitea сам перезаписал app.ini, откройте файл и найдите блок [security] — строки могут называться так же; если секции нет, добавьте её по образцу из примера.
Сгенерировать два разных значения (по одному на каждый параметр):
openssl rand -hex 32
openssl rand -hex 32
Вставьте первую строку в SECRET_KEY = ..., вторую в INTERNAL_TOKEN = ..., без кавычек. Перезапуск: sudo docker compose -f /opt/gitea/docker-compose.yml restart gitea.
2) Установка HAProxy конфига
Если HAProxy уже работает на отдельном сервере (например, 192.168.128.65), этот раздел применяется на том сервере HAProxy, а не на хосте с Gitea.
sudo cp haproxy/haproxy.cfg /etc/haproxy/haproxy.cfg
sudo haproxy -c -f /etc/haproxy/haproxy.cfg
sudo systemctl reload haproxy
Важно: сертификат papatramp.pem должен включать SAN для git.papatramp.ru.
3) Нужно ли SSL на самом Gitea?
Обычно нет. Достаточно TLS на HAProxy:
- клиент <-> HAProxy: HTTPS (с сертификатом);
- HAProxy <-> Gitea: HTTP по LAN.
SSL на Gitea нужен только если нужен end-to-end TLS внутри сети или Gitea публикуется напрямую без HAProxy.
4) Работа и из интернета, и из локалки
Рекомендуется единый адрес: https://git.papatramp.ru.
Чтобы это работало из LAN:
- либо Split DNS:
git.papatramp.ru -> LAN IP HAProxy; - либо Hairpin NAT на роутере.
5) SSH-клиент (~/.ssh/config)
Host git-papatramp
HostName git.papatramp.ru
User git
Port 2222
IdentityFile ~/.ssh/id_ed25519
IdentitiesOnly yes
ServerAliveInterval 30
ServerAliveCountMax 6
Проверка:
ssh -T git-papatramp
6) Миграция репозиториев с GitHub
Скрипт в scripts/migrate-github-to-gitea.sh:
- получает список реп через GitHub API;
- создает репозитории в Gitea API;
- делает
git clone --mirror+git push --mirror; - умеет мигрировать LFS (опционально).
Пример запуска:
chmod +x scripts/migrate-github-to-gitea.sh
export GITHUB_TOKEN='ghp_...'
export GITHUB_OWNER='your_github_user_or_org'
export GITHUB_OWNER_TYPE='user' # или org
export GITEA_URL='https://git.papatramp.ru'
export GITEA_TOKEN='gitea_pat'
export GITEA_OWNER='your_gitea_user_or_org'
export GITEA_OWNER_TYPE='user' # или org
export PUSH_WITH_SSH='true'
export GITEA_SSH_HOST='git.papatramp.ru'
export GITEA_SSH_PORT='2222'
export MIGRATE_LFS='true'
./scripts/migrate-github-to-gitea.sh
7) Быстрые проверки
Локально Gitea: curl -I на корень :3000/ может дать 405 (HEAD не разрешён); для проверки используйте /api/healthz или GET:
curl -sS -o /dev/null -w "%{http_code}\n" http://192.168.128.100:3000/api/healthz
curl -sSI https://git.papatramp.ru/api/healthz | head -n1
nc -zv git.papatramp.ru 2222
Если всё корректно:
- web UI открывается по
https://git.papatramp.ru; ssh -T git-papatrampдостигает Gitea;git clone/pushработает по SSH/HTTPS.
8) Полезные команды через Makefile
make help
make check-haproxy
make deploy-haproxy
make gitea-up
make gitea-restart
Запуск миграции через .env:
cp .env.example .env
nano .env
make dry-run
make migrate
9) Preflight и backup
chmod +x scripts/preflight-check.sh scripts/backup-gitea.sh
./scripts/preflight-check.sh
Запуск бэкапа вручную:
sudo ./scripts/backup-gitea.sh
Пример cron (ежедневно в 03:10):
10 3 * * * /opt/owngit/scripts/backup-gitea.sh >> /var/log/gitea-backup.log 2>&1
Восстановление:
sudo ./scripts/restore-gitea.sh /opt/backups/gitea/gitea-backup-YYYYMMDD-HHMMSS.tar.gz
10) Автобэкапы через systemd timer
Установка:
sudo cp systemd/gitea-backup.service /etc/systemd/system/gitea-backup.service
sudo cp systemd/gitea-backup.timer /etc/systemd/system/gitea-backup.timer
sudo systemctl daemon-reload
sudo systemctl enable --now gitea-backup.timer
Проверка:
systemctl list-timers --all | grep gitea-backup
sudo systemctl status gitea-backup.timer --no-pager
11) Hardening (firewall + fail2ban)
chmod +x scripts/setup-ufw.sh
sudo ./scripts/setup-ufw.sh
Настройка fail2ban:
sudo apt install -y fail2ban
sudo cp fail2ban/jail.d/owngit.local /etc/fail2ban/jail.d/owngit.local
sudo systemctl enable --now fail2ban
sudo fail2ban-client status
Подробный чеклист и приоритеты см. в docs/security-hardening.md.
Применение SSH hardening:
chmod +x scripts/safe-apply-ssh-hardening.sh
sudo ./scripts/safe-apply-ssh-hardening.sh
Опциональный lockdown:
chmod +x scripts/safe-apply-ssh-lockdown.sh
sudo ./scripts/safe-apply-ssh-lockdown.sh