- Rename package fablednetmon → fabledscryer throughout - Multi-dashboard: ownership, per-user defaults, HTMX edit (add/remove/reorder) - Read-only share tokens scoped to individual dashboards - Dashboard edit is HTMX-driven (no page reloads) - Plugin management system: remote catalog, download/install, hot-reload, in-app restart - plugin_index.py: fetch/cache remote index.yaml; default URL → bvandeusen/fabledscryer-plugins - plugin_manager.py: download_and_install_plugin, hot_reload_plugin, restart_app - ZIP extraction handles GitHub archive formats (name-v1.0.0/, name-main/) - Settings split into tabbed sections: General, Notifications, Ansible, Plugins - Plugins tab: catalog browser (HTMX), install/activate/update/restart actions - UI/branding: dark palette (#07071a), crystal ball SVG logo, animated star field, Libertinus Serif applied to headings, nav, labels, and section titles - Widget registry (core/widgets.py) for dashboard plugin integration - UPS widget.html (dashboard card) and settings/_tabs.html include - Migrations 0005–0008: dashboards, is_default, ownership, share tokens - docs/plugins/: writing-a-plugin.md updated with publishing guide, index.yaml.example template for fabledscryer-plugins repo Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
4.1 KiB
Configuration
Fabled Scryer uses a two-layer configuration system. Only the bare minimum needed to boot lives in files or environment variables. Everything else is stored in the database and managed through the Settings UI.
Bootstrap Config (File / Env Vars)
These three values are read at startup from config.yaml and/or environment variables:
| Key | Env var | Default | Description |
|---|---|---|---|
database.url |
FABLEDSCRYER_DATABASE_URL |
— | PostgreSQL async URL. Required. |
secret_key |
FABLEDSCRYER_SECRET_KEY |
auto-generated | Flask/Quart session signing key. Auto-generated and saved to /data/secret.key if not set. |
plugin_dir |
FABLEDSCRYER_PLUGIN_DIR |
plugins |
Path to the plugins directory. |
Resolution order for database_url: env var FABLEDSCRYER_DATABASE_URL → env var FABLEDSCRYER_DATABASE__URL (legacy double-underscore) → database.url in config.yaml.
Resolution order for secret_key: env var FABLEDSCRYER_SECRET_KEY → secret_key in config.yaml → /data/secret.key file → auto-generate and write to /data/secret.key.
Minimal config.yaml
database:
url: "postgresql+asyncpg://user:password@localhost/fabledscryer"
Minimal env-only setup (Docker)
FABLEDSCRYER_DATABASE_URL=postgresql+asyncpg://user:password@db/fabledscryer
A .env file is loaded automatically if present.
App Settings (Database-backed)
All runtime settings are stored in the app_settings table and editable through the web UI at /settings/. They are loaded into app.config at startup.
All Settings and Defaults
| Key | Default | Description |
|---|---|---|
session.lifetime_hours |
8 |
How long a login session lasts |
data.retention_days |
90 |
How many days of ping/DNS/metric/ansible history to keep |
monitors.poll_interval_seconds |
60 |
How often ping and DNS checks run |
smtp.host |
"" |
SMTP server hostname |
smtp.port |
587 |
SMTP server port |
smtp.tls |
true |
Use STARTTLS |
smtp.username |
"" |
SMTP login username |
smtp.password |
"" |
SMTP login password |
smtp.recipients |
[] |
List of email addresses to notify |
webhook.url |
"" |
Webhook POST destination URL |
webhook.template |
see below | Jinja2 JSON template for webhook body |
ansible.sources |
[] |
List of playbook source definitions |
ping.threshold.good_ms |
50 |
Latency below this is shown green in the ping UI |
ping.threshold.warn_ms |
200 |
Latency below this is shown yellow; above is orange |
Default webhook template:
{"content": "**{{ alert.state }}** — {{ alert.resource }} — {{ alert.rule_name }} ({{ alert.metric }} = {{ alert.value }})"}
Reading and Writing Settings in Code
from fabledscryer.core.settings import get_setting, set_setting
# Read
async with current_app.db_sessionmaker() as session:
host = await get_setting(session, "smtp.host")
# Write (must be inside a transaction)
async with current_app.db_sessionmaker() as session:
async with session.begin():
await set_setting(session, "smtp.host", "mail.example.com")
get_setting() returns the stored value or the default from DEFAULTS if the key has never been set.
The DEFAULTS Dict
fabledscryer/core/settings.py contains the DEFAULTS dict — the canonical list of all recognised settings and their default values. Add new settings here to make them recognised by get_all_settings() and the settings UI.
app.config Keys
After startup, app.config contains these additional keys (in addition to standard Quart keys):
| Key | Type | Source |
|---|---|---|
DATABASE_URL |
str | Bootstrap |
PLUGIN_DIR |
str | Bootstrap |
SESSION_LIFETIME_HOURS |
int | DB settings |
DATA_RETENTION_DAYS |
int | DB settings |
MONITORS_POLL_INTERVAL |
int | DB settings |
SMTP |
dict | DB settings, via to_smtp_cfg() |
WEBHOOK |
dict | DB settings, via to_webhook_cfg() |
ANSIBLE |
dict | DB settings, via to_ansible_cfg() |
PLUGINS |
dict | DB settings + plugin.yaml defaults, keyed by plugin name |