1 Install
Morozovka Admin edited this page 2026-10-21 07:06:53 +03:00
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.

Установка с нуля

Пошаговая инструкция для развёртывания на чистом Debian 12. Ориентирована на существующую инфраструктуру morozovka-bridge.

Требования

Компонент Версия Зачем
Debian 12 (bookworm) ОС
Python 3.11+ Backend
PostgreSQL 15+ БД портала
Gitea 1.22 Git + SSO + webhooks
Nginx 1.22+ Reverse proxy
OpenVPN + socat — Связность с внешним сервером

Железо: сервер morozovka (192.168.50.3), ≥4 ГБ RAM, ≥20 ГБ свободно на /opt.

1. Системные пакеты

apt update
apt install -y python3.11 python3.11-venv python3-pip \
    postgresql-15 postgresql-contrib \
    nginx git curl openssl

2. PostgreSQL

sudo -u postgres psql <<SQL
CREATE USER morozovka WITH PASSWORD 'rf-slf-1945';
CREATE DATABASE morozovka_portal OWNER morozovka;
GRANT ALL PRIVILEGES ON DATABASE morozovka_portal TO morozovka;
SQL

PGPASSWORD='rf-slf-1945' psql -h 127.0.0.1 -U morozovka -d morozovka_portal -c 'SELECT 1;'

Пароль в .env, не в коде.

3. Gitea

Если Gitea уже установлена — пропусти. Если нет:

wget -O /usr/local/bin/gitea \
    https://dl.gitea.com/gitea/1.22.0/gitea-1.22.0-linux-amd64
chmod +x /usr/local/bin/gitea

useradd -r -m -d /home/git -s /bin/bash git
mkdir -p /var/lib/gitea/{custom,data,log}
chown -R git:git /var/lib/gitea
mkdir -p /etc/gitea
chown root:git /etc/gitea
chmod 770 /etc/gitea

sudo -u git /usr/local/bin/gitea web --config /etc/gitea/app.ini

Далее через веб-интерфейс http://127.0.0.1:3000 — установка.

OAuth2-приложение для портала (Gitea → Settings → Applications → OAuth2):

  • Name: Morozovka Portal
  • Redirect URI: https://portal.morozovka.space/auth/callback
  • Сохрани Client ID и Client Secret

Webhook (Settings → Webhooks → Add webhook → Gitea):

  • URL: http://127.0.0.1:8000/webhooks/gitea (напрямую в gunicorn, без nginx)
  • Secret: openssl rand -hex 32
  • Trigger: Push events

4. Портал

cd /opt
git clone http://192.168.50.3:3000/git_admin/morozovka-portal.git
cd morozovka-portal

python3 -m venv venv
./venv/bin/pip install -r requirements.txt

5. .env

cp .env.example .env
chmod 600 .env
nano .env

Обязательные поля:

GITEA_WEBHOOK_SECRET=<тот же secret, что в webhook Gitea>
GITEA_CLIENT_ID=<из OAuth2-приложения>
GITEA_CLIENT_SECRET=<из OAuth2-приложения>

Опционально:

GITEA_API_TOKEN=        # для API приватных репо
GOOGLE_CALENDAR_ID=     # для Google sync

6. Миграции

cd /opt/morozovka-portal
export PATH=/opt/morozovka-portal/venv/bin:$PATH
alembic upgrade head
alembic current

Если база уже была создана до Alembic:

alembic stamp head

7. systemd — портал

cat > /etc/systemd/system/morozovka-portal.service <<'UNIT'
[Unit]
Description=Morozovka Portal (Flask)
After=network.target postgresql.service

[Service]
User=root
WorkingDirectory=/opt/morozovka-portal
Environment="PATH=/opt/morozovka-portal/venv/bin"
EnvironmentFile=-/opt/morozovka-portal/.env
ExecStart=/opt/morozovka-portal/venv/bin/gunicorn \
    --workers 2 --bind 127.0.0.1:8000 \
    --timeout 300 --graceful-timeout 30 \
    --access-logfile - --error-logfile - \
    app.main:app
Restart=always
RestartSec=5

[Install]
WantedBy=multi-user.target
UNIT

systemctl daemon-reload
systemctl enable --now morozovka-portal
systemctl status morozovka-portal --no-pager

8. systemd — Google sync (опционально)

cat > /etc/systemd/system/morozovka-sync.service <<'UNIT'
[Unit]
Description=Google Calendar Sync for Morozovka Portal
After=network.target postgresql.service

[Service]
Type=oneshot
User=root
WorkingDirectory=/opt/morozovka-portal
Environment="PATH=/opt/morozovka-portal/venv/bin"
ExecStart=/opt/morozovka-portal/venv/bin/python -c "from app.google_sync import sync_google_calendar; sync_google_calendar()"
UNIT

cat > /etc/systemd/system/morozovka-sync.timer <<'UNIT'
[Unit]
Description=Run Google Calendar Sync every 15 minutes

[Timer]
OnCalendar=*:0/15
Persistent=true

[Install]
WantedBy=timers.target
UNIT

systemctl daemon-reload
systemctl enable --now morozovka-sync.timer

9. Nginx (внутренний)

cat > /etc/nginx/sites-available/portal.morozovka.space <<'NGX'
server {
    listen 80;
    server_name portal.morozovka.space;
    client_max_body_size 100M;
    client_body_timeout 600s;
    proxy_send_timeout 600s;
    proxy_read_timeout 600s;

    location / {
        proxy_pass http://127.0.0.1:8000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_http_version 1.1;
        proxy_set_header Connection "";
    }
}
NGX

ln -s /etc/nginx/sites-available/portal.morozovka.space /etc/nginx/sites-enabled/
nginx -t && systemctl reload nginx

10. Проверка

curl -sS http://127.0.0.1:8000/healthz
# {"db":"ok","llm":"disabled","status":"ok"}

bash /opt/morozovka-portal/tests/run_smoke.sh
# PASS: 94, FAIL: 0

11. Чек-лист после установки

  • /healthz → 200
  • /schedule открывается без логина
  • Регистрация работает
  • Gitea OAuth работает (/login/gitea)
  • Webhook Gitea: git push → в логах POST /webhooks/gitea 200
  • Google sync: journalctl -u morozovka-sync.timer -n 5
  • Тесты PASS: 94, FAIL: 0
  • .env с chmod 600
  • Портал не доступен снаружи напрямую (только через внешний nginx)