VoxIP Kiosk OS 1.0.0: Raspberry Pi kiosk with web management
CI / test-bookworm (push) Failing after 11s
CI / test-latest (push) Successful in 1m27s

Chromium kiosk without a desktop for the Raspberry Pi 3, a Flask web
interface on port 8080 (kiosk, system and network management), a
restricted root helper, network changes with automatic rollback, a
healthcheck timer, install/update/uninstall scripts and a pi-gen image
build.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
rothmanandClaude Opus 5.5 committed 2026-11-04 21:38:49 +01:00
commit a33c4822bf
96 files changed
+7535

No files matched your search

+73
View File
@@ -0,0 +1,73 @@
"""VoxIP Kiosk Manager — Flask application factory."""
from __future__ import annotations
import os
import secrets
from dataclasses import dataclass
from datetime import timedelta
from typing import Any
from flask import Flask
from ..cdp import CDP
from ..config import load_config
from ..helper_client import HelperClient
from ..paths import Paths, load_paths, read_version
from .auth import CredentialStore, LoginThrottle
@dataclass
class Services:
paths: Paths
credentials: CredentialStore
throttle: LoginThrottle
helper: Any
cdp: Any
version: str
def _secret_key(paths: Paths) -> bytes:
path = paths.secret_key_file
try:
key = path.read_bytes()
if len(key) >= 32:
return key
except FileNotFoundError:
pass
key = secrets.token_bytes(64)
fd = os.open(str(path), os.O_WRONLY | os.O_CREAT | os.O_TRUNC, 0o600)
with os.fdopen(fd, "wb") as fh:
fh.write(key)
return key
def create_app(paths: Paths | None = None, *, helper: Any = None, cdp: Any = None) -> Flask:
paths = paths or load_paths()
config = load_config(paths.config_file)
app = Flask(__name__)
app.secret_key = _secret_key(paths)
app.config.update(
SESSION_COOKIE_NAME="voxip_session",
SESSION_COOKIE_HTTPONLY=True,
SESSION_COOKIE_SAMESITE="Strict",
SESSION_COOKIE_SECURE=config["admin_https"],
PERMANENT_SESSION_LIFETIME=timedelta(hours=12),
MAX_CONTENT_LENGTH=64 * 1024,
TEMPLATES_AUTO_RELOAD=False,
)
credentials = CredentialStore(paths.admin_file, paths.setup_code_file)
credentials.ensure_setup_code()
app.extensions["voxip"] = Services(
paths=paths,
credentials=credentials,
throttle=LoginThrottle(),
helper=helper or HelperClient(paths.helper),
cdp=cdp or CDP(timeout=5),
version=read_version(paths),
)
from .views import bp
app.register_blueprint(bp)
return app