Skip to main content
Use this when more than one person, script or agent will call the server, or when workflows run commands, SQL or HTTP calls you want to bound. A fresh server listens on 127.0.0.1 only and takes no key. These steps assume you opened it as described in Deploy Yukta. Prerequisites: an ADMIN key and the ability to change the server’s settings and restart it. For who can do what and why, read The security model. Every setting named here is listed with its default in Security reference.
Whoever can define a workflow decides what its nodes do: run commands, scripts and SQL, call HTTP endpoints, read files. Give the ADMIN role, and with it the right to define workflows, only to people you would let run code on the server. Without any key, everyone who can reach the server has that right. That is why the default is loopback only.

Steps

1

Give each caller a named key with a role

Keys are a list in yukta.api-keys. Each entry has a name (used in the audit), a key, a role (VIEWER, OPERATOR or ADMIN) and, for the first two, the sessions it may reach:
In a container or systemd file, use the same list as YUKTA_API_KEYS_0_NAME, YUKTA_API_KEYS_0_KEY, YUKTA_API_KEYS_0_ROLE, YUKTA_API_KEYS_1_... and so on.
  • A VIEWER reads. An OPERATOR also starts, stops and steers runs, and answers input requests. Defining sessions and workflows, changing scheduler limits and reading /actuator/** need ADMIN.
  • A VIEWER or OPERATOR key with no sessions is refused at start-up. Write * to allow every session, so a misspelt session can never widen a key.
  • The same secret in two entries is refused at start-up.
2

Store the digest, not the key

A key that starts with sha256: followed by 64 hex digits is the SHA-256 digest of the real key. The server then never holds the plain key, and clients still send the plain one.
Give the person or system $key, and the server sha256:<the digest>. Keys shorter than 32 characters get a warning in the log.
3

Rotate and expire keys

Several keys are valid at once. To rotate with no downtime, add the new key as another entry, move the clients over, then remove the old entry and restart. Set an expiry on a short-lived key:
After that instant the key is refused with 401. Revoking a key still needs a settings change and a restart.
4

Allow only the commands you mean

PROCESS_EXECUTOR runs nothing until you allow commands. List the executables:
While the list is set, shell mode (useShell) is refused, a node’s workingDir must stay inside the root, and a node cannot set environment variables such as PATH, LD_* or JAVA_TOOL_OPTIONS. The list names an executable, not what it does with its arguments, so it is not a sandbox: never allow a shell or an interpreter such as python3. Use yukta.process.allow-any=true only when every workflow author is fully trusted.
5

Limit the hosts a workflow may call

By default HTTP_REQUEST, MCP_TOOL_CALL and NOTIFY_TERMINAL may call any host except link-local and cloud metadata addresses. Narrow it:
A call must pass every list that applies, so a per-workflow or per-session list only narrows what the deployment allows. *.example.com matches subdomains but not example.com. The list works on the name in the URL: it does not look up what a name resolves to, so keep listed names under your control. Per-plugin lists also exist: yukta.http.allowed-hosts and yukta.mcp-client.allowed-hosts.
6

Keep secrets out of workflow definitions

A definition that holds a literal secret is refused when it is saved or run. Write a reference and set the value on the server:
decrypted:db.password reads YUKTA_SECRET_DB_PASSWORD: upper-case the name and replace every character that is not a letter or digit with _. Each read is logged with the key name, never the value. Placeholders such as ${env.NAME} read only variables that start with YUKTA_VAR_, a short safe list, or names you list in YUKTA_VARIABLES_ALLOWED; names that contain PASSWORD, SECRET, TOKEN, CREDENTIAL, PRIVATE or KEY stay blocked.
7

Read who did what

Control commands (pause, stop, skip, answer an input request, change limits and others) are recorded with the sender: key:<name> for a named key, the supervisor’s id for a supervisor.
The list is newest first, with whether each command was applied or refused and why. Add executionId=<id> to follow one run. The web UI shows the same list on the Control page, on its Audit tab.

Verify it worked

Call the server with each key and with none:
The first prints 401 (no key). The second shows the CI key’s name, role and sessions. The third prints 403, because a VIEWER may not change anything. yukta-cli whoami shows the same as the second call. A refusal carries no JSON body: handle it by status code. 401 means no key or a wrong key, 403 means the role or session list does not allow the request, and 429 means the key made too many calls.

Variations that matter

  • Behind a proxy with no key. With no key set, the server accepts only the host names localhost, 127.0.0.1 and [::1], and a changing request with a foreign Origin is refused with 403 and no body. List your host with yukta.allowed-hosts and yukta.allowed-origins. The check is off once any key is set, so prefer a key.
  • Rate limits. Each key may make 1200 /api requests per minute, and a wrong or missing key counts against the caller’s address (20 per minute), after which the address gets 429. Behind a proxy all callers share the proxy’s address. These are JVM system properties (-Dyukta.rate-limit-per-minute, -Dyukta.auth-failures-per-minute); 0 turns a limit off. Turn the first off for a load test.
  • The API description. The prod profile serves no Swagger UI and no /v3/api-docs. To turn them on behind the key, set SPRINGDOC_API_DOCS_ENABLED=true and SPRINGDOC_SWAGGER_UI_ENABLED=true. A browser cannot send the key header to the Swagger page, so fetch /v3/api-docs with a key.
  • LLM and MCP call filters. To refuse prompts or answers that match a pattern, cap prompt size, or restrict the tools a workflow may call, set the yukta.llm.* and yukta.mcp-client.* filters. They apply to every node whatever the node says. See Security reference.
  • Supervisors and agent credentials. A supervisor of type http has its own credential. See Assign a supervisor.
  • Remote workers. A worker runs plugins in its own process with its own settings; secure it like the server. See Add remote workers.
To report a vulnerability, use the repository’s security policy and not a public issue.