Cameleer

Configuration: properties, profiles and environment variables

Cameleer reads its configuration the way Camel Main and Spring Boot do: application.properties or application.yaml, profile files such as application-prod.properties, CAMEL_* environment variables, and --prop on the command line, with later sources winning. Every key is a placeholder routes can use ({{orders.target}}), and camel.main.*, camel.server.*, camel.ssl.*, camel.datasource.* and camel.component.* keys configure the runtime without code.

Applies to: the cameleer CLI, the Docker image and cameleer_main::Main in Rust ยท Apache Camel: Camel Main configuration

Where configuration comes from

Sources are merged in this order; a later source overrides an earlier one:

ordersourcenotes
1application.properties, application.yaml, application.ymlfrom the current directory, or the file given with --properties (which replaces them)
2application-<profile>.properties / .yaml / .ymlnext to the first file, for each active profile
3%<profile>.key=value entries and YAML documents with spring.config.activate.on-profileinside the files above
4environment variables starting with CAMEL_see Environment variables
5--prop key=value and the CLI flags (--port, --name, --log-level, ...)also Main::set_property in Rust
6defaults for keys still unsetfor example --mcp sets camel.server.mcp-tags=*,untagged only if you did not

Keys match without regard to case, dashes and underscores: camel.main.durationMaxSeconds, camel.main.duration-max-seconds and CAMEL_MAIN_DURATION_MAX_SECONDS are the same key. The Spring Boot and Quarkus spellings work too: camel.springboot.* and quarkus.camel.* are read as camel.main.*, and server.port or quarkus.http.port as camel.server.port when that is not set.

In the Docker image the working directory is /routes, so an application.properties in the mounted folder is read:

bash
docker run --rm -p 8080:8080 -v "$PWD:/routes:ro" pmsudhi/cameleer run /routes/orders.camel.yaml

application.properties and application.yaml

Either format works; YAML maps are flattened to dotted keys, lists to key[0] (and a list of plain values also to one comma-separated value):

properties
camel.main.name = orders
camel.server.port = 8080
orders.batch-size = 100
yaml
camel:
  main:
    name: orders
  server:
    port: 8080
orders:
  batch-size: 100

Profiles

A profile switches settings per environment. Activate one with cameleer run --profile prod, --dev (profile dev), the property camel.main.profile (also spring.profiles.active, quarkus.profile), the environment variable CAMEL_MAIN_PROFILE (also SPRING_PROFILES_ACTIVE, QUARKUS_PROFILE), or Main::set_profile in Rust. Several profiles are separated by commas. An active profile adds:

  • application-<profile>.properties (or .yaml, .yml) from the same folder;
  • Quarkus-style entries %<profile>.key=value in any file;
  • YAML documents with spring.config.activate.on-profile: <profile> (or spring.profiles).

The log says The following profiles are active: prod. A worked example is below.

Environment variables

Variables that start with CAMEL_ become properties and override the files:

variableproperty
CAMEL_MAIN_NAMEcamel.main.name
CAMEL_MAIN_DURATION_MAX_SECONDScamel.main.durationMaxSeconds (the same as camel.main.duration-max-seconds)
CAMEL_SERVER_PORTcamel.server.port
CAMEL_SERVER_MCP_REQUEST_STATE_KEYcamel.server.mcpRequestStateKey
CAMEL_COMPONENT_KAFKA_BROKERScamel.component.kafka.brokers
CAMEL_COMPONENT_PLATFORM_HTTP_PORTcamel.component.platform-http.port (a known scheme with a dash is matched)

The rule: drop CAMEL_, lowercase, the first part after camel. becomes a segment, and the rest is joined in camelCase; for CAMEL_COMPONENT_* the longest known component scheme is matched first. Because keys match loosely, camel.server.mcpRequestStateKey and camel.server.mcp-request-state-key are the same.

Any value can also read an environment variable directly with a placeholder, {{env:NAME}} or {{env:NAME:default}}, which is the usual way to pass secrets:

properties
camel.server.port = {{env:PORT:8080}}
camel.datasource.url = {{env:DB_URL}}

Other variables Cameleer reads:

variableeffect
CAMEL_LOG_LEVELlog level when nothing else sets one (TRACE, DEBUG, INFO, WARN, ERROR)
CAMEL_HOMEwhere cameleer ps, stop, log and the other local commands keep their status files
CAMEL_LOCAL_STATUSfalse turns those status files off (the Docker image sets it)
SSL_CERT_FILEthe CA bundle used as the system trust store; needed on Windows (FAQ)
TZ, TZDIRthe default time zone and an alternative zoneinfo directory
CAMEL_PROPERTY_<KEY>the value of a placeholder {{key}} that no source defines ({{orders.target}} reads CAMEL_PROPERTY_ORDERS_TARGET)

Placeholders

Every property can be used in routes and in other properties:

