feat(templates): wire SSH+Telnet to sessrec transcript recorder
Build login-session into both images as the swapped root shell, add a quarantine bind mount for telnet (symmetric to SSH), seed transcripts/ dir and service discriminant at entrypoint. Deployer syncs sessrec.c + Makefile into each build context alongside the existing syslog_bridge helper. sessrec falls back to /etc/sessrec.service when env is stripped (busybox /bin/login).
This commit is contained in:
@@ -49,6 +49,8 @@ log = get_logger("engine")
|
||||
console = Console()
|
||||
COMPOSE_FILE = Path("decnet-compose.yml")
|
||||
_CANONICAL_LOGGING = Path(__file__).parent.parent / "templates" / "syslog_bridge.py"
|
||||
_CANONICAL_SESSREC_DIR = Path(__file__).parent.parent / "templates" / "_shared" / "sessrec"
|
||||
_SESSREC_SERVICES = {"ssh", "telnet"}
|
||||
|
||||
|
||||
def _sync_logging_helper(config: DecnetConfig) -> None:
|
||||
@@ -69,6 +71,33 @@ def _sync_logging_helper(config: DecnetConfig) -> None:
|
||||
shutil.copy2(_CANONICAL_LOGGING, dest)
|
||||
|
||||
|
||||
def _sync_sessrec_sources(config: DecnetConfig) -> None:
|
||||
"""Copy sessrec.c + Makefile into SSH/Telnet build contexts as sessrec/."""
|
||||
from decnet.services.registry import get_service
|
||||
sources = [
|
||||
_CANONICAL_SESSREC_DIR / "sessrec.c",
|
||||
_CANONICAL_SESSREC_DIR / "Makefile",
|
||||
]
|
||||
seen: set[Path] = set()
|
||||
for decky in config.deckies:
|
||||
for svc_name in decky.services:
|
||||
if svc_name not in _SESSREC_SERVICES:
|
||||
continue
|
||||
svc = get_service(svc_name)
|
||||
if svc is None:
|
||||
continue
|
||||
ctx = svc.dockerfile_context()
|
||||
if ctx is None or ctx in seen:
|
||||
continue
|
||||
seen.add(ctx)
|
||||
dest_dir = ctx / "sessrec"
|
||||
dest_dir.mkdir(exist_ok=True)
|
||||
for src in sources:
|
||||
dest = dest_dir / src.name
|
||||
if not dest.exists() or dest.read_bytes() != src.read_bytes():
|
||||
shutil.copy2(src, dest)
|
||||
|
||||
|
||||
def _compose(*args: str, compose_file: Path = COMPOSE_FILE, env: dict | None = None) -> None:
|
||||
import os
|
||||
# -p decnet pins the compose project name. Without it, docker compose
|
||||
@@ -215,6 +244,7 @@ def deploy(config: DecnetConfig, dry_run: bool = False, no_cache: bool = False,
|
||||
setup_host_macvlan(config.interface, host_ip, decky_range)
|
||||
|
||||
_sync_logging_helper(config)
|
||||
_sync_sessrec_sources(config)
|
||||
|
||||
compose_path = write_compose(config, COMPOSE_FILE)
|
||||
console.print(f"[bold cyan]Compose file written[/] → {compose_path}")
|
||||
|
||||
Reference in New Issue
Block a user