Pluggable, Secure Runtimes
To maintain system security, rescile requires execution isolation using specific runtimes. The engine parameter dictates the isolation boundary:
wasi(WebAssembly): Modules compile logic to.wasm. Executed usingwasmtimewith zero external dependencies, providing strong isolation and high performance.nix(Nix Flakes): Spawns an execution boundary wrapped in anix developshell for highly reproducible environments without polluting the host OS or requiring pre-installed tooling.nix-shell: Runs commands inside anix-shellenvironment defined by ashell.nixfile.container(Docker/Podman): Spawns an ephemeral container, mounts required outputs, streams logs, and destroys the container when finished. Ideal for legacy tooling like Terraform or Ansible.http: Securely triggers existing CI/CD pipelines using signed webhook payloads, or executes multi-step REST/GraphQL API chains directly from the core.api: Executes a multi-step REST/GraphQL API chain ([[runtime.steps]]) directly in the controller core. No runner participates — these actions need noexecarray and no runner runtime capability, which makes them the canonical form for integrating external HTTP APIs (vault issuance, OCSP sync, renewal jobs). See HTTP chains withengine = "api"below.system(Operating System): Executes a command directly on the runner host with the privileges of therescile-runnerprocess. This engine relies on tools already installed on the runner (for example,ansible-playbook,ssh, or cloud CLIs) and does not provide isolation by itself.
Runner engine support: The
rescile-cerunner natively supportssystem,nix, andnix-shell. Other engines, such ascontainerorwasi, require a runner implementation that explicitly supports them.
HTTP chains with engine = "api"
engine = "api" runs the action’s [[runtime.steps]] chain directly inside the controller process. No runner participates: these actions declare no exec array and require no runner runtime capability, which makes them the canonical form for multi-step HTTP integrations that must work on controller-only deployments (vault certificate issuance, OCSP refreshes, ACME renewals):
# actions/auto_renew.toml
name = "auto_renew"
description = "Renew a certificate through the PKI API"
run_mode = "action"
[[input]]
name = "certificate_name"
type = "string"
required = true
[vault_secrets.pki_token]
collection = "pki"
secret = "api_token"
[runtime]
engine = "api"
[[runtime.steps]]
method = "POST"
url = "https://pki.internal/v1/renew"
headers = { "Authorization" = "Bearer ${secrets.pki_token}" }
body = """
{ "certificate": "{{ input.certificate_name }}" }
"""
Semantics:
- Step templating uses
{{ input.<name> }}(stringified action payload values) and${secrets.<key>}(vault-mapped secrets resolved as plaintext inside the controller; no age sealing is involved because secrets never leave the controller). - Steps execute sequentially; the first non-success response fails the whole chain.
- REST bodies, GraphQL steps (
graphql_query/graphql_variables), and per-step headers behave exactly as withengine = "http". - Step logs are written to the action log (same UI as runner logs), and the queue tracks the execution
Running -> Completed/Failedlike any runner-executed action. - Service-mode (
run_mode = "service") api actions execute once; they are not duplicated per connected runner.
Use engine = "http" instead when the chain must run on a specific runner (e.g. inside an isolated network where only that runner can reach the API); the step format is identical.
Platform Constraints: Some runtimes depend on the underlying architecture and operating system. The runtime block evaluates declarative platform constraints against the host system, emitting a warning if the action cannot be executed locally.
Execution via rescile-runner
The rescile-runner component is responsible for securely executing the generated action bundles. It is compiled as a standalone binary designed to reduce the blast radius. Depending on your network and security requirements, actions support four distinct modes of execution:
- Air-Gapped (Manual): You download the fully packaged artifact (
bundle.tar.gz) directly from the Rescile UI. This bundle contains the executable, context data, injected secrets, and amanifest.json. You then manually transfer this bundle to an air-gapped machine and execute it locally using the runner (rescile-ce runner ./bundle.tar.gz). - Webhook (Fetch/Watch): External systems can pull the action payload and execute it independently by invoking the
rescile-runnerCLI with the Controller API URL. Optionally, the runner can act as a background daemon (rescile-ce runner --watch <URL>) that automatically re-executes when changes are detected via WebSocket subscription. - Agent (Push): Autonomous Agent runners connect outward to the Controller via a persistent gRPC multiplexed stream. When an action is placed in the queue, the Controller instantly pushes the payload to a matching agent, making it ideal for crossing NAT boundaries and executing workloads inside isolated VPCs.