Web-панель была подготовлена к продакшену

- исправлен NameError при создании VM: не был импортирован platform;
- на странице VM автозапуск всегда показывался выключенным;
- сообщения в redirect-URL теперь кодируются (кириллица, пробелы, &);
- проверка пароля вынесена в web/auth.py и работает на Python 3.13+,
  где модули crypt и spwd удалены (fallback на libcrypt и /etc/shadow);
- добавлены ограничение попыток входа, срок жизни сессии, флаг Secure
  для cookie, защита от cross-origin POST и заголовки безопасности;
- добавлен публичный /healthz с версией панели;
- правила проброса портов восстанавливаются после перезагрузки
  (virtuality-network.service);
- обновление из панели запускается через systemd-run и больше не
  убивается перезапуском virtuality-web;
- install_web_panel.sh сохраняет порт, пользователя и режим
  автообновления в /var/lib/virtuality/config/web.env, поэтому
  обновление больше не сбрасывает порт на 8088 и пользователя на viktor;
- поддержка офлайн-установки Python-зависимостей из wheels/.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019LEUXMcdZo7b87mjkUsPgg
Этот коммит содержится в:
Claude
2026-09-25 06:26:51 +00:00
родитель 10a780d381
Коммит 975ab4d1a0
6 изменённых файлов: 342 добавлений и 38 удалений
+8 -1
Просмотреть файл
@@ -1,5 +1,6 @@
import json
import os
import shutil
import subprocess
from datetime import datetime
from pathlib import Path
@@ -219,5 +220,11 @@ def start_update() -> dict[str, Any]:
'finished_at': '',
}
write_json(STATE_FILE, data)
subprocess.Popen(['bash', str(script)], cwd=str(SOURCE_DIR), stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, start_new_session=True)
cmd = ['bash', str(script)]
if shutil.which('systemd-run'):
# Run outside virtuality-web's cgroup: the update restarts virtuality-web,
# which would otherwise kill the update script before it finishes.
unit = f"virtuality-update-{datetime.now().strftime('%Y%m%d%H%M%S')}"
cmd = ['systemd-run', '--unit', unit, '--collect', '--quiet', f'--setenv=VIRTUALITY_SOURCE_DIR={SOURCE_DIR}', f'--working-directory={SOURCE_DIR}'] + cmd
subprocess.Popen(cmd, cwd=str(SOURCE_DIR), stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, start_new_session=True)
return data