Skip to main content

Environment Variables

Load option values from environment variables to support containerized deployments, CI/CD pipelines, and system-wide configurations.

Basic Setup

Configure environment variable support by setting an optional prefix:

int main(int argc, char **argv)
{
argus_t argus = argus_init(options, "my_app", "1.0.0");

// Optional: set prefix for all environment variables
argus.env_prefix = "APP";

if (argus_parse(&argus, argc, argv) != ARGUS_SUCCESS)
return 1;

argus_free(&argus);
return 0;
}

Environment Variable Types

Specify exact environment variable names:

ARGUS_OPTIONS(
options,
HELP_OPTION(),

// Will look for APP_HOST (with prefix) or HOST (without prefix)
OPTION_STRING('H', "host", HELP("Server hostname"),
ENV_VAR("HOST"), DEFAULT("localhost")),

// Will look for APP_PORT (with prefix) or PORT (without prefix)
OPTION_INT('p', "port", HELP("Server port"),
ENV_VAR("PORT"), DEFAULT(8080)),

// Will look for APP_DATABASE_URL regardless of prefix setting
OPTION_STRING('d', "database", HELP("Database URL"),
ENV_VAR("DATABASE_URL")),
)

Environment usage:

# With prefix "APP"
export APP_HOST=production.example.com
export APP_PORT=9000
export APP_DATABASE_URL=postgres://user:pass@db/app

# Without prefix
export HOST=localhost
export PORT=8080
export DATABASE_URL=sqlite:///local.db

./my_app

Precedence Control

Control whether environment variables provide defaults or override command-line options:

Environment variables provide fallback values when command-line options aren't specified:

ARGUS_OPTIONS(
options,
OPTION_STRING('h', "host", HELP("Server host"),
ENV_VAR("HOST"), DEFAULT("localhost")),

OPTION_INT('p', "port", HELP("Server port"),
ENV_VAR("PORT"), DEFAULT(8080)),
)

Precedence order:

  1. Command-line option (highest priority)
  2. Environment variable
  3. Default value (lowest priority)

Example:

export APP_HOST=env-server.com
export APP_PORT=9000

./my_app # Uses env values: env-server.com:9000
./my_app --host cli-server.com # Uses: cli-server.com:9000 (CLI overrides env)
./my_app --port 8080 # Uses: env-server.com:8080 (CLI overrides env)

Type Conversion

Environment variables (always strings) are automatically converted to option types:

ARGUS_OPTIONS(
options,
OPTION_STRING('h', "host", ENV_VAR("HOST")),
OPTION_INT('p', "port", ENV_VAR("PORT")),
OPTION_FLOAT('r', "rate", ENV_VAR("RATE")),
OPTION_BOOL('d', "debug", ENV_VAR("DEBUG")),
OPTION_FLAG('v', "verbose", ENV_VAR("VERBOSE")),
)

Environment values:

export APP_HOST=example.com        # String: used as-is
export APP_PORT=8080 # Integer: parsed as 8080
export APP_RATE=0.75 # Float: parsed as 0.75
export APP_DEBUG=true # Boolean: parsed as true
export APP_VERBOSE=1 # Flag: parsed as true

Complete Examples

#include "argus.h"

ARGUS_OPTIONS(
options,
HELP_OPTION(),
VERSION_OPTION(),

// Connection settings
OPTION_STRING('H', "host", HELP("Server hostname"),
ENV_VAR("HOST"), DEFAULT("localhost")),

OPTION_INT('p', "port", HELP("Server port"),
ENV_VAR("PORT"), DEFAULT(8080)),

// Database configuration
OPTION_STRING('d', "database", HELP("Database URL"),
ENV_VAR("DATABASE_URL"), FLAGS(FLAG_NO_ENV_PREFIX)),

// System settings (auto-generated names)
OPTION_STRING('\0', "log-level", HELP("Log level"),
FLAGS(FLAG_AUTO_ENV), DEFAULT("info")),

OPTION_INT('\0', "worker-threads", HELP("Number of worker threads"),
FLAGS(FLAG_AUTO_ENV), DEFAULT(4)),

// Security settings (override mode)
OPTION_BOOL('\0', "ssl-verify", HELP("Verify SSL certificates"),
ENV_VAR("SSL_VERIFY"), FLAGS(FLAG_ENV_OVERRIDE),
DEFAULT(true)),
)

