Skip to main content

Environment variables

Every setting in the configuration file has an environment equivalent. The environment wins over the file, and the command-line flags win over the environment — which makes it easy to keep a base configuration in a file and override one value per deployment in a compose file.

VariableEquivalentExample
PROBEGLASS_CONFIG—/etc/probeglass/probeglass.yaml
PROBEGLASS_LISTENlisten:8080
PROBEGLASS_DATA_DIRdata_dir/data
PROBEGLASS_DBdb_path/data/probeglass.db
PROBEGLASS_BASE_URLbase_urlhttps://probeglass.lan
PROBEGLASS_LOG_LEVELlog_leveldebug
PROBEGLASS_LOG_FORMATlog_formatjson
PROBEGLASS_TRUST_PROXYtrust_proxytrue
PROBEGLASS_RETENTION_RAWretention.raw7d
PROBEGLASS_RETENTION_HOURLYretention.hourly90d
PROBEGLASS_ADMIN_PASSWORD—see below

PROBEGLASS_CONFIG is special: it names the configuration file rather than overriding a setting inside it. If it points at a file that does not exist, that is an error — a typo in a mount path should not silently leave you running on defaults.

One thing is set by the environment and has no counterpart in the file at all: which user the container runs as. That is PUID, PGID and UMASK, below.

note

PROBEGLASS_DB maps to the db_path key, not to db. The variable name is shorter than the key on purpose: it is the one that gets typed into a docker run line.

PROBEGLASS_ADMIN_PASSWORD​

Bootstraps the dashboard password on a fresh database. It is read only when no password exists yet and ignored on every later start — it does not override an existing password, so leaving it in a compose file is not a back door.

This is the intended way to deploy ProbeGlass unattended:

services:
probeglass:
image: ghcr.io/j000k3r/probeglass:0.2.1
restart: unless-stopped
ports: ["8080:8080"]
volumes: ["probeglass-data:/data"]
cap_add: ["NET_RAW"]
environment:
PROBEGLASS_ADMIN_PASSWORD: ${PROBEGLASS_ADMIN_PASSWORD:?set it in .env}
PROBEGLASS_BASE_URL: http://probeglass.lan:8080
PROBEGLASS_LOG_FORMAT: json
PROBEGLASS_RETENTION_RAW: 14d
volumes:
probeglass-data:

Compose expands ${VAR:?message} from the shell environment or a .env file next to the compose file, and refuses to start if it is unset — which is the behaviour you want for a password.

PUID, PGID and UMASK​

These three have no PROBEGLASS_ prefix and no line in the configuration file, and that is not an oversight: they are not settings of the daemon. They say which user the container should run as, and there is no equivalent in a YAML file for a decision the kernel has to be asked for.

VariableDefaultMeaning
PUID500the user the daemon becomes
PGID500the group it becomes
UMASK022the permission mask for files it creates

The container starts as root, takes its data directory over and then becomes PUID:PGID, before it opens the database or binds a port. That is what makes a first install work without a chown: a bind mount keeps the ownership of the host folder, and the platforms this gets installed on create that appdata folder as root — a folder that only root may hand to somebody else. Security explains the root moment in full.

The practical consequences:

  • They only work when the process starts as root. With --user, with user: in compose, or on a rootless runtime, the daemon is not root, cannot claim the folder and cannot change user, so it ignores the three and says so in one log line. A value that is quietly ignored is the failure these variables exist to remove.
  • Outside a container they apply to the same rule, not to the same paths. Run the binary as yourself and it runs as you; run it as root — sudo, a systemd unit with User=root — and it takes the data directory over and drops exactly like the container does, so PUID=0 is how you keep root there.
  • A value that cannot be parsed stops the start when the process is root — the same treatment PROBEGLASS_LOG_LEVEL gets. PUID=abc is an error rather than a silent fall back to 500.
  • PUID=0 and PGID=0 mean "stay root", for the whole run. It is supported and it is logged at startup, and it is not recommended: it gives up the property that everything a sensor or a request can reach runs unprivileged.
  • Quote UMASK: UMASK: "022", not UMASK: 022. YAML reads an unquoted 022 as the number 18, and 0018 is not a mask anybody typed — so the daemon refuses it instead of running with it. 022, 0022 and 22 all mean the same thing when they arrive as text.
services:
probeglass:
image: ghcr.io/j000k3r/probeglass:0.2.1
volumes: ["/srv/appdata/probeglass:/data"]
cap_add: ["NET_RAW"]
environment:
PUID: 1000
PGID: 1000
UMASK: "022"

Durations​

PROBEGLASS_RETENTION_RAW and PROBEGLASS_RETENTION_HOURLY accept:

FormExampleMeaning
Go duration30s, 5m, 2hThe usual
Day7d, 1.5d7 days, 36 hours
Week2w14 days
Bare number3600Seconds

The day and week suffixes exist because retention is the one place where 168h is a worse way of writing 7d, and a monitoring tool whose retention setting is unreadable is a monitoring tool with the wrong retention setting.

Invalid values​

An environment variable that cannot be parsed is a startup error naming the variable — not a silent fallback to the default:

probeglass: PROBEGLASS_RETENTION_RAW: invalid duration "seven days": ...

The process exits. A monitor that comes up with a different retention policy than the one you configured, and does not say so, is worse than one that does not come up at all.

Precedence, in one example​

Given a file with log_level: info and:

PROBEGLASS_LOG_LEVEL=warn probeglass serve -log-level debug

the effective level is debug: flags beat environment, environment beats file, file beats defaults.

Next steps​