left4me/l4d2web
mwiegand ffc4cdbd7d
refactor(l4d2-web): remove legacy external overlay type
The workshop + managed-global overlay surface fully covers the
admin-SFTP flow that 'external' was a placeholder for. Drop the type
from the model defaults, builder registry, routes, template, and
tests, and add migration 0004 that deletes any leftover external
rows along with their blueprint and job references.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 09:31:04 +02:00
..
alembic refactor(l4d2-web): remove legacy external overlay type 2026-05-08 09:31:04 +02:00
routes refactor(l4d2-web): remove legacy external overlay type 2026-05-08 09:31:04 +02:00
services refactor(l4d2-web): remove legacy external overlay type 2026-05-08 09:31:04 +02:00
static feat(web): blueprint-prefilled create-server flow + empty-state CTA 2026-05-07 01:47:33 +02:00
templates refactor(l4d2-web): remove legacy external overlay type 2026-05-08 09:31:04 +02:00
tests refactor(l4d2-web): remove legacy external overlay type 2026-05-08 09:31:04 +02:00
__init__.py chore(l4d2): flatten component layout 2026-05-05 23:47:06 +02:00
alembic.ini chore(l4d2): flatten component layout 2026-05-05 23:47:06 +02:00
app.py feat(l4d2-web): workshop overlay UI (routes + templates) 2026-05-07 16:50:54 +02:00
auth.py fix(l4d2-web): reject encoded unsafe redirects 2026-05-06 13:24:04 +02:00
cli.py feat(l4d2-web): managed global map overlays with daily refresh 2026-05-08 08:05:14 +02:00
config.py feat(web): forms in modals, edit/delete on detail pages, port auto-assign 2026-05-07 01:30:33 +02:00
db.py feat(deploy): add production-like test deployment 2026-05-06 19:30:10 +02:00
models.py refactor(l4d2-web): remove legacy external overlay type 2026-05-08 09:31:04 +02:00
pyproject.toml feat(l4d2-web): managed global map overlays with daily refresh 2026-05-08 08:05:14 +02:00
README.md feat(deploy): add production-like test deployment 2026-05-06 19:30:10 +02:00

l4d2-web-app

Flask web app for managing L4D2 servers through user-private blueprints.

Key v1 behaviors

  • Local username/password login; no public signup
  • Admin-managed overlay catalog
  • Private blueprints per user
  • Server creation from blueprints (live-linked; no per-server blueprint overrides)
  • Async job model with persisted command logs in job_logs
  • Desired vs actual state model
  • Live logs for jobs and servers via SSE endpoints
  • Host operations go through l4d2ctl via a local host command runner, not direct l4d2host imports

Frontend constraints

  • Server-rendered templates (Jinja)
  • Vendored HTMX (static/vendor/htmx.min.js)
  • Custom CSS only
  • Tokenized, consistent link and accent colors

Development

python3 -m venv .venv
.venv/bin/pip install -e .
.venv/bin/pytest tests -q

Configuration

The web app reads these settings from the environment:

  • DATABASE_URL: SQLAlchemy database URL, for example sqlite:////var/lib/left4me/left4me.db.
  • SECRET_KEY: Flask secret key used for sessions and CSRF-sensitive state.
  • JOB_WORKER_THREADS: number of background job worker threads.

In the systemd deployment, environment is loaded from /etc/left4me/host.env and /etc/left4me/web.env.

Admin Bootstrap

Create the first admin account with the Flask CLI. Provide the password through LEFT4ME_ADMIN_PASSWORD:

LEFT4ME_ADMIN_PASSWORD='change-me' flask create-user <username> --admin