Every EPISODIC_* variable is optional; each entry point
works fine with the equivalent argument passed explicitly instead.
Environment variables exist so an operator can configure a running
instance (a systemd unit, a Docker container) without
editing R code - set them once where the instance runs, and every entry
point that falls back to them picks the setting up automatically.
| Variable | Used by | Meaning |
|---|---|---|
EPISODIC_DB |
episodic_run_app(), episodic_add_user()
(db_path argument) |
Path to the instance’s SQLite database, or a mysql://
DSN pointing at a MariaDB/MySQL database instead - see “Database
backend” above. |
EPISODIC_LANGUAGE |
every lang argument - episodic_run_app(),
episodic_demo(), and every renderer beneath them |
Dashboard/report language: en, ar,
nl, fr, de, hi,
zh, or es, or one of the regional variants
en-US and es-419 (Latin American Spanish).
en is British English and es is Spain’s
Spanish, so en-GB and es-ES name those exactly
and are accepted as such. Case and separator do not matter
(en_us is en-US). Defaults to en
if unset. A region EpiSODIC does not ship falls back to the language
itself, with a warning saying so once (nl-BE renders in
Dutch); anything else falls back to en with a warning,
once, not on every render. Also sets the document’s lang
and dir, so Arabic renders right to left. Fixed for the
whole running app - there is no in-app language switcher. |
EPISODIC_CONFIG |
episodic_run_cron() (episodic_config_path
argument), episodic_run_app()
|
Path to an instance override of configuration (pathogen thresholds,
same_place/rare_trigger/Farrington settings,
notification channels, and
access:),
overlaid key-by-key on the shipped inst/config/episodic_default_config.yaml.
Set to a path that does not exist, or to a file that is not valid YAML,
this stops with an error rather than falling back to the defaults; every
key it sets is checked against the shipped defaults, so a misspelled key
or a value of the wrong type is named rather than silently ignored. See
Tuning
detection for your catchment for the complete reference
table of tunable keys, and Deployment’s
“Opening the app to anonymous visitors” for
access:. |
EPISODIC_PATHOGEN_CONFIG |
episodic_run_cron() (pathogen_config_path
argument) |
Path to an instance override of per-pathogen parameters (episode
length, case-free days, severity weight, MEM mode, serial interval, and
the rest), overlaid row-by-row on the shipped inst/config/episodic_default_pathogen_config.csv.
Write a CSV with a pathogen column and only the columns you
want to change; non-empty values override the shipped default for that
pathogen and column, empty cells keep it, and pathogens not in your file
keep their shipped row entirely. New pathogens are added. Set to a path
that does not exist, this stops with an error. See Tuning
detection for your catchment for the column reference. |
EPISODIC_STYLE |
episodic_palette() (palette_config_path
argument) |
Path to an instance override of the UI colour palette (including the
five severity_* roles that colour verdicts and MEM
intensity bands alike) and typography (font,
font_size_base), overlaid key-by-key on the shipped inst/config/episodic_default_style.yaml.
The same palette styles the outbreak reports and the emails EpiSODIC
sends. Each value is checked: a colour must be a quoted hex colour,
font a CSS font-family stack and
font_size_base a CSS length. A value that fails keeps the
shipped value for that role only, and a path that does not exist or a
file that is not valid YAML keeps the whole shipped palette - neither
stops the dashboard, a report or an email, and both are shown on the
Info screen, written to every run’s log and raised once as a warning.
Deliberately separate from EPISODIC_CONFIG: colour and
typography are display concerns, never part of the
detection-reproducibility guarantee. |
EPISODIC_GEO_DATA |
episodic_geo_source_resolve() (path
argument) |
Path to an .rds file holding your own geographic
reference data (an sf object with
pc/geometry columns) for the choropleth map -
any country, any area unit. There is no default: with this unset the
dashboard shows its bar-chart fallback instead of a map, since a default
map is a default country. EpiSODIC does bundle one worked
example (Dutch postcodes) that episodic_demo() points this
at. See Getting
your data in’s “Geographic reference data” section. |
EPISODIC_GEO_DATA_OVERLAY |
episodic_geo_overlay_resolve() (path
argument) |
Path to an .rds file holding an optional region-outline
overlay (an sf object with just a geometry
column), drawn on top of the choropleth. No default. See Getting
your data in’s “Geographic reference data” section. |
EPISODIC_PC_PROVINCE_MAP |
episodic_pc_to_province() (path
argument) |
Path to a CSV (pc, province_code columns)
mapping your postcodes to provinces/states/regions, for L4 stream
detection and for naming the province beside each postcode in the
dashboard. Unset, no postcode resolves to a province and L4 simply has
nothing to detect on - there is no built-in rule, because deriving a
province from a postcode is country-specific; set but unusable (no such
file, unreadable, no rows, wrong columns, or a repeated pc)
stops the run and says which of those it is, rather than falling back.
See Getting
your data in’s “Geographic reference data” section. |
EPISODIC_QUARTO_REPORT |
episodic_report_render() (qmd_path
argument) |
Path to an operator’s own Quarto report template, overriding the
shipped inst/report/episodic_default_report.qmd.
Set to a path that does not exist, this stops with an error rather than
silently sending reports out under EpiSODIC’s own layout instead of
yours. See “Custom report templates” above. |
EPISODIC_MAIL_TEMPLATE_NEW_CLUSTERS |
episodic_run_cron(),
episodic_mail_template_preview()
|
Path to an operator’s own Quarto (.qmd) template for
the body of the email sent when a run detects new clusters. Unset, the
built-in body is used. Only the email channels (smtp,
sendmail, microsoft365) are affected; ntfy,
Teams and Slack keep their own messages. A template that cannot be used
(no such file, not a .qmd, Quarto not installed, or a
render that fails) never costs an alert: the email goes out with the
built-in body, and the run log, the Info screen and
episodic_notify_test() say why. See Notifications’s
“Your own email layout”. |
EPISODIC_MAIL_TEMPLATE_REPORT |
episodic_run_cron(),
episodic_mail_template_preview()
|
The same, for the body of the email a scheduled outbreak report is attached to. See Scheduled reports. |
None of these need to be set to run the demo -
episodic_demo() uses a temporary SQLite file and the
shipped defaults, and writes its own geography and an illustrative
pathogen overlay beside it. See Deployment
for EPISODIC_DB and
EPISODIC_CONFIG/EPISODIC_STYLE in context
(database backend, custom report templates), and Getting
your data in’s “Geographic reference data” section for the
detail behind EPISODIC_GEO_DATA and
EPISODIC_GEO_DATA_OVERLAY.
Checking what they actually delivered
Setting a variable and seeing nothing change on screen has, until now, been indistinguishable from setting it wrongly. The dashboard’s Info screen carries a “Reference data” panel that resolves each of these live and reports, per variable, whether the instance’s own file is in use, the shipped default is standing in, nothing is configured, the file was configured and could not be used (with the reason), or an optional package the feature needs is missing - alongside what it put into the app: how many areas the map geometry holds, how many postcodes the province mapping maps and to how many provinces, and how many of the distinct postcodes in your own case data resolve to a province.
That last figure is the one worth reading first when a province is not appearing where you expect: a mapping read successfully but matching none of your postcodes looks, on every other screen, exactly like a mapping that was never read.
The resolved file paths are shown only to a signed-in user. By
default the Info screen itself needs no sign-in, so the statuses and
counts - the part that answers “is my file being used” - are readable
without one, while the paths, which say more about the machine than a
visitor needs, are not. On an instance with
access.require_login set the whole screen is behind the
sign-in like every other, so a signed-in reader sees the paths there
too.