Skip to main content

Stop Hardcoding Credentials

Every IoT deployment needs connection strings, API keys, and passwords — but embedding them directly in your LoT code or route definitions creates security risks and makes your configuration impossible to reuse across environments. The Coreflux Broker solves this with built-in environment variable and secrets management.
  • Environment variables store non-sensitive configuration (hostnames, ports, URLs) in a plain-text .env file
  • Secrets store sensitive credentials (passwords, API keys, tokens) encrypted at rest with AES-256-GCM
Both are accessible from LoT Actions, Models, Routes, and broker CLI commands using a unified syntax — no external tools or services required.
Think of it like a vault and a notebook. Environment variables are the notebook — quick to read, easy to update, visible if someone opens the file. Secrets are the vault — locked with a key, encrypted on disk, only decrypted when the broker needs them at runtime.
Environment variables and secrets management is available from Coreflux Broker v1.9.3 and above.

When to Use Each

ScenarioUseWhy
Database host, port, nameEnvironment variableNon-sensitive, changes per environment
API base URLsEnvironment variableConfiguration that varies between dev/staging/prod
Feature flagsEnvironment variableSimple on/off toggles
Database passwordsSecretMust not be readable on disk
API keys and tokensSecretSensitive credentials
TLS passphrasesSecretSecurity-critical values

In This Page

SectionDescription
Config RootHow the broker resolves its configuration directory
Environment VariablesPlain-text configuration management
SecretsEncrypted credential storage
Using in LoTGET ENV, GET SECRET, KEEP, DELETE syntax
Using in RoutesReferencing env vars and secrets in route definitions
CLI CommandsManaging env vars and secrets via broker commands
DeploymentWindows, Linux, Docker, and Kubernetes setup
Resolution ReferenceQuick-reference tables for resolution order and syntax

Config Root

The broker builds its configuration root directory from two parts:
Config root = {CONFIG_PATH or AppDirectory} + /Coreflux
  • If the CONFIG_PATH environment variable is set, it is used as the base path
  • Otherwise, the application directory is used (e.g. /app in Docker, the executable’s folder on Windows/Linux)
  • /Coreflux is always appended automatically
For example, with CONFIG_PATH=/data, the config root becomes /data/Coreflux.

File Layout

The environment and secrets files live alongside the broker’s internal data under the config root:
{config_root}/
  .env                # Plain-text environment variables (key=value)
  secrets.json        # AES-256-GCM encrypted secrets
  secret.key          # Optional: encryption key (base64, 32 bytes)
  bin/                # Internal broker data (managed automatically)
  log/                # Log files
  stats/              # Statistics

Environment Variables

Storage

Environment variables are stored in plain text in {config_root}/.env using standard key=value format:
DB_HOST=postgres.example.com
DB_PORT=5432
API_BASE_URL=https://api.example.com
MQTT_BRIDGE_HOST=remote-broker.company.com

Resolution Order

When the broker resolves an environment variable (via GET ENV, route config, or CLI), it checks multiple sources in this order:
PrioritySourceDescription
1.env file (managed)Set via -setEnv or KEEP ENV. Persisted to disk.
2Process environmentDocker environment:, Kubernetes env:, or shell exports.
3User environmentOS user-level environment variables (non-Docker).
4Machine environmentOS machine-level environment variables (non-Docker).
If not found in any source, an empty string is returned.
This fallback chain means Docker environment: variables work even without a .env file — the broker picks them up from the process environment automatically.

Secrets

How Secrets Work

Secrets are encrypted at rest using AES-256-GCM and stored in {config_root}/secrets.json. Each secret entry contains the initialization vector, the encrypted value with authentication tag, and a creation timestamp:
{
  "DB_PASSWORD": {
    "IV": "base64...",
    "Value": "base64(ciphertext):base64(tag)",
    "Created": "2026-02-08T12:00:00Z"
  }
}
Secret values are only decrypted at runtime when accessed via GET SECRET or route configuration. They are never logged or displayed — even the -listSecrets command only shows secret names, never values.

Encryption Key

The broker resolves the encryption key in this order:
PrioritySourceNotes
1COREFLUX_SECRET_KEY env varBest for Docker/Kubernetes. Base64-encoded, 32 bytes.
2{config_root}/secret.key fileGood for mounted volumes. Base64-encoded, 32 bytes.
3Derived from machine GUIDAuto-generated fallback. Machine-specific — secrets become unreadable if moved to a different machine.

