Architecture

Last edited 2026-05-11 11:06 UTC · history · 10 views

Architecture

A 10,000-ft overview of how ANetBBS is wired up.

Processes

+---------------------+         +------------------------+
|  anetbbs-web        |         |  anetbbs-telnet        |
|  gunicorn+eventlet  |         |  asyncio listener      |
|  Flask app + sock.IO|         |  telnet/ssh/rlogin     |
+----------+----------+         +-----------+------------+
           |                                |
           |  SQLite (shared)               |
           +--------- data/anetbbs.db ------+
                                            |
                                  +---------+----------+
                                  |  anetbbs-mrc-bridge|
                                  |  MRC client (long  |
                                  |  poll)             |
                                  +--------------------+

Two main services (web, telnet), one secondary (mrc-bridge),
all sharing the same SQLite database. Cross-process signals (like
NodeSpy kick) go via DB flags polled by the other process.

Tech stack

Layer Choice
Web framework Flask 3 + Flask-Login + Flask-SocketIO
WSGI gunicorn + eventlet workers
Realtime Socket.IO (web) / asyncio (terminal)
DB SQLite via SQLAlchemy 2
Migrations "Auto-sweep" — read model metadata, ALTER TABLE for missing cols
Frontend Bootstrap 5, xterm.js, vanilla JS
Markdown python-markdown + bleach
RSS feedparser
ANSI custom CP437 helpers in anetbbs/core/ansi_ui.py

Repo layout

anetbbs-rebuilt/
  anetbbs/
    core/           session, ANSI, terminal protocols
    features/       BBS sub-systems (menus, doors, multinode...)
    web/            Flask blueprints (one per feature)
    wiki/           wiki renderer + slug + seed
    models.py       SQLAlchemy models (one file, ~2000 lines)
    web_app.py      Flask app factory
    config.py       env-driven config
  templates/        Jinja templates
  static/           images, css overrides
  data/             SQLite + uploads (runtime; gitignored)
  docs/             markdown docs served at /docs/
  deploy/           systemd units, sudoers, logrotate
  tools/            one-off scripts
  install.sh / update.sh

Auto-sweep migrations

web_app.py walks db.metadata.sorted_tables on startup. For each
model column the live DB is missing, it issues ALTER TABLE ADD COLUMN. New columns are added permissively (nullable, no default)
so the migration always succeeds on SQLite. ORM defaults apply for
new inserts.

This means: adding a column = bump the model, restart anetbbs-web,
done. No alembic incantations needed for the common case.