feat: публикация портов не-HTTP сервисами, проверка портов до деплоя, пример RustDesk
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>
This commit is contained in:
1 parent
a8d1f286d1
commit
fd4b05097a
16 files changed
+526
-13
No files matched your search
Executable
+38
@@ -0,0 +1,38 @@
|
||||
#!/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'))
|
||||
Reference in new issue
Block a user