int main(int argc, char **argv)
{
argus_t argus = argus_init(options, "webapp", "1.0.0");
argus.env_prefix = "WEBAPP";

if (argus_parse(&argus, argc, argv) != ARGUS_SUCCESS)
return 1;

// Access configuration
const char *host = argus_get(&argus, "host").as_string;
int port = argus_get(&argus, "port").as_int;
const char *database = argus_get(&argus, "database").as_string;
const char *log_level = argus_get(&argus, "log-level").as_string;

printf("Starting webapp on %s:%d\n", host, port);
printf("Database: %s\n", database ? database : "not configured");
printf("Log level: %s\n", log_level);

argus_free(&argus);
return 0;
}

Environment setup:

# Production environment
export WEBAPP_HOST=0.0.0.0
export WEBAPP_PORT=443
export DATABASE_URL=postgres://prod-db/webapp
export WEBAPP_LOG_LEVEL=warn
export WEBAPP_WORKER_THREADS=8
export WEBAPP_SSL_VERIFY=true

./webapp

Best Practices

✅ Good Practices

// 1. Use consistent naming with prefixes
argus.env_prefix = "MYAPP";

// 2. Provide sensible defaults
OPTION_STRING('h', "host", ENV_VAR("HOST"), DEFAULT("localhost"))

// 3. Use FLAG_NO_ENV_PREFIX for standard system variables
OPTION_STRING('\0', "home", ENV_VAR("HOME"), FLAGS(FLAG_NO_ENV_PREFIX))

// 4. Use override mode for security-critical settings
OPTION_BOOL('\0', "ssl-verify", ENV_VAR("SSL_VERIFY"),
FLAGS(FLAG_ENV_OVERRIDE), DEFAULT(true))

// 5. Document environment variables in help text
OPTION_STRING('d', "database", HELP("Database URL (env: DATABASE_URL)"),
ENV_VAR("DATABASE_URL"))

❌ Avoid These Patterns

// ❌ Don't use confusing environment variable names
OPTION_STRING('p', "port", ENV_VAR("SERVER_PORT_NUMBER_CONFIG"))

// ❌ Don't override critical security settings by default
OPTION_BOOL('\0', "skip-auth", ENV_VAR("SKIP_AUTH"),
FLAGS(FLAG_ENV_OVERRIDE)) // Dangerous!

// ❌ Don't forget to set prefix consistently
// Set argus.env_prefix once, not per option

Documentation

Argus automatically displays environment variables in the help output. Simply define your options and the help system will show the corresponding environment variables:

ARGUS_OPTIONS(
options,
HELP_OPTION(),

OPTION_STRING('h', "host", HELP("Server hostname"),
ENV_VAR("HOST"), DEFAULT("localhost")),

OPTION_INT('t', "timeout", HELP("Timeout in seconds"),
ENV_VAR("FORCE_TIMEOUT"), FLAGS(FLAG_ENV_OVERRIDE)),

OPTION_INT('p', "port", HELP("Server port"),
FLAGS(FLAG_AUTO_ENV), DEFAULT(8080)),
)

Automatic help output:

Options:
-h, --host <STR> - Server hostname (default: "localhost", env:
APP_HOST)
-t, --timeout <NUM> - Timeout in seconds (env: APP_FORCE_TIMEOUT)
-p, --port <NUM> - Server port (default: 8080, env: APP_PORT)

Environment Variable Loading Process

Argus loads environment variables in this order:

  1. Parse command-line arguments - Process all CLI options first
  2. Load environment variables - Check for environment values
  3. Apply precedence rules - Respect FLAG_ENV_OVERRIDE settings
  4. Apply defaults - Use default values for unset options
  5. Run validation - Validate all final values

Integration with Other Features

Environment variables work seamlessly with other Argus features:

ARGUS_OPTIONS(
options,
// Environment + validation
OPTION_INT('p', "port", ENV_VAR("PORT"),
VALIDATOR(V_RANGE(1, 65535)), DEFAULT(8080)),

// Environment + choices
OPTION_STRING('l', "level", ENV_VAR("LOG_LEVEL"),
VALIDATOR(V_CHOICE_STR("debug", "info", "warn", "error")),
DEFAULT("info")),

// Environment + collections
OPTION_ARRAY_STRING('t', "tags", ENV_VAR("TAGS"),
VALIDATOR(V_COUNT(1, 10))),
)

What's Next?

Debugging Environment Variables

Use printenv | grep APP_ to see what environment variables are set with your prefix, and add verbose logging to verify which values are being loaded.