serverus: app_ports.py проверяет опубликованные порты приложения до изменений - по docker compose config (переменные из .env подставлены) против слушающих сокетов сервера и портов контейнеров других приложений. Занятый порт больше не роняет up после замены файлов. Конвенция: только мост; не-HTTP сервисы публикуют свои порты, 80 и 443 - у caddy; bind-mount только своих файлов из data/<сервис>/ с :ro. Описано, что упавший up после синхронизации файлы не откатывает. App: uploads.check предупреждает о 80/443 вместо любых портов и о bind-mount из папки приложения вне data/ или без :ro. docs/apps/rustdesk: приложение (hbbs, hbbr, ключ генерируем сами), genkey.py и check.py - проверка сервера по протоколу RustDesk снаружи. Проверено на стенде Debian 13: деплой, повторный деплой, отказ второго приложения на тех же портах до изменений, перезагрузка сервера. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
39 lines
1.9 KiB
Python
Executable File
39 lines
1.9 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
"""Ключ RustDesk для приложения: genkey.py [<папка приложения>], по умолчанию app/ рядом со скриптом.
|
|
|
|
Пара ed25519 в формате hbbs/hbbr: id_ed25519 - base64 64 байт (seed + публичный ключ), id_ed25519.pub - base64
|
|
32 байт публичного ключа. Пишется в data/hbbs/ и data/hbbr/. Существующий ключ не перезаписывается: новый ключ
|
|
отключит всех настроенных клиентов. Печатает публичный ключ - его вводят в клиентах.
|
|
Нужен пакет cryptography (есть в .venv проекта).
|
|
"""
|
|
import base64
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
from cryptography.hazmat.primitives import serialization
|
|
from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PrivateKey
|
|
|
|
SERVICES = ('hbbs', 'hbbr')
|
|
|
|
|
|
def main(app_dir: Path) -> int:
|
|
paths = [app_dir / 'data' / service / 'id_ed25519' for service in SERVICES]
|
|
existing = [path for path in paths if path.exists()]
|
|
if existing:
|
|
print(f'ключ уже есть: {existing[0]}, публичный: {existing[0].with_suffix(".pub").read_text().strip()}')
|
|
return 1
|
|
key = Ed25519PrivateKey.generate()
|
|
seed = key.private_bytes(serialization.Encoding.Raw, serialization.PrivateFormat.Raw, serialization.NoEncryption())
|
|
public = key.public_key().public_bytes(serialization.Encoding.Raw, serialization.PublicFormat.Raw)
|
|
for path in paths:
|
|
path.parent.mkdir(parents=True, exist_ok=True)
|
|
path.write_text(base64.b64encode(seed + public).decode())
|
|
path.chmod(0o600)
|
|
path.with_suffix('.pub').write_text(base64.b64encode(public).decode())
|
|
print(base64.b64encode(public).decode())
|
|
return 0
|
|
|
|
|
|
if __name__ == '__main__':
|
|
sys.exit(main(Path(sys.argv[1]) if len(sys.argv) > 1 else Path(__file__).resolve().parent / 'app'))
|