minimost (App Factory)
minimost
Flask application factory for the MiniMost chat platform.
This module is the primary entry point for the MiniMost application. It exposes
create_app(), which constructs a fully-configured flask.Flask
instance ready to serve HTTP requests.
Typical usage in development:
from minimost import create_app
app = create_app()
app.run(host="127.0.0.1", port=5000)
Typical usage with a WSGI server such as Gunicorn:
gunicorn "minimost:create_app()" --config gunicorn.conf.py
Module-level attributes
- _APP_VERSIONstr
The package version string, resolved once at import time by
_read_version(). Available in every Jinja2 template as{{ app_version }}.
- minimost._read_version() str[source]
Return the package version string.
The version lives in
minimost._version, which ships inside the package and is therefore importable from an installed wheel and on every supported Python version (unlikeimportlib.metadata, which is 3.8+). The same module is the build-time source of truth via the dynamic-version config inpyproject.toml.If the module cannot be imported for any reason, the string
"unknown"is returned so the application always has a displayable value.- Returns:
The version string, for example
"0.1.0", or"unknown"if the version cannot be determined.- Return type:
- minimost._max_upload_size_mb() int[source]
Return the configured max upload size in MB (default 25).
- minimost._max_avatar_size_mb() int[source]
Return the configured max avatar size in MB (default 5).
- minimost._stun_port() int[source]
Return the configured STUN UDP port (default 3478).
The bundled STUN server lets LAN WebRTC peers gather a real-IP server-reflexive candidate, avoiding the mDNS
.localhost-candidate resolution that otherwise breaks calls on LANs without avahi/Bonjour.
- minimost._provision_tls(app) None[source]
Generate the self-signed TLS cert/key once, for any WSGI server.
Historically only the development server and the bundled Gunicorn config generated certificates, so running MiniMost under another WSGI server (waitress, uWSGI, mod_wsgi, …) silently meant no HTTPS — and therefore no voice/video calling. Doing it here means any server that loads
minimost:create_app()gets certificates provisioned, with no server-specific glue.Generation is idempotent (see
minimost.certs.ensure_certs()) and the resolved paths are stored inapp.config['TLS_CERT_FILE']and['TLS_KEY_FILE']so a launcher can point its TLS listener at them. Note that generating the files does not terminate TLS — the WSGI server still has to be configured to serve HTTPS using these paths.Set
MINIMOST_SKIP_TLS=1to skip generation entirely, e.g. when TLS is terminated upstream by a reverse proxy, or under the test suite.- Parameters:
app – The Flask application whose config receives the cert paths.
- minimost.create_app()[source]
Create and configure the MiniMost Flask application.
This is the canonical application factory used by every execution path — the CLI entry point (
minimost.__main__), the Gunicorn WSGI configuration, and any test suite that imports the package.The factory performs the following steps in order:
Instantiate a
flask.Flaskapplication object.Provision the secret key — read from
secret.keyin the project root, generating a fresh 64-character hex token if the file does not exist. The secret key is required for Flask’s signed session cookies.Set upload limit to 16 MiB via
MAX_CONTENT_LENGTH. Requests that exceed this size are rejected by Flask before the route handler runs.Inject the version into every Jinja2 template context via a context processor, making
{{ app_version }}available in all templates.Register blueprints —
auth_bp,chat_bp, andpresence_bp.
The
auth.dbandpresence.dbdatabases are also initialised as a side effect of importingminimost.databaseandminimost.presenceat module load time.- Returns:
A configured
flask.Flaskapplication instance.- Return type:
Example:
app = create_app() with app.test_client() as client: response = client.get("/login") assert response.status_code == 200
- minimost._migrate_search_indexes() None[source]
Ensure the shared message database and its search index exist at boot.
init_messages_db()is idempotent and builds (then rebuilds, once) the FTS5 trigram index if it is missing, so calling it at startup transparently upgrades a database that predates the index. Runs once per worker at boot.
- minimost._start_cleanup_scheduler(interval_hours: int = 24, days: int = 30, message_days: int = 770, initial_delay_seconds: int = 5) None[source]
Start a daemon thread that periodically purges old upload files.
Runs
minimost.clean.delete_files_older_than()once shortly after startup and then every interval_hours hours. The thread is a daemon so it exits automatically when the server process shuts down — no teardown required.The retention period is read from the
"image_retention_days"key insettings.jsonat each run, so changes to the file take effect on the next scheduled cleanup without restarting the server. If the key is absent or the file cannot be read, days is used as the fallback.Two optional size caps are also honoured each run:
"max_upload_dir_size_mb"bounds the total size ofuploads/(oldest files deleted first), and"max_message_db_size_mb"bounds the sharedmessages.db(oldest messages deleted first). Either is disabled when its key is absent or non-positive.Multiple Gunicorn workers each start their own thread; concurrent runs are safe because
delete_files_older_than()toleratesFileNotFoundErroron files already removed by another worker.- Parameters:
interval_hours – Hours between cleanup runs. Defaults to
24.days – Fallback retention period in days if
settings.jsondoes not specify"image_retention_days". Defaults to30.message_days – Fallback retention period in days for messages if
settings.jsondoes not specify"message_retention_days".initial_delay_seconds – Seconds to wait after startup before the first cleanup run, giving the server time to finish booting. Defaults to
5.