scaffold: project skeleton, schema, healthz/readyz, CI
Initial project structure for neuronetz-gateway per scope-docs/SPEC.md: - Python 3.12 / FastAPI / SQLAlchemy 2.0 (async) / Redis / Postgres stack managed by uv. Multi-stage non-root Dockerfile, prod + dev compose files (ollama service is NEVER published in either), Caddyfile + systemd unit, justfile, GitHub Actions CI (ruff, mypy --strict, pytest, bandit, pip-audit). - Pydantic-Settings config covering every env var from SPEC §7, including the MODEL_DISCOVERY_* keys for the dynamic-discovery feature (§4.6). - Alembic 0001_initial creates the full gateway schema (8 tables, 3 enums, notify_key_revoked() trigger), incl. allow_all_models on tenant_limits and key_limits for the per-tenant auto-grant toggle. - Working /healthz, /readyz (fail-closed when deps unreachable), and a Prometheus /metrics stub. Sanitizing error handlers that attach X-Request-ID to every response and never leak upstream internals. - SPEC + AGENT_PROMPT included under scope-docs/ (source of truth).
This commit is contained in:
58
ops/systemd/neuronetz-gateway.service
Normal file
58
ops/systemd/neuronetz-gateway.service
Normal file
@@ -0,0 +1,58 @@
|
||||
# neuronetz-gateway — systemd unit for non-Compose deployments.
|
||||
#
|
||||
# Assumes the project is installed into a virtualenv at /opt/neuronetz-gateway/venv
|
||||
# (e.g. `uv venv /opt/neuronetz-gateway/venv && uv pip install ...`) and that
|
||||
# configuration lives in /etc/neuronetz-gateway/gateway.env (same keys as
|
||||
# .env.example). Postgres, Redis and Ollama are reached over the network/loopback
|
||||
# per that env file — Ollama must remain bound to localhost / a private network
|
||||
# and never be published publicly.
|
||||
#
|
||||
# Install:
|
||||
# sudo cp neuronetz-gateway.service /etc/systemd/system/
|
||||
# sudo systemctl daemon-reload
|
||||
# sudo systemctl enable --now neuronetz-gateway
|
||||
|
||||
[Unit]
|
||||
Description=neuronetz-gateway — secure API gateway in front of Ollama
|
||||
Documentation=https://github.com/neuronetz/neuronetz-gateway
|
||||
After=network-online.target
|
||||
Wants=network-online.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
|
||||
# Dedicated unprivileged service account (create with: useradd --system gateway).
|
||||
User=gateway
|
||||
Group=gateway
|
||||
|
||||
WorkingDirectory=/opt/neuronetz-gateway
|
||||
EnvironmentFile=/etc/neuronetz-gateway/gateway.env
|
||||
|
||||
# Apply migrations before starting (idempotent; no-op when already at head).
|
||||
ExecStartPre=/opt/neuronetz-gateway/venv/bin/alembic upgrade head
|
||||
ExecStart=/opt/neuronetz-gateway/venv/bin/python -m neuronetz_gateway
|
||||
|
||||
Restart=on-failure
|
||||
RestartSec=5
|
||||
TimeoutStopSec=30
|
||||
|
||||
# --- Hardening ---
|
||||
NoNewPrivileges=true
|
||||
ProtectSystem=strict
|
||||
ProtectHome=true
|
||||
PrivateTmp=true
|
||||
PrivateDevices=true
|
||||
ProtectKernelTunables=true
|
||||
ProtectKernelModules=true
|
||||
ProtectControlGroups=true
|
||||
RestrictNamespaces=true
|
||||
RestrictRealtime=true
|
||||
RestrictSUIDSGID=true
|
||||
LockPersonality=true
|
||||
MemoryDenyWriteExecute=true
|
||||
RestrictAddressFamilies=AF_INET AF_INET6 AF_UNIX
|
||||
# Allow writing only where the app legitimately needs to (none by default).
|
||||
ReadWritePaths=
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
Reference in New Issue
Block a user