Configure admin title and deploy docs

This commit is contained in:
Your Name
2026-07-28 12:37:04 +05:00
parent bb2c58e02f
commit 3ab8a7b4f2
7 changed files with 68 additions and 88 deletions
+1
View File
@@ -1,5 +1,6 @@
APP_ENV=production
APP_SECRET_KEY=change-me
ADMIN_APP_TITLE=Редакторская
ADMIN_BOOTSTRAP_LOGIN=admin
ADMIN_BOOTSTRAP_PASSWORD=change-me-long-password
+40 -57
View File
@@ -31,9 +31,11 @@
- Telegram: `aiogram`.
- AI: `litellm`, сейчас используется Anthropic через LiteLLM.
- Логи: `loguru`.
- Системный запуск на сервере: `systemd`.
- Reverse proxy / TLS: nginx + сертификат для `https://sw.exostring.xyz`.
- Репозиторий: GitHub `exostring/n8_parser`.
- Runtime/deploy: локальная инфраструктура Proxmox + Coolify + Docker.
- Reverse proxy / TLS: edge-proxy Caddy из локальной инфраструктуры.
- Публичная админка: `https://panel.f-n8.ru` (`https://admin.f-n8.ru` после обновления DNS).
- Deploy-репозиторий: Gitea `http://192.168.1.135:3000/exostring/new_vk_parser.git`, remote `gitea`.
- GitHub `origin` используется как upstream/backup, не как основной deploy remote.
## 3. Структура проекта
@@ -74,6 +76,8 @@
Если меняется поведение системы, эксплуатационная схема, публикационный формат, БД, деплой или админка, это нужно отражать в `PROJECT.md` или другом релевантном `.md` рядом с кодом.
Инфраструктурная карта вне репозитория: `D:\DEVELOPMENT\.infra.md`. Перед любыми deploy/server действиями сначала читать её. Для этого проекта актуален контур Gitea -> Coolify -> LXC 105; старые инструкции про `sw.exostring.xyz`, `109.120.156.205`, `/opt/vk-parser` и ручной `systemctl` не использовать без явной команды пользователя.
Текущие зафиксированные изменения:
- Публичный сайт вынесен в самостоятельное приложение `forma_n8_site/` и разворачивается на отдельном VPS. Сайт хранит собственные статьи и медиа, отдаёт серверный HTML, RSS, sitemap, robots.txt, canonical и JSON-LD `NewsArticle`.
@@ -1230,47 +1234,42 @@ $env:PYTHONPYCACHEPREFIX="$env:TEMP\n8_pycache"
python -m py_compile src\vk_parser_app\admin.py
```
## 16. Сервер
## 16. Runtime / Deploy
Рабочий путь:
Актуальный runtime живёт в локальной инфраструктуре. Источник правды по хостам,
ключам, Coolify, Gitea и edge-proxy: `D:\DEVELOPMENT\.infra.md`.
```bash
/opt/vk-parser
Текущая схема:
```text
local repo
-> git push gitea main
-> Gitea webhook on 192.168.1.135
-> Coolify on 192.168.1.135
-> Docker app on LXC 105 / 192.168.1.105
-> edge-proxy / Caddy
-> https://panel.f-n8.ru
```
Основные команды:
Важно:
```bash
cd /opt/vk-parser
git pull --ff-only
PYTHONPATH=src .venv/bin/python scripts/apply_migrations.py
systemctl restart vk-parser-admin.service
```
- Не использовать для этого проекта старый VPS `109.120.156.205`.
- Не использовать `https://sw.exostring.xyz` как проверку текущей админки.
- Не выполнять `/opt/vk-parser`, `git pull` на VPS и `systemctl restart ...`
без явного указания пользователя, что речь именно о старом VPS.
- Основной deploy remote: `gitea`.
- URL репозитория в Coolify должен резолвиться из build/helper container на
deploy-сервере. Не использовать `http://coolify.lan:3000/...`, если это имя
не настроено внутри LXC/Docker; рабочий локальный URL Gitea:
`http://192.168.1.135:3000/exostring/new_vk_parser.git`.
- Coolify должен собирать и деплоить приложение после push/webhook; при ручном
деплое использовать Coolify API/UI из `D:\DEVELOPMENT\.infra.md`.
Проверка сервисов:
Публичная админка:
```bash
systemctl is-active vk-parser-admin.service
systemctl is-active vk-parser.service
systemctl is-active vk-storage-uploader.service
systemctl is-active ai-qualifier.service
systemctl is-active ai-writer.service
systemctl is-active tg-poster.service
systemctl is-active max-poster.service
systemctl is-active telegram-bot-api.service
```
Логи:
```bash
journalctl -u vk-parser-admin.service -n 100 --no-pager
journalctl -u vk-parser.service -n 100 --no-pager
journalctl -u vk-storage-uploader.service -n 100 --no-pager
journalctl -u ai-qualifier.service -n 100 --no-pager
journalctl -u ai-writer.service -n 100 --no-pager
journalctl -u tg-poster.service -n 100 --no-pager
journalctl -u max-poster.service -n 100 --no-pager
journalctl -u telegram-bot-api.service -n 100 --no-pager
```text
https://panel.f-n8.ru
https://admin.f-n8.ru
```
## 17. Git workflow
@@ -1281,28 +1280,12 @@ journalctl -u telegram-bot-api.service -n 100 --no-pager
git status
git add ...
git commit -m "Message"
git push
git pull --rebase gitea main
git push gitea main
```
На сервере origin настроен через deploy key.
Обычный деплой:
```bash
cd /opt/vk-parser
git pull --ff-only
PYTHONPATH=src .venv/bin/python scripts/apply_migrations.py
systemctl restart vk-parser-admin.service
```
Если менялся конкретный worker, перезапустить его:
```bash
systemctl restart ai-writer.service
systemctl restart ai-qualifier.service
systemctl restart vk-parser.service
systemctl restart vk-storage-uploader.service
```
`origin` остаётся GitHub/upstream/backup. Для deploy использовать `gitea`,
потому что Gitea webhook запускает Coolify.
## 18. Контролируемый тест AI-райтера
+16 -22
View File
@@ -1,28 +1,22 @@
# N8 Parser: current state
Last updated: 2026-06-17
Last updated: 2026-07-28
This file is the short handoff state for future Codex threads. Read this first before touching the project, so the whole chat history does not need to be carried forward.
## Server
## Runtime / Deploy
- Production host: `109.120.156.205`
- Domain: `https://sw.exostring.xyz`
- App directory on server: `/opt/vk-parser`
- Timezone: `Asia/Yekaterinburg`
- Main services:
- `vk-parser-admin.service`
- `vk-parser.service`
- `vk-storage-uploader.service`
- `ai-qualifier.service`
- `ai-writer.service`
- `site-poster.service`
- Useful commands:
- `cd /opt/vk-parser`
- `systemctl status vk-parser-admin.service ai-qualifier.service ai-writer.service`
- `journalctl -u ai-writer.service -n 100 --no-pager`
- `journalctl -u ai-qualifier.service -n 100 --no-pager`
- `PYTHONPATH=src .venv/bin/python -m py_compile src/vk_parser_app/admin.py src/vk_parser_app/workers/ai_writer.py`
Current runtime is local infrastructure, not the old VPS.
- Infrastructure source of truth: `D:\DEVELOPMENT\.infra.md`.
- Git deploy remote: `gitea` -> `http://192.168.1.135:3000/exostring/new_vk_parser.git`.
- Deploy path: push to `gitea/main` -> Gitea webhook -> Coolify -> Docker build/deploy.
- Coolify + Gitea LXC: `192.168.1.135` (CTID 102).
- Application LXC: `192.168.1.105` (CTID 105, `new-vk-parser`).
- Public admin URL: `https://panel.f-n8.ru` (also `https://admin.f-n8.ru` when DNS is current).
- Coolify repository URL must be reachable from the deployment container; use `http://192.168.1.135:3000/exostring/new_vk_parser.git` or another resolvable Gitea URL, not `http://coolify.lan:3000/...`.
- Do not deploy this project through `sw.exostring.xyz`, `109.120.156.205`, `/opt/vk-parser`, or manual `systemctl` unless the user explicitly says the old VPS is being restored.
- Old `sw.exostring.xyz` / `109.120.156.205` notes are stale for this project.
## Local Project
@@ -102,9 +96,9 @@ On 2026-06-17 the hashtag flow was fixed:
## Working Rules For Future Codex Runs
- Before any deploy/server operation, read `D:\DEVELOPMENT\.infra.md` first.
- For this project, push deployable changes to `gitea/main`; Coolify handles deployment.
- Prefer small targeted file reads with `rg` and narrow ranges.
- Avoid dumping long post texts from DB unless explicitly needed.
- For server checks, return counts/statuses first.
- Be careful: both local and server worktrees may be dirty.
- For runtime checks, use the current Coolify/Gitea/LXC 105 path from `D:\DEVELOPMENT\.infra.md`.
- Do not `git reset --hard` or revert user/server hotfixes.
- When fixing production, patch server and then mirror the same change locally.
+2 -2
View File
@@ -45,7 +45,7 @@ BASE_DIR = Path(__file__).resolve().parent
PROJECT_ROOT = BASE_DIR.parents[1]
FAVICON_PATH = PROJECT_ROOT / "favi.png"
templates = Jinja2Templates(directory=str(BASE_DIR / "templates"))
app = FastAPI(title="VK Parser Admin")
app = FastAPI(title=settings.display_admin_title)
LOCAL_TZ = ZoneInfo("Asia/Yekaterinburg")
MODEL_CACHE: dict[str, Any] = {"key": "", "at": 0.0, "models": []}
UPLOAD_ROOT = Path("uploads").resolve()
@@ -444,7 +444,7 @@ def require_csrf(user: dict, csrf_token: str) -> None:
def base_context(request: Request, user: dict | None, **extra: Any) -> dict[str, Any]:
ctx = {"request": request, "user": user, "app_env": settings.app_env}
ctx = {"request": request, "user": user, "app_env": settings.app_env, "app_title": settings.display_admin_title}
ctx.update(extra)
return ctx
+5
View File
@@ -6,6 +6,7 @@ from pydantic_settings import BaseSettings, SettingsConfigDict
class Settings(BaseSettings):
app_env: str = "production"
app_secret_key: str = "change-me"
admin_app_title: str = "Редакторская"
admin_bootstrap_login: str = "admin"
admin_bootstrap_password: str = ""
@@ -37,6 +38,10 @@ class Settings(BaseSettings):
f"@{self.db_host}:{self.db_port}/{self.db_name}"
)
@property
def display_admin_title(self) -> str:
return self.admin_app_title.strip() or "Редакторская"
@property
def vk_storage_owner_id(self) -> int:
return -abs(int(self.vk_storage_group_id))
+3 -5
View File
@@ -4,7 +4,7 @@
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/png" href="/favi.png">
<title>{{ title or "VK Parser Admin" }}</title>
<title>{{ title or app_title or "Редакторская" }}</title>
<!-- Fonts: Fira Sans (UI) & Fira Code (Data) -->
<link rel="preconnect" href="https://fonts.googleapis.com">
@@ -162,8 +162,7 @@
<div class="p-4">
<div class="flex items-center gap-3 text-app-textMain font-bold text-lg tracking-wide" :class="expanded ? 'justify-between' : 'justify-center'">
<div class="flex items-center gap-3 min-w-0">
<i data-lucide="zap" class="w-6 h-6 text-app-primary flex-shrink-0"></i>
<span x-show="expanded" x-cloak class="truncate">Parser Admin</span>
<span x-show="expanded" x-cloak class="truncate">{{ app_title or "Редакторская" }}</span>
</div>
<button type="button" class="btn btn-ghost btn-icon flex-shrink-0" @click="expanded = !expanded" :aria-label="expanded ? 'Свернуть меню' : 'Развернуть меню'" :title="expanded ? 'Свернуть меню' : 'Развернуть меню'">
<i data-lucide="panel-left" class="w-5 h-5"></i>
@@ -223,8 +222,7 @@
<!-- Mobile Topbar (Visible only on small screens) -->
<div class="md:hidden fixed top-0 left-0 right-0 h-16 bg-app-surface border-b border-app-border z-50 flex items-center justify-between px-4">
<div class="flex items-center gap-2 font-bold text-app-textMain">
<i data-lucide="zap" class="w-5 h-5 text-app-primary"></i>
Parser
{{ app_title or "Редакторская" }}
</div>
<button class="btn btn-ghost btn-icon" onclick="document.getElementById('mobile-menu').classList.toggle('hidden')">
<i data-lucide="menu" class="w-6 h-6"></i>
+1 -2
View File
@@ -205,8 +205,7 @@
<div>
<button class="btn btn-ghost btn-sm text-app-error hover:bg-app-errorBg hover:text-app-error" type="button"
hx-post="/editor/{{ p.id }}/reject" hx-target="#post-container-{{ p.id }}" hx-swap="outerHTML"
hx-vals='{"csrf_token": "{{ user.csrf_token }}"}'
onclick="return confirm('Отклонить пост?')">
hx-vals='{"csrf_token": "{{ user.csrf_token }}"}'>
<i data-lucide="x" class="w-4 h-4"></i> Отклонить
</button>
</div>