wiki: Operations + User-Guide
parent
3c92744163
commit
d3b7c0d09c
236
Operations.md
Normal file
236
Operations.md
Normal file
|
|
@ -0,0 +1,236 @@
|
|||
# Эксплуатация
|
||||
|
||||
## Управление сервисами
|
||||
|
||||
```bash
|
||||
# Портал
|
||||
systemctl restart morozovka-portal
|
||||
systemctl status morozovka-portal --no-pager
|
||||
systemctl is-active morozovka-portal
|
||||
|
||||
# Gitea
|
||||
systemctl restart gitea
|
||||
systemctl status gitea --no-pager
|
||||
|
||||
# Nginx
|
||||
systemctl reload nginx
|
||||
nginx -t
|
||||
|
||||
# PostgreSQL
|
||||
systemctl restart postgresql
|
||||
|
||||
# Google sync
|
||||
systemctl list-timers morozovka-sync.timer
|
||||
```
|
||||
|
||||
## Логи
|
||||
|
||||
```bash
|
||||
# Портал (gunicorn + access log)
|
||||
journalctl -u morozovka-portal -f --no-pager
|
||||
journalctl -u morozovka-portal -n 100
|
||||
|
||||
# Gitea
|
||||
journalctl -u gitea -f --no-pager
|
||||
|
||||
# Nginx
|
||||
tail -f /var/log/nginx/access.log
|
||||
tail -f /var/log/nginx/error.log
|
||||
|
||||
# PostgreSQL
|
||||
journalctl -u postgresql -f --no-pager
|
||||
tail -f /var/log/postgresql/postgresql-15-main.log
|
||||
|
||||
# Google sync
|
||||
journalctl -u morozovka-sync.timer -n 20
|
||||
journalctl -u morozovka-sync.service -n 50
|
||||
```
|
||||
|
||||
## Проверка здоровья
|
||||
|
||||
```bash
|
||||
# 1. Health портала
|
||||
curl -sS http://127.0.0.1:8000/healthz
|
||||
# → {"db":"ok","llm":"disabled","status":"ok"}
|
||||
|
||||
# 2. Все публичные роуты
|
||||
for p in / /schedule /feed /projects /workshops /login; do
|
||||
code=$(curl -sS -o /dev/null -w '%{http_code}' "http://127.0.0.1:8000$p")
|
||||
printf '%-15s %s\n' "$p" "$code"
|
||||
done
|
||||
|
||||
# 3. Полные смоук-тесты (94 проверки, 3 сек)
|
||||
bash /opt/morozovka-portal/tests/run_smoke.sh
|
||||
|
||||
# 4. Миграции
|
||||
cd /opt/morozovka-portal
|
||||
export PATH=./venv/bin:$PATH
|
||||
alembic current
|
||||
|
||||
# 5. Сервисы
|
||||
systemctl is-active morozovka-portal gitea nginx postgresql
|
||||
```
|
||||
|
||||
## Обновление кода
|
||||
|
||||
```bash
|
||||
cd /opt/morozovka-portal
|
||||
|
||||
# 1. Бэкап
|
||||
cp -r app /tmp/app_backup_$(date +%s)
|
||||
PGPASSWORD='rf-slf-1945' pg_dump -h 127.0.0.1 -U morozovka morozovka_portal > /tmp/db_backup_$(date +%s).sql
|
||||
|
||||
# 2. Git pull
|
||||
git fetch origin
|
||||
git log HEAD..origin/main --oneline
|
||||
git pull origin main
|
||||
|
||||
# 3. Зависимости (если requirements.txt изменился)
|
||||
./venv/bin/pip install -r requirements.txt
|
||||
|
||||
# 4. Миграции
|
||||
export PATH=./venv/bin:$PATH
|
||||
alembic upgrade head
|
||||
|
||||
# 5. Синтаксис
|
||||
python3 -c "import ast,glob; [ast.parse(open(f).read()) for f in glob.glob('app/*.py') + glob.glob('app/modules/*.py')]" && echo "OK"
|
||||
|
||||
# 6. Рестарт
|
||||
systemctl restart morozovka-portal
|
||||
sleep 3
|
||||
|
||||
# 7. Проверка
|
||||
curl -sS http://127.0.0.1:8000/healthz
|
||||
bash tests/run_smoke.sh
|
||||
```
|
||||
|
||||
**Если что-то сломалось — откат:**
|
||||
|
||||
```bash
|
||||
git reset --hard HEAD~1
|
||||
alembic downgrade -1
|
||||
systemctl restart morozovka-portal
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Портал не запускается
|
||||
|
||||
```bash
|
||||
systemctl status morozovka-portal --no-pager
|
||||
journalctl -u morozovka-portal -n 100 --no-pager
|
||||
```
|
||||
|
||||
Частые причины:
|
||||
|
||||
- `.env` не читается → проверь `EnvironmentFile=-/opt/morozovka-portal/.env` в systemd
|
||||
- Синтаксическая ошибка в Python → `python3 -c "import ast,glob; [ast.parse(open(f).read()) for f in glob.glob('app/*.py')]"`
|
||||
- Миграции не применены → `alembic current` и `alembic upgrade head`
|
||||
- Порт 8000 занят → `ss -tlnp | grep 8000`
|
||||
|
||||
### /healthz → 503 (db:error)
|
||||
|
||||
- PostgreSQL не запущен → `systemctl restart postgresql`
|
||||
- Неверный `DATABASE_URL` → проверь `.env`, `app/config.py`
|
||||
- Пароль изменился → `ALTER USER morozovka WITH PASSWORD 'новый';` и `.env`
|
||||
|
||||
### Файлы не скачиваются
|
||||
|
||||
- Блоб отсутствует на диске → `ls -la /var/lib/gitea/portal-files/ | wc -l`
|
||||
- `current_version_id` указывает на несуществующую версию → проверь в psql
|
||||
- Права на папку → проверь `FileFolderACL`
|
||||
|
||||
### Webhook 401
|
||||
|
||||
- `GITEA_WEBHOOK_SECRET` не совпадает с настройкой в Gitea → проверь оба
|
||||
|
||||
### Webhook 200, но нет уведомлений
|
||||
|
||||
- У проекта нет `gitea_repo` → проверь в `/projects/<id>`
|
||||
- У проекта нет подписчиков → проверь `projectsubscription`
|
||||
- Push в ветку, которая не отслеживается → проверь `payload.ref`
|
||||
|
||||
### Gitea sync не работает
|
||||
|
||||
- `GOOGLE_CALENDAR_ID` неправильный → проверь в `.env`
|
||||
- `google_credentials.json` отсутствует → положи в `/opt/morozovka-portal/`
|
||||
- Календарь не расшарен на service account → Google Calendar → настройки → доступ
|
||||
- Timer не запущен → `systemctl status morozovka-sync.timer`
|
||||
|
||||
### Email не приходит
|
||||
|
||||
- SMTP не настроен → письма идут в `journalctl`
|
||||
- Проверка: `journalctl -u morozovka-portal | grep "EMAIL ДЛЯ"`
|
||||
|
||||
### LLM не работает
|
||||
|
||||
- `LLM_ENABLED=false` в `.env` (по умолчанию)
|
||||
- Модель не загружена → `ollama list` (должна быть `qwen2.5:14b`)
|
||||
- Ollama не запущена → `systemctl status ollama`
|
||||
- Проверка: `curl -sS http://localhost:11434/v1/models`
|
||||
|
||||
## Обслуживание
|
||||
|
||||
### Очистка старых сессий
|
||||
|
||||
```bash
|
||||
PGPASSWORD='rf-slf-1945' psql -h 127.0.0.1 -U morozovka -d morozovka_portal -c "
|
||||
DELETE FROM usersession WHERE created_at < NOW() - INTERVAL '30 days';
|
||||
"
|
||||
```
|
||||
|
||||
### Очистка старых уведомлений
|
||||
|
||||
```bash
|
||||
PGPASSWORD='rf-slf-1945' psql -h 127.0.0.1 -U morozovka -d morozovka_portal -c "
|
||||
DELETE FROM notification WHERE is_read = true AND created_at < NOW() - INTERVAL '90 days';
|
||||
"
|
||||
```
|
||||
|
||||
### Проверка размера портала
|
||||
|
||||
```bash
|
||||
# БД
|
||||
PGPASSWORD='rf-slf-1945' psql -h 127.0.0.1 -U morozovka -d morozovka_portal -c "
|
||||
SELECT pg_size_pretty(pg_database_size('morozovka_portal'));
|
||||
"
|
||||
|
||||
# Файлы
|
||||
du -sh /var/lib/gitea/portal-files/
|
||||
|
||||
# Топ-10 таблиц по размеру
|
||||
PGPASSWORD='rf-slf-1945' psql -h 127.0.0.1 -U morozovka -d morozovka_portal -c "
|
||||
SELECT relname, pg_size_pretty(pg_total_relation_size(relid))
|
||||
FROM pg_stat_user_tables
|
||||
ORDER BY pg_total_relation_size(relid) DESC LIMIT 10;
|
||||
"
|
||||
```
|
||||
|
||||
## Cron / systemd timers
|
||||
|
||||
| Timer | Что | Когда |
|
||||
|---|---|---|
|
||||
| `morozovka-sync.timer` | Google Calendar → Event | Каждые 15 мин |
|
||||
| (TODO) `morozovka-backup.timer` | pg_dump + rsync | 3:00 |
|
||||
|
||||
## Emergency recovery
|
||||
|
||||
### Портал полностью лёг
|
||||
|
||||
1. Проверь `systemctl status morozovka-portal postgresql nginx`
|
||||
2. Если БД умерла → `systemctl restart postgresql`
|
||||
3. Если портал падает в цикле → `journalctl -u morozovka-portal -n 100`
|
||||
4. Синтаксис → `python3 -c "import ast,glob; [ast.parse(open(f).read()) for f in glob.glob('app/*.py') + glob.glob('app/modules/*.py')]"`
|
||||
5. Если миграция сломала → `alembic downgrade -1`
|
||||
6. Worst case — восстановление из бэкапа (см. Database)
|
||||
|
||||
### Вебхук Gitea сломался
|
||||
|
||||
```bash
|
||||
curl -X POST http://127.0.0.1:8000/webhooks/gitea \
|
||||
-H "X-Gitea-Signature: DEADBEEF" -d '{}'
|
||||
```
|
||||
|
||||
- `401` = защита работает, ок
|
||||
- `200` = подпись не проверяется → `GITEA_WEBHOOK_SECRET` пустой
|
||||
- `000` = портал не отвечает → см. выше
|
||||
128
User-Guide.md
Normal file
128
User-Guide.md
Normal file
|
|
@ -0,0 +1,128 @@
|
|||
# Гайд для пользователей
|
||||
|
||||
## Регистрация
|
||||
|
||||
1. Открой `https://portal.morozovka.space`
|
||||
2. Кнопка «Регистрация» в правом верхнем углу
|
||||
3. Заполни: ФИО, организация (ННГУ / Неймарк / Ядро / внешний), логин, email, пароль (мин 6 символов)
|
||||
4. После регистрации — можно войти
|
||||
|
||||
**Альтернатива:** войти через Gitea — кнопка «Войти через Gitea» на странице `/login`.
|
||||
|
||||
## Онбординг
|
||||
|
||||
При первой регистрации:
|
||||
|
||||
- В колокольчике уведомлений — «👋 Добро пожаловать!»
|
||||
- Клик → страница `/onboarding` с туром по 6 разделам
|
||||
- Отмечаешь, что освоил → прогресс-бар растёт
|
||||
- «Отметить всё сразу» — если уже разобрался
|
||||
|
||||
**Повторно пройти** — ссылка «🎯 Тур» в футере или в `/profile`.
|
||||
|
||||
## Разделы
|
||||
|
||||
### 📅 Расписание (`/schedule`)
|
||||
|
||||
Публичная страница — видна без логина.
|
||||
|
||||
- **Статус-баннер сверху**: зелёный = на месте, жёлтый = опаздываю, красный = отменено/перенесено, серый = вне расписания
|
||||
- **Календарь**: переключение День/Неделя/Месяц
|
||||
- **Фильтры**: лекции / мастер-классы / встречи / личное
|
||||
- **Клик по событию** — попап с деталями (место, аудитория, причина переноса)
|
||||
- **Чат-ассистент** (кнопка 💬 справа снизу) — спроси «Где сейчас?», «Когда следующая пара?», «Что сегодня?», «Что на неделе?», «Как связаться?»
|
||||
- **Подписка на уведомления** — блок под календарём (нужен логин)
|
||||
|
||||
### 🗂 Проекты (`/projects`)
|
||||
|
||||
- **Каталог** с фильтрами: по статусу (идея/в работе/завершён/заморожен), по тегам
|
||||
- **Карточка проекта** — описание, участники с ролями, файлы, лента новостей, ссылка на Gitea
|
||||
- **Канбан-доска** (`/projects/<id>/board`) — задачи со статусами backlog → todo → in_progress → review → done
|
||||
- **Drag&drop** — перетаскивай задачи между колонками
|
||||
- **Подписка** — получать уведомления о новых постах
|
||||
|
||||
**Создание** — только admin/professor/lead. Кнопка «+ Добавить проект».
|
||||
|
||||
### 🎓 Мастер-классы (`/workshops`)
|
||||
|
||||
- **Каталог** с фильтрами: по категории (пайка, embedded, Linux, творчество), по статусу
|
||||
- **Карточка МК** — программа, ведущий, помощники, сессии, материалы, лента, участники
|
||||
- **Записаться** — кнопка на странице МК (только для published)
|
||||
- **Материалы** — доступны после записи (зависит от `visible_to`)
|
||||
- **Подписка** — на новости
|
||||
|
||||
**Создание** — только admin. Кнопка «+ Создать мастер-класс».
|
||||
|
||||
### 📁 Файлы (`/files`)
|
||||
|
||||
- **Пространства** — верхний уровень (по проекту, направлению, тематике)
|
||||
- **Папки** внутри пространства (можно вкладывать)
|
||||
- **Файлы** с версиями (v1, v2, ...) и историей
|
||||
- **Drag&drop** загрузка — перетащи файлы в зону или кликни
|
||||
- **Мультизагрузка** — до 100 МБ суммарно за раз
|
||||
- **Права** — на уровне пространства (viewer/editor/manager) и папки (4 флага)
|
||||
- **Поиск** — по имени, описанию, тегам
|
||||
- **Перемещение** — файл между пространствами через ↔
|
||||
- **Версии** — загрузить новую версию, откатить к старой
|
||||
|
||||
### 📰 Лента (`/feed`)
|
||||
|
||||
- Все посты из проектов и МК в одном потоке
|
||||
- Фильтры: источник (все/МК/проекты), поиск
|
||||
- Закреплённые посты — сверху
|
||||
|
||||
### 🏠 Дашборд (`/dashboard`)
|
||||
|
||||
Персональный экран после входа:
|
||||
|
||||
- Ближайшие события
|
||||
- Мои проекты и задачи
|
||||
- Непрочитанные уведомления
|
||||
- Новые материалы МК (где записан)
|
||||
- Последние коммиты в Gitea (если есть)
|
||||
- Быстрые ссылки
|
||||
|
||||
### 👤 Профиль (`/profile`)
|
||||
|
||||
- Личные данные
|
||||
- Подписки на email-уведомления
|
||||
- Активные сессии (можно выйти со всех устройств)
|
||||
- Тур по платформе
|
||||
|
||||
## Уведомления
|
||||
|
||||
- **Колокольчик** в правом верхнем углу — счётчик непрочитанных
|
||||
- **`/notifications`** — все уведомления
|
||||
- **Триггеры**: новая запись на МК, материал, пост, задача, push в Gitea
|
||||
- **Email-подписка** — через `/profile` (пока письма в `journalctl`, SMTP не настроен)
|
||||
|
||||
## Роли
|
||||
|
||||
| Роль | Что может |
|
||||
|---|---|
|
||||
| admin | Всё + `/admin/*` |
|
||||
| professor | Управление расписанием |
|
||||
| lead | Создавать проекты, пространства файлов |
|
||||
| member | Участвовать в проектах, записываться на МК |
|
||||
| student | Запись на МК, просмотр |
|
||||
| guest | Только публичное |
|
||||
|
||||
## FAQ
|
||||
|
||||
**Q: Забыл пароль.**
|
||||
A: `/forgot_password` → введи email → ссылка в `journalctl` (пока SMTP не настроен).
|
||||
|
||||
**Q: Не вижу проект.**
|
||||
A: Возможно, он «внутренний» или «приватный». Спроси владельца добавить тебя.
|
||||
|
||||
**Q: Не могу загрузить файл.**
|
||||
A: Проверь права на пространство/папку. Если не участник — попроси editor/manager.
|
||||
|
||||
**Q: Файл больше 100 МБ.**
|
||||
A: Не пройдёт. Загрузи частями (архивы) или через Gitea LFS.
|
||||
|
||||
**Q: Как скачать старую версию файла?**
|
||||
A: `/files/<id>/history` → «Скачать» напротив нужной версии.
|
||||
|
||||
**Q: Как связаться с админом?**
|
||||
A: Напиши в Telegram / лично. В платформе пока нет чата с админом.
|
||||
Loading…
Reference in New Issue
Block a user