Run an RTE

The settings of each mode, and how to start an RTE

  1. Settings
  2. Start it

Settings

What an RTE needs depends on its mode (see Modes). Every RTE reads these:

Variable Meaning
RTE_MODE Since 7.3.0: outbound (it dials the app), inbound (the app dials it) or database (deprecated, the default throughout 7.x)
RTE_TOKEN The token between the app and the RTE, at least 16 characters; the RTE refuses to start without it
RTE_MAX_JOBS How many playbooks it runs at once, 10 by default (0 sets no limit). A job for a full RTE waits until a playbook ends
RTE_DRAIN_SECONDS On a stop, how long it waits for its running playbooks, 25 by default; the ones still running then end as abandoned
RTE_QUEUE_MINUTES Read by the app nodes and the worker, not the RTE: how long a job waits for a full or stopping RTE, 60 by default
ANSIBLE_PATH, PROCESS_MAX_BUFFER The playbooks folder and the output limit: read by the RTE, so set them in its environment
LISTEN_HOST Since 7.3.0: the address its listeners bind, every interface by default; 127.0.0.1 when nothing dials it from outside (an outbound RTE)

An RTE in a socket mode, outbound or inbound, also reads these, and no DB_* and no ENCRYPTION_SECRET:

Variable Meaning
APP_URL The app’s address as people open it, such as https://forms.example.com. Outbound: the address it dials. Inbound: the address of its one registration call
APP_TLS_VERIFY 1 (default): the app’s certificate must be valid. 0 accepts any, inside one trusted network only
RTE_NAME Its runner’s name, which forms name with runner:. Not set: its node id, rte-<hostname>-<port>, which changes with the container: set it in production
RTE_JOIN_TOKEN Optional, the first time only: a join token, made through the API, which approves its runner at once instead of waiting for an admin (see Join tokens)
RTE_URL Inbound, when it asks to join: the address the app dials, such as http://rte-dmz.example.com:8000
RTE_FILES transfer (default): the app sends the playbooks and inventories with the job. local: it runs from its own mounted folders
RTE_SPOOL_PATH Where each job’s output, events and end wait until the app stored them, <persistent>/rte-spool by default: keep it on a volume
RTE_CACHE_PATH With transfer: where the folders the app sent are kept, <persistent>/rte-files by default
RTE_CACHE_MB With transfer: how much those folders may take, 1024 by default; the ones used longest ago go first, and 0 keeps none
RTE_FILES_MAX_MB Read by the app, not the RTE: the largest folder it sends with transfer, 512 by default

On an RTE in a socket mode, RTE_MAX_JOBS, RTE_DRAIN_SECONDS, RTE_FILES and RTE_CACHE_MB can also be set on its runner page, under the RTE tab: a value there wins over the variable, which then only fills a field left empty (see An RTE’s settings). A value out of range is brought to its limit, and the RTE says so when it starts.

An RTE in database mode (deprecated) reads the database settings instead, and registers itself:

Variable Meaning
DB_HOST, DB_PORT, DB_USER, DB_PASSWORD The app’s own values: the RTE reads its jobs from the database and writes their output there
RTE_URL The address the app calls the RTE on, such as http://rte:8000. The runner is named after its host (rte), so forms can use runner: rte
RTE_REGISTER Deprecated in 7.3.0, with database mode: a socket-mode RTE joins with a join token instead. 1 (default): the RTE adds itself under Connections > Runners at its start, and the first one becomes the default runner. 0: add it there yourself, or in the config seed
ENCRYPTION_SECRET The app’s own value, needed only to register itself (the runner’s token is stored encrypted); leave it out with RTE_REGISTER=0

In database mode, without RTE_URL the RTE registers its IP address and port under the name rte-<hostname>-<port>, which change when the container is recreated: set RTE_URL in production. The worker removes a runner the RTE registered itself 10 minutes after the RTE’s last heartbeat.


Start it

The RTE runs the playbooks, so it needs its ssh folder, with the private key and the known_hosts the playbooks use, and a persistent folder for its spool and the files the app sends. Pick the mode:

Start the RTE on any host that reaches the app, with its own token and the name its runner gets:

docker run -d --name rte-dmz --restart unless-stopped --stop-timeout 40 \
  -e RTE_MODE=outbound -e APP_URL=https://forms.example.com \
  -e RTE_NAME=rte-dmz -e RTE_TOKEN=<at least 16 characters> -e HTTPS=0 \
  -v /srv/apps/rte/persistent:/app/dist/persistent \
  -v /srv/apps/rte/ssh:/home/node/.ssh \
  ghcr.io/ansibleforms/ansibleforms-rte-full:7

It dials the app and asks to join: Connections > Runners shows the runner rte-dmz as waiting for approval, and its log shows the fingerprint of its token. Check that its review shows the same fingerprint, then Approve it (see Approving an RTE): it takes jobs from then on, signing in with its own RTE_TOKEN. For an unattended start, add -e RTE_JOIN_TOKEN=<a join token, afj_...>, which approves it at once. Nothing needs to reach this host: publish no port. Only /live, /ready and /metrics listen on its PORT, for the probes.

Keep an inbound RTE off the public network: its socket answers any caller that has the token. docker stop waits only 10 seconds before it kills a container, so give the RTE a longer stop timeout (--stop-timeout, or stop_grace_period in compose) or lower RTE_DRAIN_SECONDS. Kubernetes waits 30 seconds by default.

The installer sets up an outbound or inbound RTE on a server of its own, with Docker, Podman or without containers, and prints the fingerprint to approve it by. To run an RTE in another datacenter by hand, follow Another datacenter.