yt-dlp-gui/deploy/ytdlp-gui.service
loop-uh a4ac02a023 YouTube: свой профиль zapret (провайдер режет SNI youtube.com); квота загрузок 50 ГБ
13.10.2026 сайт висел на «Проверяем…» для любой ссылки YouTube: провайдер
начал молча глотать ClientHello с SNI youtube.com, youtu.be, ytimg.com,
ggpht.com и youtubei.googleapis.com (TCP проходит, TLS молчит; с SNI
www.google.com на том же адресе рукопожатие проходит). В списках zapret
YouTube не было вовсе. Заведён отдельный список egress-hosts-yt.txt и профиль
hostfakesplit_multi:hosts=google.com,vimeo.com:tcp_ts=-1000:tcp_md5:repeats=2
(zapret-multishake.lua) — описано в AGENTS.md вместе с запасными стратегиями
и быстрой проверкой.

YTG_DISK_QUOTA_MB: 5120 -> 51200. В 5 ГБ влезало два с половиной файла
предельного размера, готовый файл могли вытеснить раньше, чем его сохранят.
Раздел защищает отдельный порог YTG_MIN_FREE_DISK_MB.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 18:57:58 +03:00

105 lines
5.2 KiB
Desktop File
Raw Permalink 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.

[Unit]
Description=yt-grab — веб-GUI для yt-dlp (yt.zapret.moe)
After=network-online.target ytgrab-egress-tunnel.service ytgrab-egress-pool.target ytgrab-youtube-ip.service
Wants=ytgrab-egress-tunnel.service ytgrab-egress-pool.target ytgrab-youtube-ip.service
Wants=network-online.target
[Service]
Type=simple
# Отдельный системный пользователь, а не codex-pve: весь трафик uid 1000
# (codex-pve) заворачивает в туннель VPN-замок ccw-vpn (ccw-vpn-lock.service,
# /etc/ccw-vpn), а всё мимо туннеля сбрасывает. Привязка к <IP_ДЛЯ_YOUTUBE> на
# vmbr0 под ним даёт «Connection reset by peer» — 29.09.2026 YouTube так и
# лёг. Доступ к репозиторию — ACL: x на /home/codex-pve, rX на репо,
# rwX на downloads/ и data/ (setfacl, пакет acl).
User=ytgrab
Group=ytgrab
WorkingDirectory=/home/codex-pve/ytdlp-gui
# Домашняя папка примонтирована только на чтение (ProtectHome),
# а gunicorn пишет туда управляющий сокет — уводим его в приватный /tmp.
Environment=HOME=/tmp
Environment=YTG_HOST=127.0.0.1
Environment=YTG_PORT=8090
Environment=YTG_TRUST_PROXY=1
Environment=YTG_MAX_CONCURRENT=32
Environment=YTG_MAX_FILESIZE_MB=2048
# Квота держится заметно ниже свободного места на разделе: это
# гипервизор, и заполнить его корень — значит остановить виртуальные
# машины, а не просто отдать пользователю ошибку.
Environment=YTG_DISK_QUOTA_MB=51200
Environment=YTG_QUIET_ACCESS_LOG=1
Environment=YTG_EGRESS_PROXY=socks5h://127.0.0.1:18099
Environment=YTG_EGRESS_POOL=socks5://127.0.0.1:18110-18141
Environment=YTG_YT_SOURCE_IP=<IP_ДЛЯ_YOUTUBE>
# Один воркер: состояние задач держится в памяти процесса.
# Потоки обслуживают SSE-соединения и параллельные запросы.
# Потоков заметно больше числа одновременных загрузок: каждое SSE-соединение
# занимает поток на всё время загрузки, и при 16 потоках сервис подвешивался
# двумя клиентами. В nginx стоит limit_conn 24 на адрес.
ExecStart=/home/codex-pve/ytdlp-gui/.venv/bin/gunicorn \
--workers 1 \
--threads 64 \
--timeout 0 \
--graceful-timeout 30 \
--bind 127.0.0.1:8090 \
--access-logfile /dev/null \
--error-logfile - \
app:app
Restart=on-failure
RestartSec=5
# --- Изоляция ---
NoNewPrivileges=yes
PrivateTmp=yes
ProtectSystem=strict
ProtectHome=read-only
ReadWritePaths=/home/codex-pve/ytdlp-gui/downloads
ReadWritePaths=/home/codex-pve/ytdlp-gui/data
ProtectKernelTunables=yes
ProtectKernelModules=yes
ProtectControlGroups=yes
RestrictSUIDSGID=yes
RestrictNamespaces=yes
LockPersonality=yes
# --- Запрет исходящих во внутреннюю сеть ---
# Проверка адреса в приложении принципиально не закрывает DNS rebinding
# (yt-dlp резолвит имя заново и сам ходит по редиректам), поэтому запрет
# ставится на уровне ядра. Хост — гипервизор: во внутренней сети живут
# его API и виртуальные машины.
# Здесь НЕТ IPAddressAllow=any, и это существенно: с ним запреты ниже
# фактически не работали — проверено, Proxmox API на 10.20.0.1:8006 и
# соседняя ВМ оставались доступны. Когда список состоит только из
# запретов, systemd пропускает всё остальное, и внешняя сеть с DNS
# продолжают работать (тоже проверено).
#
# Петля (127.0.0.0/8, ::1) сознательно НЕ закрыта: фильтр systemd не
# различает направление, и запрет петли обрывает входящие соединения от
# nginx к этому же сервису — проверено, слушатель становится недоступен
# снаружи и сайт ложится. Поэтому службы на 127.0.0.1 остаются достижимы;
# закрыть их можно, только переведя связку nginx→приложение на
# unix-сокет.
IPAddressDeny=10.0.0.0/8
IPAddressDeny=172.16.0.0/12
IPAddressDeny=192.168.0.0/16
IPAddressDeny=169.254.0.0/16
IPAddressDeny=100.64.0.0/10
IPAddressDeny=fc00::/7
IPAddressDeny=fe80::/10
# --- Ресурсы хоста ---
# Сервис делит гипервизор с виртуальными машинами: ffmpeg при
# перекодировании иначе забирает все ядра у соседей.
CPUWeight=20
IOWeight=20
Nice=10
# --- Лимиты ресурсов ---
MemoryMax=4G
TasksMax=2048
[Install]
WantedBy=multi-user.target