Документация
PRODUCTION.md — чек-лист до продакшена
Живой документ. Статусы: - ✅ — сделано - 🚧 — в работе / частично - 🔜 — ждёт внешнего (оборудование, регистрация, решение) - ❌ — не сделано
1. Оборудование и размещение
1.1. Выбранная схема — B: VPS + ноут с белым IP ✅
VPS — «витрина»:
- Django + gunicorn + nginx + PostgreSQL.
- Статика + превью 600px + постеры видео + 10-сек mp4.
- Оплата (LiqPay / Fondy).
- Telegram-бот — один.
- Модель DownloadToken.
- SSL Let's Encrypt.
- Домен znymkari.com → A → 128.140.81.213.
Ноут Олега — «склад + цех» (белый IP):
- Оригиналы: единое хранилище на HDD. SSD — под ОС, БД, venv, превью.
- Пользователи: olegarh (uid 1000), deploy (uid 1001, sudo NOPASSWD).
- Hostname oleg-home, ядро 7.0.0-38.
- Сеть: Wi-Fi wlp8s0, LAN 192.168.31.87 (резерв DHCP).
- Внешний SSH: 193.176.249.24:22022 → 192.168.31.87:22.
- Стек: Python 3.14, PostgreSQL 18, nginx 1.28, ffmpeg 8.0.1.
- STORAGE: /mnt/hdd/znymkari-storage (рабочая копия).
- FESTIVALS: /mnt/hdd/zny-festivals (оригиналы, источник импорта).
- HEAP: /mnt/hdd/zny-heap (свалка).
- Samba: юзер olegarh, порт 445, LAN 192.168.31.0/24.
- Шары: zny-festivals, zny-heap.
- Локальный Django + PostgreSQL (znymkari_local, uk_UA.UTF-8).
- Два проекта: web/ и znymkari-data/.
- systemd: gunicorn-oleg.service, 0.0.0.0:8000.
- nginx на :443 — отдача файлов по одноразовой ссылке (план).
- Домен files.znymkari.com → A → 193.176.249.24 (план).
- Ноут = мини-UPS (2–4 ч).
Что VPS НЕ делает: - ❌ Не хранит оригиналы. - ❌ Не проксирует скачивание. - ❌ Не запускает импорт.
1.2. Оборудование для дома
- ✅ Белый статический IP:
193.176.249.24(GPON-1Gbit-PPP, 200 ₴/мес). - ✅ Ноут Олега — уже есть.
- ✅ Ноут = мини-UPS.
- ✅ Ubuntu Server 24.04.
- ✅ Пользователи
olegarh/deploy. - ✅ HDD WD My Passport 2 ТБ (NTFS,
/mnt/hdd, SMART здоровый). - ✅ Стек: Python 3.14, PostgreSQL 18, nginx 1.28, ffmpeg 8.0.1.
- ✅ Samba с шарами
zny-festivals,zny-heap. - ✅ WinSCP у Олега.
- 🔜 Второй HDD под бэкап БД.
- 🔜 Внешний HDD 16 ТБ (когда кончится место).
1.3. VPS — ✅ создан
- ✅ Hetzner (Германия, Falkenstein).
- ✅ CPX22 — 2 vCPU / 4 ГБ RAM / 80 ГБ SSD.
- ✅ Ubuntu 24.04.5 LTS.
- ✅ Трафик 20 ТБ/мес.
- ✅ IP
128.140.81.213. - ✅ SSH-ключ
znymkari-my. - ✅ Backups включены (+€3.9/мес).
- ✅ Owner: Олег (
zhurbenko1985@gmail.com). - ✅ Команда: я — Member.
1.4. Сеть между VPS и ноутом
- 🔜 WireGuard — постоянный туннель.
- 🔜 Установлен на VPS и на ноуте.
- 🔜 Ключи, конфиги.
- 🔜
PersistentKeepalive = 25со стороны дома. - 🔜 Внутренние IP: VPS
10.0.0.1, дом10.0.0.2. - 🔜 Проверка:
ping 10.0.0.2с VPS и наоборот. - ✅ Решение: WireGuard (не Tailscale).
- 🔜 Мониторинг туннеля.
- ✅ SSH ноута снаружи — через проброс
22022 → 192.168.31.87:22.
2. Домен и DNS
- ✅ Куплен
znymkari.comв Hetzner (аккаунт Олегаkonsolch, €13.50/год). - ✅ DNS:
- ✅
A @→128.140.81.213. - ✅
A www→128.140.81.213. - 🔜
files.znymkari.com→ A →193.176.249.24. - ✅ DNS у Hetzner (без Cloudflare).
- ✅ SSL VPS —
certbot --nginx -d znymkari.com -d www.znymkari.com(до 2027-01-09). - 🔜 SSL дома:
certbot --nginx -d files.znymkari.com. - ✅
ALLOWED_HOSTS:znymkari.com,www.znymkari.com,128.140.81.213. - ✅
CSRF_TRUSTED_ORIGINS:https://znymkari.com,https://www.znymkari.com. - ✅
DEBUG = False.
3. Регистрации и аккаунты
3.1. Обязательные
- ✅ Домен — Hetzner.
- ✅ VPS — Hetzner.
- ✅ Telegram-бот —
@Znymkari_dev_bot(id8807489402). - ✅ Токен →
settings_local.py. - ✅ Webhook настроен (
set_telegram_webhook). - ✅ Long polling выключен.
- ❌ Финальная ротация токена (
/revoke) перед публичным запуском. - ❌ Описание / аватар / команды в
BotFather. - 🔜 Переименовать в прод-бота.
- ❌ Платёжный провайдер.
- ❌ Email-провайдер (SMTP).
- ❌ SMS-провайдер.
3.2. Опциональные
- ❌ Sentry.
- ❌ Uptime-мониторинг.
- ❌ Аналитика.
- ❌ Облако под бэкапы.
4. Оплата
4.1. Провайдер
- ❌ Выбрать: LiqPay / Monobank / Fondy / WayForPay / Stripe / PayPal.
- ❌ Зарегистрировать мерчант-аккаунт.
- ❌ Пройти верификацию (ФОП / ТОВ / физлицо).
- ❌ API-ключи:
public_key,private_key,merchant_id. - ❌ Прописать в
settings_local.py. - ❌ Настроить вебхук (callback URL).
4.2. Логика (Этап 3)
- ❌ Модель
Order+OrderItem. - ❌ Страница
/checkout/или модалка. - ❌ Интеграция: создание платежа, редирект, callback.
- ❌ Статусы:
new→pending→paid/cancelled/refunded. - ❌ Модель
DownloadToken. - ❌ При
paid: - ❌ Генерация
DownloadToken. - ❌
Media.is_purchased = True+ FK на покупателя. - ❌ Бот шлёт
https://files.znymkari.com/d/<token>. - ❌ Email-дубль (если нет Telegram).
- ❌ История заказов в кабинете (
/accounts/orders/). - ❌ Возвраты.
4.3. Тест
- ❌ Прогнать sandbox-платёж.
- ❌ Проверить заказ → оплата → ссылка → скачивание.
- ❌ Проверить отмену / возврат.
5. Уведомления
5.1. Email
- ❌ Провайдер: SendGrid / Mailgun / Postmark / SES / Yandex.
- ❌ SMTP / API-ключ.
- ❌
MAILERS— не console. - ❌ SPF / DKIM / DMARC.
- ❌ Отправитель
noreply@znymkari.com. - ❌ Шаблоны:
- ✅ Активация.
- ❌ Восстановление пароля.
- ❌ Подтверждение оплаты.
- ❌ Ссылка на скачивание (дубль Telegram).
- ❌ Ответ по Issue.
5.2. SMS
- ❌ Провайдер: TurboSMS / SMSC / Twilio.
- ❌ Ключи.
- ❌ Логика.
5.3. Telegram
- ✅ Бот работает в проде (webhook).
- ❌ Уведомления клиенту: «Оплачено», «Ссылка», «Брошенная корзина».
- ❌ Уведомления админу: новый заказ, новый Issue, критичная ошибка,
ноут не отвечает на
auth_request.
6. Инфраструктура
6.1. Хранилище и отдача
Корни:
- ✅ STORAGE_ROOT — на ноуте, /mnt/hdd/znymkari-storage/ (единое хранилище).
- ✅ FESTIVALS_ROOT — на ноуте, /mnt/hdd/zny-festivals/ (оригиналы).
- ✅ PREVIEW_ROOT — на ноуте /mnt/ssd/..., на VPS /srv/previews/.
Ноут — публикация (план):
- ✅ Проброс 22022 → 192.168.31.87:22.
- 🔜 Проброс 443 → 192.168.31.87:443.
- 🔜 DNS: files.znymkari.com → A → 193.176.249.24.
- 🔜 Firewall ноута: 22, 80, 443, WireGuard.
- 🔜 nginx ноута слушает :443 с auth_request.
- 🔜 auth_request → http://10.0.0.1:8000/internal/check-token/.
- 🔜 Let's Encrypt на files.znymkari.com.
- 🔜 fail2ban.
Модель DownloadToken (VPS):
- ❌ is_valid().
- ❌ Инкремент при auth_request.
- ❌ Админка с фильтрами.
60%-превью (план):
- ❌ Поля Media.width/height.
- ❌ Endpoint /catalog/api/client/media/<id>/large/.
- ❌ Internal API /internal/large-preview/ на ноуте.
- ❌ Кеш MEDIA_LARGE_CACHE/<id>.jpg.
- ❌ Кнопка «Проверить качество» в лайтбоксе.
Хранилище (единое, без HOT/COLD):
- ✅ content_shop_archive → znymkari-storage (2026-10-16).
- 🔜 Перенос на второй HDD при заполнении (Олег планирует покупку).
- 🔜 RSYNC-бэкап znymkari-storage на второй HDD.
6.2. Бэкапы
- ❌ БД ноута → второй HDD / облако.
- ❌ БД VPS → на ноут + облако.
- 🔜
znymkari-storage→ второй HDD (при покупке). - 🔜
zny-festivals→ второй HDD (при покупке). - ❌ Превью (VPS) → облако.
- ❌
settings_local.py→ локально + облако. - ❌ Автоматизация (cron / systemd timers).
- ❌ Проверить восстановление.
6.3. Мониторинг и логи
- ✅ Django logging → файл
/var/log/znymkari/django.log+RotatingFileHandler(10 МБ × 5). - ❌ Healthcheck (
/healthz/). - ❌ Внешний мониторинг.
- ❌ Ротация системных логов.
- ❌ Sentry.
- ❌ Диск-мониторинг ноута.
- ❌ Мониторинг WireGuard / nginx ноута.
6.4. Безопасность
- ✅
DEBUG = False. - ✅
SECRET_KEY— боевой, вне git. - ✅
settings_local.py— на VPS и на ноуте, вне git. - ❌
INTERNAL_SECRET— общий секрет VPS ↔ ноут. - ✅ HTTPS-only (HSTS,
SECURE_SSL_REDIRECT). - ✅
SESSION_COOKIE_SECURE = True. - ✅
CSRF_COOKIE_SECURE = True. - ✅
SECURE_HSTS_SECONDS = 31536000,SECURE_HSTS_INCLUDE_SUBDOMAINS. - ❌
SECURE_HSTS_PRELOAD = True(необратимо, позже). - ❌ Бэкап
SECRET_KEYвне сервера. - ✅ Firewall VPS (80/443 + SSH по ключу).
- 🔜 Firewall ноута.
- ✅ SSH VPS только по ключу.
- 🔜 SSH ноута только по ключу.
- ❌ fail2ban.
- 🚧 Регулярные обновления системы.
- ✅ Пароль админки сложный.
7. Код — что доделать
7.0. znymkari-data — цех импорта
- ✅ Каркас Django-проекта, отдельный git-репо.
- ✅ Модели
catalog(10 моделей), миграции0001–0010. - ✅
sanitize.py— транслит. - ✅
media_metadata.py— локальная копия из старого мира. - ✅
import_service.py— копирование + превью + sanitize. - ✅ Команда
import_media <event_id> <festival_name>. - ✅ Команда
generate_video_posters <event_id> [--force]. - ✅ Поля
Event.external_id,Event.slug,Event.source_folder. - ❌
Media.width,Media.height. - ✅ Мини-админка Олега:
/,/import/,/import/<id>/,/storage/,/settings/. - ✅ Модель
ImportJob. - ✅
pack_event/push_event— проверено на живом цикле. - ✅ Интерфейс отправки в Лаборатории (логи, прогресс-бар, SFTP).
- ✅ Экран «Чистка» (сироты, пустые ивенты, зависшие задачи).
- ✅ Кнопка «Проверить связь с VPS».
- ✅
gunicorn-oleg.service.
7.1. Транспорт VPS ↔ ноут
- ✅
receive_eventна VPS — мягкий merge JSON через ORM. - ✅ Превью →
/srv/previews/. - ✅
requirements.txt—paramikoдобавлен. - ✅ Идемпотентность проверена: повторный push без дублей.
- ❌ Backup VPS-БД перед merge.
- ❌ Обратный канал VPS → ноут:
pull_protected+ файл чистки.
7.2. Критично
- ✅ Webhook для Telegram-бота.
- ✅
DEBUG = False. - ❌ Оплата (Этап 3).
- ❌ Выдача через
DownloadToken. - ❌ Реальный SMTP.
- ❌ Восстановление пароля.
- ✅ Локальный импорт (
znymkari-data) — команда работает. - ✅ Мини-админка Олега.
- ✅ Транспорт на VPS (
pack_event/push_event/receive_event).
7.3. Очень желательно
- ❌
home.html→ канонический app-shell. - ❌
event.html→ общийlightbox.js. - ✅ Тесты — 77 OK.
- ❌ Мобильная версия.
- ❌ Мобильная корзина (удаление на тач).
- 🚧
favicon.ico(файл есть, nginx не отдаёт). - ❌ Заголовки и meta на всех страницах.
- ❌
robots.txt/sitemap.xml. - ❌ og:image.
- ❌ Rate limit на API.
- ❌ Защита от массового скачивания превью.
- ❌ Кнопка «Проверить качество».
7.4. Желательно
- ❌ SiteSettings — контакты, соцсети, лого.
- ❌ Страница «Услуги».
- ❌ Публичная форма
/issue/. - ❌ Вложения к Issue.
- 🚧 Экспорт ивентов (JSON / PDF / Excel).
- ❌ Кнопка «Удалить без лайков и покупок».
- ❌
width/heightвMedia. - ❌ Бок-о-бок расходы / доходы.
- ❌ File picker для путей.
- ❌ Поиск по фразе (синонимы).
- 🚧 Grid-view для разметки.
- 🚧
.timeline-*→.markup-*+PAGE_TIMELINE. - ❌ Уведомления о брошенной корзине.
7.5. Стратегическое
- ❌ Кэшбек (
referrer_userв Order). - ❌ Рефералка / групповой кошик.
- ❌ Telegram как единственный способ.
- ✅ Удаление старого мира (
domain/,storage/,cli/,scripts/,services/) — 2026-10-16.
8. Инструкции
8.1. Для себя
- ❌
INSTALL.md— установка с нуля. - ❌
DEPLOY.md— развёртывание. - ✅
deploy.bat— VPS. - 🔜
deploy-data.bat/ SFTP —znymkari-dataна ноут. - ✅
SETUP_VPS.md. - ✅
SETUP_HOME.md. - ✅
COMMANDS.md. - ❌
BACKUP.md. - ❌
OPERATIONS.md. - ❌
TROUBLESHOOTING.md. - ❌
TELEGRAM.md. - ❌
PAYMENTS.md. - ❌
STORAGE_MIGRATION.md. - ❌
NGINX_HOME.md.
8.2. Для клиента
- ❌ «Как купить?» — проверить содержимое.
- ❌ FAQ.
- ❌ «Контакты».
- ❌ Terms.
- ❌ Политика возврата.
- ❌ Политика конфиденциальности.
8.3. Внутренняя документация
- ✅
CONTEXT.md,STATE.md,ARCHITECTURE.md,CHANGES.md,PRODUCTION.md. - ✅
SETUP_HOME.md,SETUP_VPS.md,COMMANDS.md.
9. Данные
9.1. Контент
- ✅ Ребрендинг «BRAVO» → «Znymkari».
- ❌ Хвосты в
.md. - ❌ Перегенерация старых превью с QR BRAVO.
- ❌ Логотип (PNG / SVG) — шапка, футер, favicon.
- ❌ Слоган / описание.
- ❌ Фото для главной / карусели.
- ❌ Реальные контакты.
- ❌ Реквизиты.
- ❌ Заполнить
Organizer.
9.2. Прайс
- ❌ Проверить все цены в
Event. - ❌ Совпадает с
/catalog/prices/. - ❌ Решить:
discount_cash_percentприменяется?
9.3. Импорт
- ✅ Тестовый импорт (фото + видео) на Windows — работает.
- ❌ Прогнать импорт реального ивента на ноуте.
- ✅ Проверено: превью 600px с QR / постеры / 10-сек превью.
- ✅ Проверено:
camera_key,camera_offset_seconds. - ✅ Проверено:
push_event/receive_event— идемпотентность подтверждена. - ✅ Проверено:
assign_media_authorsна VPS. - ❌ Прогнать разметку.
10. Юридическое
- ❌ Политика конфиденциальности.
- ❌ Terms.
- ❌ Политика возврата.
- ❌ Cookie-баннер.
- ❌ Согласие на обработку персональных данных.
- ❌ Оферта.
11. Развёртывание
11.1. VPS — ✅
- ✅ Ubuntu 24.04.5 LTS, ядро 6.8.0-146.
- ✅ Пользователь
deploy, sudo NOPASSWD. - ✅ Python 3.12.3, pip, venv.
- ✅ PostgreSQL 16.15.
- ✅ nginx 1.24.
- ✅ ffmpeg 6.1.1.
- ✅ certbot.
- ✅ systemd:
- ✅
gunicorn-znymkari.service. - ✅
run_telegram_bot.service— disabled. - 🔜
wireguard. - ✅ nginx: прокси + статика +
/media/. - ✅ Код через
tar+scp. - ✅
settings_local.py— боевой. - ✅
migrate,collectstatic. - ✅ Суперюзер
admin. - ✅
https://znymkari.com→ 200 OK.
11.1-бис. Ноут Олега
- ✅ Белый IP
193.176.249.24. - ✅ Ubuntu Server 24.04 LTS.
- ✅
olegarh/deploy. - ✅ SSH-ключ
id_ed25519. - ✅ LAN
192.168.31.87(резерв DHCP). - ✅ Ethernet сломан, не используется.
- ✅ Проброс
22022 → 192.168.31.87:22. - ✅ Сон отключён.
- ✅ Python 3.14 + ffmpeg 8.0.1.
- ✅ PostgreSQL 18 (
znymkari_local). - ✅ nginx 1.28.
- ✅ HDD WD My Passport 2 ТБ.
- ✅ STORAGE / FESTIVALS / HEAP.
- ✅ Симлинки в
/home/olegarh(HDD,STORE). - ✅ Samba с
zny-festivals,zny-heap. - ✅ 10 фестивалей в
zyn-festivals. - ⏳ Django + venv +
settings_local.py(znymkari-data) — код готов, деплой на ноут ещё нет. - ⏳
gunicorn-oleg.service. - ✅ Мини-админка Олега — код готов (5 страниц,
ImportJob, транспорт). Не развёрнута. - 🔜 nginx ноута +
auth_request+ отдача файлов. - 🔜 Certbot
files.znymkari.com. - 🔜 WireGuard VPS ↔ ноут.
- 🔜 fail2ban.
- 🔜
migrate_events.sh. - 🔜 Бэкап-скрипт.
- 🔜 Мониторинг.
- 🔜 Ребут-тест.
11.2. Проверка после развёртывания
- ✅ Главная открывается.
- ✅ Event: галерея, лайтбокс.
- ✅ Telegram-вход.
- ✅ Избранное / Корзина.
- ✅ Разметка ивента.
- ✅ Бот
/start,/help,/me. - ✅ Webhook.
- ✅ Доки.
- ❌ Регистрация email → письмо → активация.
- ✅ Импорт медиа (
znymkari-data) — фото + видео, тест пройден. - ✅ Мини-админка Олега (страницы
/,/import/,/import/<id>/,/storage/,/settings/). - ✅ Пуш на VPS —
pack_event→push_event→receive_event. Проверено на живом цикле. - 🔜
auth_request, скачивание, лимит, срок. - 🔜 60%-превью.
11.3. Финальный чек-лист
- ✅
DEBUG = False. - ✅
ALLOWED_HOSTS. - ✅
SECRET_KEY. - ❌
INTERNAL_SECRET. - ✅ HTTPS VPS.
- 🔜 HTTPS ноут.
- ❌ Бэкапы.
- ❌ Мониторинг.
- ❌ Sentry.
- ✅ Логи пишутся (файл).
- ❌ SMTP.
- ❌ Оплата.
- ✅ Telegram-бот боевой.
- ✅ Вход через Telegram.
- ✅ Доки.
- ❌ Ротация токена бота.
- ❌ Ротация пароля Postgres.
- ❌ Бэкап
settings_local.py. - ❌ Тестовый заказ.
- ❌ Первый реальный заказ.
12. Пост-запуск
Первая неделя
- ❌ Логи каждый день.
- ❌ Sentry / мониторинг.
- ❌ Фидбек.
- ❌ Баги → в трекер.
Первый месяц
- ❌ Бэкапы работают.
- ❌ Место на дисках.
- ❌ Скорость API.
- ❌ Миграция HOT → COLD не сломала старьё.
- ❌
auth_requestне тормозит.
Плановое
- ❌ Раз в неделю — бэкап, лог.
- ❌ Раз в месяц — перенос HOT → COLD.
- ❌ Раз в год — чистка ивентов.
Открытые вопросы
- ✅ Postgres реализован на VPS и на ноуте.
- ❌ Провайдер оплаты?
- ❌ Кто регистрирует ФОП/ТОВ?
- ❌ SMS — нужен?
- ❌ Храним оригиналы вечно?
- ❌ Срок жизни ссылки — 72 часа?
- ❌ Лимит скачиваний — 1 раз на файл?
- ❌ Что делать, если клиент потерял ссылку?
- ❌ Что делать, если дома упал свет?
- ❌ Кэшбек — нужен?
- ❌ Мобильная версия — насколько глубоко?
- ❌
STORAGE_ROOTна VPS — нужен ли вообще?