> ## Documentation Index
> Fetch the complete documentation index at: https://yukta.infenia.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Deploy Yukta for a team

> Run Yukta beyond your laptop with Docker, a Linux package, an archive or a source build, put TLS in front of it and protect it with an API key.

<dl />

**Use this when** you move Yukta from your laptop to a machine other people or other systems call. For a first install on a laptop, start with [Install Yukta](https://yukta.infenia.com/get-started/install.md).

**Prerequisites:** you know which install method fits (the table below), and you can run a reverse proxy that ends TLS, such as nginx or Caddy.

> [!WARNING]
>
> Yukta is in alpha. The release server and the Docker image are the **Community** edition: they keep sessions and run history in memory. Storing state on disk, PostgreSQL, high availability and remote workers need a build you make yourself. See [Persist sessions](https://yukta.infenia.com/guides/operate/persist-sessions.md) before you promise anyone that a restart keeps their workflows.

## Pick how to install it

| Method | Platforms | Choose it when |
| - | - | - |
| Docker image `ghcr.io/infenia/yukta` | Linux, and macOS or Windows through Docker Desktop (`linux/amd64`; `linux/arm64` from `0.1.0-alpha.4`) | You already run containers. The image holds the native server and nothing else |
| `.deb` or `.rpm` package | Linux `amd64` (`arm64` from `0.1.0-alpha.4`) | You want a `systemd` service, a service user and a settings file |
| Install script (`install.sh`) | Linux and macOS; with `0.1.0-alpha.3` and earlier only Linux `amd64` gets the server | You want the binaries in `/usr/local/bin` with checked checksums |
| Archive (`.tar.gz`, `.zip` on Windows) | Linux, macOS and Windows, from `0.1.0-alpha.4` (`0.1.0-alpha.3` and earlier: Linux `amd64`) | You manage the service yourself |
| From source | Anything with JDK 25 | You need a Plus build, extra plugins or a custom plugin. See [Write a plugin](https://yukta.infenia.com/guides/extend/write-a-plugin.md) |

![Clients reach Yukta over HTTPS through a reverse proxy on the same host; Yukta itself listens on loopback and checks the API key.](https://yukta.infenia.com/images/diagrams/ops-deploy.light.svg)

Only the proxy faces the network. The probe goes straight to Yukta, and state is in memory unless you build a Plus edition.

## Steps

**1. Make a key for the first administrator**

A server that listens on anything but loopback refuses to start without an API key. Make a long random one now and keep it in your secret store:

```bash theme={"system"}
export YUKTA_KEY="$(openssl rand -hex 32)"
```

The server warns about a key shorter than 32 characters. To keep the plain key off the server, give it the SHA-256 digest instead, written `sha256:<64 hex digits>`; clients still send the plain key. See [Secure the server](https://yukta.infenia.com/guides/operate/secure-the-server.md).

**2. Start the server**

> [tab] Docker
>
> The image listens on `0.0.0.0` inside the container, so it always needs a key. Publish the port on loopback and let the reverse proxy in step 3 face the network:
>
> ```bash theme={"system"}
> docker run -d --name yukta --restart unless-stopped \
>   -p 127.0.0.1:9858:9858 \
>   -e YUKTA_API_KEYS_0_NAME=admin \
>   -e YUKTA_API_KEYS_0_KEY="$YUKTA_KEY" \
>   -e YUKTA_API_KEYS_0_ROLE=ADMIN \
>   ghcr.io/infenia/yukta:0.1.0-alpha.4
> ```
>
> The image has no shell and no `curl`. It runs as the unprivileged user 65532.

> [tab] Linux package
>
> Install the `.deb` or `.rpm` from the release page. The package adds a `yukta` user and a `systemd` unit, and leaves the service stopped. Put the address and the key in `/etc/yukta/yukta.env`:
>
> ```bash theme={"system"}
> sudo tee -a /etc/yukta/yukta.env >/dev/null <<EOF
> YUKTA_API_KEYS_0_NAME=admin
> YUKTA_API_KEYS_0_KEY=$YUKTA_KEY
> YUKTA_API_KEYS_0_ROLE=ADMIN
> EOF
> sudo systemctl enable --now yukta
> ```
>
> Leave `YUKTA_SERVER_ADDRESS` unset so the server stays on `127.0.0.1` behind the proxy. The package sets the file to mode `0640`, so other users cannot read the key. Follow the logs with `journalctl -u yukta -f`.

> [tab] Install script
>
> ```bash theme={"system"}
> curl -fsSL https://github.com/infenia/yukta/releases/download/v0.1.0-alpha.4/install.sh | sh
> ```
>
> This puts `yukta` and `yukta-cli` in `/usr/local/bin` (as root) or `~/.local/bin`, after checking their checksums. It starts nothing. Run the server under a service manager of your choice, with the same three `YUKTA_API_KEYS_0_*` variables:
>
> ```bash theme={"system"}
> YUKTA_API_KEYS_0_NAME=admin YUKTA_API_KEYS_0_KEY="$YUKTA_KEY" YUKTA_API_KEYS_0_ROLE=ADMIN yukta
> ```

> [tab] Archive
>
> Unpack the `.tar.gz` from the release page. It holds the native `yukta` server and `yukta-cli`. Run `yukta` as in the install-script tab, under your own service manager.

> [tab] From source
>
> ```bash theme={"system"}
> ./gradlew :boot:bootJar
> YUKTA_API_KEYS_0_NAME=admin YUKTA_API_KEYS_0_KEY="$YUKTA_KEY" YUKTA_API_KEYS_0_ROLE=ADMIN \
>   java -jar boot/build/libs/boot-*.jar
> ```
>
> A jar started with no flags runs the `prod` profile. `./gradlew bootRun` runs `dev` instead, which logs more and is for development only. For a native binary, `./gradlew :boot:nativeCompile` needs GraalVM 25.

**3. Check the server on the host**

```bash theme={"system"}
curl -fsS http://127.0.0.1:9858/actuator/health
curl -fsS -H "Authorization: Bearer $YUKTA_KEY" http://127.0.0.1:9858/api/me
```

The first call returns `{"status":"UP"}` and needs no key. The second shows the name and role of your key.

**4. Put TLS in front of it**

Yukta serves plain HTTP, and keys travel in request headers, so end TLS in a reverse proxy on the same host. Two things matter in the proxy: do not buffer event streams, and do not close idle ones early (the server sends a keep-alive comment every 15 seconds).

> [tab] nginx
>
> ```nginx theme={"system"}
> server {
>   listen 443 ssl;
>   server_name yukta.example.com;
>   # ssl_certificate and ssl_certificate_key go here
>
>   location / {
>     proxy_pass http://127.0.0.1:9858;
>     proxy_http_version 1.1;
>     proxy_set_header Host $host;
>     proxy_set_header X-Forwarded-For $remote_addr;
>     proxy_buffering off;
>     proxy_read_timeout 1h;
>   }
> }
> ```

> [tab] Caddy
>
> ```text theme={"system"}
> yukta.example.com {
>   reverse_proxy 127.0.0.1:9858 {
>     flush_interval -1
>   }
> }
> ```

These are examples; adapt them to your proxy. When you set a key, the `Host` and `Origin` check that protects a keyless local server is off, so no extra setting is needed for the host name. The one-time-token answer path (`/api/inputs/token-answer`) rate-limits by caller address; for that to be the caller and not the proxy, set `server.forward-headers-strategy=framework` and make the proxy replace `X-Forwarded-For` as shown.

**5. Tell clients where the server is**

```bash theme={"system"}
export YUKTA_SERVER_URL=https://yukta.example.com
export YUKTA_TOKEN="$YUKTA_KEY"
yukta-cli whoami
```

For named keys with limited roles per person or agent, see [Secure the server](https://yukta.infenia.com/guides/operate/secure-the-server.md). Do not hand the first administrator key to every client.

**6. Give it time to stop**

On a stop signal the server refuses new starts and gives running runs `yukta.execution.shutdown-timeout` (30 seconds by default) to finish. The packaged `systemd` unit waits 45 seconds. In an orchestrator, set the stop grace period above 30 seconds. Use `GET /actuator/health` as the probe: the image has no shell for an exec probe.

## Verify it worked

From another machine:

```bash theme={"system"}
curl -fsS https://yukta.example.com/actuator/health
curl -s -o /dev/null -w '%{http_code}\n' https://yukta.example.com/api/sessions
curl -fsS -H "Authorization: Bearer $YUKTA_KEY" https://yukta.example.com/api/me
```

The health call returns `{"status":"UP"}`. The second call prints `401`, because it sent no key. The third returns your key's name and role. If the container or service exits at start, read its log: "Refusing to listen on ... without an API key" means no key reached the server. See [Troubleshoot](https://yukta.infenia.com/guides/operate/troubleshoot.md).

## Variations that matter

* **Choose the plugins you ship.** Optional plugins are chosen when you build, with `-Pyukta.plugins=default`, `all`, `none` or a comma-separated list. A running server cannot add or remove them. The settings and the plugin names are in [Configuration reference](https://yukta.infenia.com/reference/configuration.md) and the [plugin reference](https://yukta.infenia.com/reference/plugins/overview.md).
* **Run more than one server.** Failover needs a Plus build and PostgreSQL. See [Run highly available](https://yukta.infenia.com/guides/operate/run-highly-available.md).
* **Install on a machine with no internet.** Copy a release's files to a web server laid out as `<base>/vX.Y.Z/<file>`, then run `install.sh` with `YUKTA_DOWNLOAD_BASE=<base>`. Read the script first if you need to audit it.
* **Check a download.** Every release publishes `SHA256SUMS` and a Sigstore signature for it. See [Releases](https://yukta.infenia.com/reference/releases.md).
* **Publish the API description.** The `prod` profile serves no Swagger UI or `/v3/api-docs`. To turn them on behind your key, see [Secure the server](https://yukta.infenia.com/guides/operate/secure-the-server.md).

## Related

* [Install Yukta](https://yukta.infenia.com/get-started/install.md): the first install, on a laptop
* [Upgrade and roll back](https://yukta.infenia.com/guides/operate/upgrade-and-roll-back.md)
* [Secure the server](https://yukta.infenia.com/guides/operate/secure-the-server.md)
* [Configuration reference](https://yukta.infenia.com/reference/configuration.md): every setting, its default and its environment variable
* [How durability and high availability work](https://yukta.infenia.com/concepts/durability-and-high-availability.md)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.