Files
owngit/README.md
T
PTah 72746cf415
Scripts And Docs Check / shellcheck (push) Has been cancelled
Scripts And Docs Check / markdown-links (push) Has been cancelled
feat(migrate): GITHUB_REPOS and GITHUB_REPOS_FILE for selective import
Made-with: Cursor
2026-04-22 15:46:09 +10:00

411 lines
17 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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) **и** Gitea `git.kalinamall.ru``192.168.160.129:443`, SSH `:2222`.
- `docs/haproxy-kalinamall.md` — описание схемы kalinamall.ru, `git.kalinamall.ru`, DNS и `app.ini`.
- `docs/gitea-nginx-https.md` — nginx на сервере Gitea: TLS на **443**, прокси на контейнер **:3000** (для связки с периметровым HAProxy).
- `nginx/` — примеры `git.kalinamall.ru` и map для WebSocket.
- `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.md), конфиг — [`docs/haproxy-kalinamall.cfg`](docs/haproxy-kalinamall.cfg). На узле Gitea поднимите **HTTPS на 443** (например **nginx** по [`docs/gitea-nginx-https.md`](docs/gitea-nginx-https.md)). В `app.ini`: `ROOT_URL=https://git.kalinamall.ru/` и настройки SSH-домена/порта под внешний `:2222`.
## 1) Установка Gitea
```bash
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`](docs/troubleshooting.md#10-e-unable-to-locate-package-docker-compose-plugin).
```bash
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, если он уже есть отдельно):
```bash
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`:
```bash
sudo OWGIT_REPO_DIR=/opt/owngit ENABLE_HAPROXY=false ./scripts/bootstrap-own-git.sh
```
Сначала безопасная проверка шагов без изменений:
```bash
cd /путь/к/owngit
sudo OWGIT_REPO_DIR="$(pwd)" ENABLE_HAPROXY=false ./scripts/bootstrap-own-git.sh --dry-run
```
Полезные переменные bootstrap:
```bash
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
```bash
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
```
Сначала прогон без изменений:
```bash
cd /opt/owngit
sudo OWGIT_REPO_DIR=/opt/owngit ENABLE_HAPROXY=false ./scripts/bootstrap-own-git.sh --dry-run
```
Потом реальный запуск:
```bash
cd /opt/owngit
sudo OWGIT_REPO_DIR=/opt/owngit ENABLE_HAPROXY=false ./scripts/bootstrap-own-git.sh
```
После установки быстрая проверка:
```bash
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` (с откатом при ошибке).
Пример запуска для вашего случая:
```bash
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 можно прогнать единый тест-скрипт:
```bash
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`:
```bash
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`](gitea/app.ini.example) они заданы как плейсхолдеры `CHANGE_ME_*`. Если при первом запуске Gitea сам перезаписал `app.ini`, откройте файл и найдите блок **`[security]`** — строки могут называться так же; если секции нет, добавьте её по образцу из примера.
Сгенерировать два разных значения (по одному на каждый параметр):
```bash
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.
```bash
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`)
Файл **`~/.ssh/config`** нужен на **вашем компьютере** (рабочая станция, ноутбук), откуда вы работаете с Git по SSH: `git clone`, `pull`, `push`, а также проверка `ssh -T …`. Это не настройка сервера Gitea и не вход администратора на сервер по SSH.
**`IdentityFile`** — путь к **вашему локальному закрытому ключу** (обычно пара создаётся командой `ssh-keygen -t ed25519 -C "email"`). В Gitea в веб-интерфейсе → **Настройки → SSH-ключи** добавляют **открытый** ключ (`*.pub`), а в `IdentityFile` указывают **закрытый** файл без суффикса `.pub`.
```sshconfig
Host git-papatramp
HostName git.papatramp.ru
User git
Port 2222
IdentityFile ~/.ssh/id_ed25519
IdentitiesOnly yes
ServerAliveInterval 30
ServerAliveCountMax 6
```
Проверка:
```bash
ssh -T git-papatramp
```
## 6) Миграция репозиториев с GitHub
Скрипт в `scripts/migrate-github-to-gitea.sh`:
- получает список реп через GitHub API;
- создает репозитории в Gitea API;
- делает `git clone --mirror` + `git push --mirror`;
- умеет мигрировать LFS (опционально).
**Только выбранные репозитории** (не весь аккаунт):
- переменная **`GITHUB_REPOS`** — через запятую полные имена **`owner/repo`**;
- и/или **`GITHUB_REPOS_FILE`** — путь к файлу, по одному **`owner/repo`** в строке, строки с **`#`** — комментарии.
Пример:
```bash
export GITHUB_REPOS="PTah/app1,PTah/app2"
# или: export GITHUB_REPOS_FILE=/root/repos-to-migrate.txt
```
Пуш в Gitea по умолчанию идёт по **SSH**. Если скрипт запускается **на самом сервере Gitea** (или под `root`) и там **нет SSH-ключа**, добавленного в ваш аккаунт Gitea, будет `Permission denied (publickey)`. Тогда используйте пуш по HTTPS: **`export PUSH_WITH_SSH=false`** и **`export GITEA_USERNAME=`** ваш логин в Gitea (пароль — ваш **`GITEA_TOKEN`**).
Пример запуска:
```bash
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'
# При PUSH_WITH_SSH=false добавьте: export GITEA_USERNAME='ваш_логин_gitea'
export MIGRATE_LFS='true'
./scripts/migrate-github-to-gitea.sh
```
## 7) Быстрые проверки
Локально Gitea: **`curl -I` на корень `:3000/` может дать 405** (HEAD не разрешён); для проверки используйте **`/api/healthz`** или GET:
```bash
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
```bash
make help
make check-haproxy
make deploy-haproxy
make gitea-up
make gitea-restart
```
Запуск миграции через `.env`:
```bash
cp .env.example .env
nano .env
make dry-run
make migrate
```
## 9) Preflight и backup
```bash
chmod +x scripts/preflight-check.sh scripts/backup-gitea.sh
./scripts/preflight-check.sh
```
Запуск бэкапа вручную:
```bash
sudo ./scripts/backup-gitea.sh
```
Пример cron (ежедневно в 03:10):
```bash
10 3 * * * /opt/owngit/scripts/backup-gitea.sh >> /var/log/gitea-backup.log 2>&1
```
Восстановление:
```bash
sudo ./scripts/restore-gitea.sh /opt/backups/gitea/gitea-backup-YYYYMMDD-HHMMSS.tar.gz
```
## 10) Автобэкапы через systemd timer
Установка:
```bash
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
```
Проверка:
```bash
systemctl list-timers --all | grep gitea-backup
sudo systemctl status gitea-backup.timer --no-pager
```
## 11) Hardening (firewall + fail2ban)
```bash
chmod +x scripts/setup-ufw.sh
sudo ./scripts/setup-ufw.sh
```
Настройка fail2ban:
```bash
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:
```bash
chmod +x scripts/safe-apply-ssh-hardening.sh
sudo ./scripts/safe-apply-ssh-hardening.sh
```
Опциональный lockdown:
```bash
chmod +x scripts/safe-apply-ssh-lockdown.sh
sudo ./scripts/safe-apply-ssh-lockdown.sh
```