placeholdervalue
{{key}}the property key; startup fails if it is not defined
{{key:default}}the property, else default
{{env:NAME}}, {{env:NAME:default}}the environment variable
{{sys:NAME}}the environment variable (Java system properties don't exist here)
{{aws:secret}}, {{azure:secret}} and other functionssecrets from a vault: see cloud credentials

Placeholders inside camel.main.* and camel.server.* values are resolved before the runtime reads them, so camel.server.port={{env:PORT:8080}} works on Cloud Run, Knative and anywhere else that passes the port in PORT. cameleer validate reports a placeholder no source defines as unresolved-placeholder.

The keys

camel.main.*: the runtime

keydefaulteffect
camel.main.namethe context's namethe integration's name in logs, cameleer ps and MCP serverInfo
camel.main.profilenonethe active profile(s)
camel.main.routes-include-patternroute files on the command linemore route files, comma-separated globs such as routes/*.yaml
camel.main.kamelet-locations./kameletsfolders with Kamelets to load (alias camel.component.kamelet.location)
camel.main.duration-max-secondsnonestop after this many seconds
camel.main.duration-max-messagesnonestop after this many messages have completed (a run-once job, or a Kubernetes CronJob)
camel.main.duration-max-idle-secondsnonestop after this many seconds without a message
camel.main.shutdown-timeout45seconds to wait for in-flight messages at shutdown
camel.main.log-levelINFOTRACE, DEBUG, INFO, WARN, ERROR (also logging.level.root)
camel.main.dev-reloadfalsereload route files when they change (--dev)
camel.main.tracingfalselog every message at every step (--trace)
camel.main.backlog-tracingfalsekeep recent messages for cameleer trace and /q/dev/trace
camel.main.message-historyfalserecord the steps each message passed
camel.main.jmxManagementStatisticsLevelRoutesOnlyExtended, Default, RoutesOnly or Off: how much per-step statistics to keep
camel.main.startup-recordernonelogging logs how long each part of startup took
camel.main.route-controller-supervise-enabledfalserestart routes that fail to start, with back-off (also camel.routecontroller.enabled)
camel.main.route-controller-initial-delay, -back-off-delay, -back-off-max-attemptsthe supervising route controller's timing (also camel.routecontroller.*)
camel.main.lambda-handlerdirect:lambdaon AWS Lambda, the endpoint non-HTTP events go to (deployment)

camel.server.*: the shared HTTP server, health, metrics and consoles

platform-http and REST routes, the management endpoints and the MCP server share one HTTP server.

keydefaulteffect
camel.server.port8080the port (0 picks a free one)
camel.server.host0.0.0.0the bind address
camel.server.enabledfalsestart the management endpoints below (needed with any of the next three)
camel.server.healthCheckEnabledfalseGET /q/health, /q/health/ready, /q/health/live (200 when up, 503 when down)
camel.server.metricsEnabledfalseGET /q/metrics in Prometheus text format
camel.server.devConsoleEnabledfalseGET /q/dev/* consoles and POST /q/dev/route/{id}/start|stop|suspend|resume|reset-stats
camel.server.sslEnabledfalseserve every platform-http endpoint over HTTPS
camel.server.ssl.keyStore, .certFile and .keyFile, .keystorePassword, ...the server certificate (the same keys as camel.ssl.* below)
camel.server.useGlobalSslContextParametersfalsetake the server certificate from camel.ssl.* instead
camel.server.mcp-*the MCP server: see MCP server configuration

cameleer run --console turns on camel.server.enabled, health, metrics and the dev console in one flag. With camel.server.sslEnabled=true the management endpoints, /q/attestation and the MCP server are HTTPS on the same port as the routes.

camel.management.*: a separate management port

keydefaulteffect
camel.management.enabledfalseserve /q/health, /q/metrics and /q/dev on their own plain-HTTP port instead of camel.server.port
camel.management.port9876the management port
camel.management.hostcamel.server.hostthe bind address
camel.management.healthCheckEnabled, metricsEnabled, devConsoleEnabledfalsewhich endpoints (the camel.server.* switches count as well)

See Observability.

camel.ssl.*: global TLS

Endpoints with useGlobalSslContextParameters=true, and components that fall back to the global parameters, use these. They apply only with camel.ssl.enabled=true.

keyeffect
camel.ssl.enabledturn the global parameters on
camel.ssl.keyStoreour certificate and key: a PKCS12 file, a Java keystore (JKS) or a PEM file with the chain and key
camel.ssl.certFile and camel.ssl.keyFilethe same as two PEM files
camel.ssl.keystorePassword, camel.ssl.keyPassword, camel.ssl.keyStoreType, camel.ssl.certAliaskey store password, key password, type (PKCS12, JKS, PEM) and which entry to use
camel.ssl.trustStoretrusted CA certificates (PEM files, comma-separated, or a PKCS12/JKS file with trustStorePassword, trustStoreType)
camel.ssl.useSystemTrustStorealso trust the system store
camel.ssl.clientAuthenticationservers: NONE, WANT or REQUIRE client certificates
camel.ssl.secureSocketProtocol, minVersion, maxVersionTLS versions (TLSv1.2, TLSv1.3)
camel.ssl.hostnameVerificationcheck the server's name (on by default)
camel.ssl.crlFile, camel.ssl.sessionTimeout, camel.ssl.serverNamerevocation list, session lifetime, SNI name
camel.ssl.trustAllCertificatesaccept any certificate; for tests only

camel.datasource.*: databases for sql, jdbc and sql-stored

properties
# one data source, bound as "dataSource" (or the name in camel.datasource.name)
camel.datasource.url = jdbc:postgresql://db:5432/shop
camel.datasource.username = app
camel.datasource.password = {{env:DB_PASSWORD}}

# more, each bound under its own name
camel.datasource.reports.url = jdbc:postgresql://reports:5432/bi

Routes refer to them as sql:select ...?dataSource=#reports. See sql.

camel.component.<scheme>.<option>: defaults for every endpoint of a component

properties
camel.component.kafka.brokers = {{env:KAFKA_BROKERS:localhost:9092}}
camel.component.seda.queueSize = 10000

An option on the endpoint URI still wins over the component default.

camel.beans.*: beans

camel.beans.<name>=#class:<type> plus camel.beans.<name>.<property>=value create a bean through a factory registered for that type in Rust (cameleer_yaml::register_bean_factory). The cameleer binary registers no factories, so with the CLI and the Docker image these entries are logged and skipped; see what works without Rust.

What works without Rust

Everything in a route URI, and everything on this page except beans, works from the CLI and the Docker image. Some options take a reference to an object in the registry (#name):

you needwithout Rustwith Rust
a database for sql / jdbccamel.datasource.*bind your own
TLS settingsURI options (sslTruststoreLocation, ...), camel.ssl.*, camel.server.ssl.*an SSLContextParameters bean
a component defaultcamel.component.<scheme>.<option>the same, or configure the component
an aggregation strategythe built-in names on aggregate, split and enrichbind your own
an idempotent or aggregation repositorythe in-memory defaultbind a JDBC, Redis or file repository
a processor or beana script step (js, groovy, python, ...)bind a Processor or bean factory

A worked example

One route, three environments. The route sends orders to a target chosen by configuration:

yaml example: configuration-orders
- route:
    id: orders
    from:
      uri: direct:order
      steps:
        - to: "{{orders.target}}"
properties
camel.main.name = orders
orders.target = log:orders?level=INFO
%dev.orders.target = log:orders?level=DEBUG
properties
camel.server.port = {{env:PORT:9090}}
orders.target = log:orders?level=WARN
runorders.targetcamel.main.namecamel.server.port
cameleer run orders.camel.yamllog:orders?level=INFOorders8080 (default)
cameleer run orders.camel.yaml --profile dev (or --dev)log:orders?level=DEBUGorders8080
PORT=7070 cameleer run orders.camel.yaml --profile prodlog:orders?level=WARNorders7070
CAMEL_MAIN_NAME=orders-eu cameleer run orders.camel.yamllog:orders?level=INFOorders-eu8080
CAMEL_MAIN_NAME=orders-eu cameleer run orders.camel.yaml --name orders-testlog:orders?level=INFOorders-test8080

The test configuration_guide_worked_example (crates/cameleer-main/tests/docs_reference.rs) writes these files from this page and checks every row of the table.

In Rust

cameleer_main::Main reads the same sources:

rust
let mut main = cameleer_main::new_main();
main.load_application_config(".")?;          // application.properties / .yaml
main.set_profile("prod");                    // or CAMEL_MAIN_PROFILE
main.set_property("camel.server.port", "9090"); // like --prop
main.add_route_file("orders.camel.yaml");
main.run()?;

Common questions

How do I use different settings for development and production?

Put the shared settings in application.properties, the production ones in application-prod.properties (or %prod.key=value lines), and start with --profile prod or CAMEL_MAIN_PROFILE=prod. See Profiles.

How do I pass a secret without putting it in a file?

Use {{env:NAME}} in the property or route (camel.datasource.password={{env:DB_PASSWORD}}), or a vault function such as {{aws:orders/db-password}} (cloud credentials).

How do I change the port?

--port 9090, camel.server.port=9090, CAMEL_SERVER_PORT=9090, or camel.server.port={{env:PORT:8080}} to follow the platform's PORT.

Why is my application.properties ignored?

cameleer run reads it from the current directory; run from that folder, or pass --properties path/to/application.properties (which then replaces the files of the current directory). In Docker, mount the folder at /routes, the image's working directory.

Why does a camel.ssl.* setting have no effect?

Set camel.ssl.enabled=true; without it the global TLS parameters are ignored.

Which keys does a component read from configuration?

Any endpoint option, as camel.component.<scheme>.<option>; the options are listed on each component page.

Found a problem?

If something on this page doesn't match what Cameleer does, please open an issue, or fork the repository, fix it, add a test, run cargo test --workspace and open a pull request.

Edit this page on GitHub