Generating a Key

Use OpenSSL to generate a cryptographically secure 32-byte key:
openssl rand -base64 32
# Example output: K7x2mN8pQ1rT5uW3yB6dF9hJ0kL4nP7sV2xZ8cG1eA=
If you use the derived key fallback (no explicit key), your secrets are tied to the specific machine. Moving the secrets.json file to another machine or container will make the secrets unreadable. Always use an explicit key for portable deployments.

Using in LoT

Environment variables and secrets can be read, written, and deleted from within LoT Actions, Models, and route configurations.

Reading Values

Use GET ENV to read an environment variable and GET SECRET to read an encrypted secret (decrypted at runtime):
-- Read configuration from environment
SET "myHost" WITH (GET ENV "DB_HOST")
SET "myPort" WITH (GET ENV "DB_PORT")

-- Read credentials from encrypted secrets
SET "dbPass" WITH (GET SECRET "DB_PASSWORD")
SET "apiKey" WITH (GET SECRET "API_KEY")

Persisting Values

Use KEEP ENV to save a new environment variable to the .env file, and KEEP SECRET to encrypt and store a new secret:
-- Save an environment variable (persisted to .env)
KEEP ENV "LAST_RUN" WITH TIMESTAMP "UTC"

-- Save an encrypted secret (persisted to secrets.json)
KEEP SECRET "API_KEY" WITH "sk-abc123"

Deleting Values

Use DELETE ENV and DELETE SECRET to remove values:
-- Remove an environment variable
DELETE ENV "OLD_CONFIG"

-- Remove a secret
DELETE SECRET "OLD_API_KEY"

Complete Example

This action reads database configuration from environment variables and credentials from secrets on broker startup, then reports the status:
DEFINE ACTION ConnectToDatabase
ON START DO
    -- Read connection settings from environment
    SET "host" WITH (GET ENV "DB_HOST")
    SET "port" WITH (GET ENV "DB_PORT")
    SET "dbName" WITH (GET ENV "DB_NAME")

    -- Read credentials from encrypted secrets
    SET "user" WITH (GET SECRET "DB_USER")
    SET "pass" WITH (GET SECRET "DB_PASSWORD")

    IF {host} == EMPTY THEN
        PUBLISH TOPIC "system/errors" WITH "DB_HOST not configured"
    ELSE
        PUBLISH TOPIC "system/status" WITH "Database configured: " + {host} + ":" + {port}

    -- Track when we last initialized
    KEEP ENV "LAST_DB_INIT" WITH TIMESTAMP "UTC"

Using in Routes

Environment variables and secrets can be referenced directly in route definitions, keeping connection details out of your LoT code.

Standard Syntax

Use GET ENV and GET SECRET in route configuration blocks to inject values at runtime:
DEFINE ROUTE MyDB WITH TYPE POSTGRESQL
    ADD SQL_CONFIG
        WITH SERVER GET ENV "DB_HOST"
        WITH PORT 5432
        WITH DATABASE GET ENV "DB_NAME"
        WITH USERNAME GET ENV "DB_USER"
        WITH PASSWORD GET SECRET "DB_PASSWORD"

Legacy Prefix Syntax

The ENV: and SECRET: prefix syntax is also supported for backward compatibility in route ADD CONFIG sections:
WITH SERVER ENV:DB_HOST
WITH PASSWORD SECRET:DB_PASSWORD

Event Query Placeholders

In route event queries (e.g. WITH QUERY), use curly-brace placeholders that are resolved at execution time:
ADD EVENT StoreReading
    WITH SOURCE_TOPIC "sensors/#"
    WITH QUERY "INSERT INTO readings (host, value) VALUES ('{env.DB_HOST}', '{payload}')"
PlaceholderResolves To
{env.NAME}Environment variable value
{secret.NAME}Decrypted secret value

CLI Commands

Manage environment variables and secrets at runtime by publishing commands to $SYS/Coreflux/Command using any MQTT client (such as MQTT Explorer).

Environment Variable Commands

CommandDescription
-setEnv NAME=valueSet an environment variable (persisted to .env file)
-removeEnv NAMERemove an environment variable
-listEnvList all managed environment variables
Publish these messages to $SYS/Coreflux/Command to manage environment variables:
# Set an environment variable
-setEnv DB_HOST=postgres.example.com

# List all environment variables
-listEnv

# Remove an environment variable
-removeEnv OLD_CONFIG

Secret Commands

CommandDescription
-setSecret NAME=valueSet a secret (encrypted and persisted to secrets.json)
-removeSecret NAMERemove a secret
-listSecretsList secret names (values are never shown)
Publish these messages to $SYS/Coreflux/Command to manage secrets:
# Set a secret
-setSecret DB_PASSWORD=my_secure_password

# List secret names
-listSecrets

# Remove a secret
-removeSecret OLD_API_KEY
Subscribe to $SYS/Coreflux/Command/Output to receive confirmation responses from commands.

Deployment

Set up environment variables and secrets across different deployment targets.
On Windows, the config root defaults to the broker’s executable directory + \Coreflux unless CONFIG_PATH is set.
1

Locate the Config Directory

If the broker is installed at C:\Coreflux\, the config root is C:\Coreflux\Coreflux\.To use a custom path, set the CONFIG_PATH system environment variable:
[Environment]::SetEnvironmentVariable("CONFIG_PATH", "C:\CorefluxData", "Machine")
The config root becomes C:\CorefluxData\Coreflux\.
2

Create the .env File

Create a .env file in the config root with your environment variables:
@"
DB_HOST=postgres.example.com
DB_PORT=5432
API_BASE_URL=https://api.example.com
"@ | Out-File -FilePath "C:\CorefluxData\Coreflux\.env" -Encoding UTF8
3

Generate an Encryption Key

Generate and save a secret.key file for encrypting secrets:
openssl rand -base64 32 > "C:\CorefluxData\Coreflux\secret.key"
4

Set Secrets After Start

Start the broker, then set secrets using any MQTT client (such as MQTT Explorer). Publish to $SYS/Coreflux/Command:
-setSecret DB_PASSWORD=my_secure_password
Subscribe to $SYS/Coreflux/Command/Output to confirm the secret was stored.

Best Practices

Never rely on the derived key fallback for production deployments. Always provide a COREFLUX_SECRET_KEY environment variable or a secret.key file. The derived key is machine-specific — if you migrate, scale, or recreate a container, your secrets become unreadable.
On Linux, restrict access to sensitive files to the broker’s service user only:
chmod 600 /data/Coreflux/.env
chmod 600 /data/Coreflux/secret.key
chmod 600 /data/Coreflux/secrets.json
Even for values that seem static (like a database port), use GET ENV so you can change configuration without redeploying LoT code. This makes your Actions and Routes portable across dev, staging, and production.
Always mount a persistent volume at {CONFIG_PATH}/Coreflux in Docker and Kubernetes. Without a volume, your .env, secrets.json, and all broker state are lost when the container stops.
Keep secret.key, secrets.json, and .env files out of Git. Add them to .gitignore and use your deployment pipeline to inject them at runtime.

Resolution Reference

Where Each Syntax Reads From

SyntaxWhere It WorksResolved By
GET ENV "NAME"Actions, Models, Route configs.env file, then process env fallback
GET SECRET "NAME"Actions, Models, Route configsDecrypts from secrets.json
ENV:NAMERoute ADD CONFIG sections onlySame as GET ENV
SECRET:NAMERoute ADD CONFIG sections onlySame as GET SECRET
{env.NAME}Event queries (WITH QUERY)Replaced at event execution time
{secret.NAME}Event queries (WITH QUERY)Replaced at event execution time

Encryption Key Resolution Order

PrioritySourceNotes
1COREFLUX_SECRET_KEY env varBest for Docker/Kubernetes. Base64-encoded, 32 bytes.
2{config_root}/secret.key fileGood for mounted volumes. Base64-encoded, 32 bytes.
3Derived from machine GUIDAuto-generated fallback. Machine-specific — secrets won’t decrypt on a different machine.

GetEnv Resolution Order

PrioritySourceNotes
1.env file (managed)Set via -setEnv or KEEP ENV. Persisted to disk.
2Process environmentDocker environment:, Kubernetes env:, or shell exports.
3User environmentOS user-level env vars (non-Docker).
4Machine environmentOS machine-level env vars (non-Docker).

Next Steps