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

# Docker - full stack

> Stand up Ekso in minutes with the full-stack bundle — app, worker, Postgres, and a daily backup service in a single docker compose up.

The full-stack bundle is the fastest path to a running Ekso. One `docker compose up -d` brings up the API, the background worker, a Postgres database with pgvector preinstalled, and a daily backup service. No external services to wire up.

<Note>
  Already running Postgres or SQL Server you want Ekso to share? Use [Docker - bring your own database](/guide/install/byod) instead — same code, different install path.
</Note>

## Prerequisites

* **Docker Engine 20+** on Linux, **Docker Desktop** on macOS or Windows
* **\~2 GB free disk** for first-time image pulls
* **A free license.** Fetch one at [ekso.app/get-started](https://ekso.app/get-started) — the site emails you the personalized download link in the same step. Free tier is 3 users, no credit card. [Standard and Advanced](https://ekso.app/pricing) are flat-rate annual with unlimited users.
* **An install URL** — the public hostname your users will reach Ekso at, e.g. `https://ekso.acme.com`. Used as the OAuth audience and for outbound email links. Doesn't need to resolve *before* install — you finalize it during the [first run wizard](/guide/install/first-run).

## Install

<Note>
  **Want your AI to run this for you?** See [Agentic install](/guide/install/agentic) — same bundle, paste-executed by Claude Code, Cursor, Codex, or ChatGPT in \~2 minutes. Best for evaluation; use the manual steps below for production deployments where you want full control.
</Note>

1. **Download the bundle** from the link in your welcome email (`ekso-docker-stack.zip`).

2. **Unzip** somewhere persistent — for example `~/ekso/` or `/srv/ekso/`. The zip contains:

   | File                         | Purpose                                                                                                                            |
   | ---------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- |
   | `docker-compose.yml`         | Service definitions: `app`, `worker`, `backup`, `postgres`                                                                         |
   | `ekso.json`                  | Install configuration. JWT signing key is pre-baked per download. See the [configuration reference](/guide/install/configuration). |
   | `restore.sh` / `restore.ps1` | Recovery scripts for the bundled `backup` service. See [Data management](/guide/manage/data-management).                           |
   | `README.md`                  | Bundle-local quick reference                                                                                                       |

   <Warning>
     The `Secrets.JwtKey` and `Secrets.EncryptionKey` in `ekso.json` are unique to your download. Re-fetching the bundle from ekso.app issues fresh keys — a new `JwtKey` invalidates every active session, and a new `EncryptionKey` makes every admin-managed setting (S3 credentials, SMTP password, mailbox creds) unreadable. Treat the zip as a one-time install artifact — store it safely if you want a stable reference.
   </Warning>

3. **Bring it up** from the unzipped directory:

   ```bash theme={null}
   docker compose up -d
   ```

   On first run, Compose pulls `eksoapp/app` and `eksoapp/worker` from Docker Hub, starts a `postgres` container with pgvector, and the API auto-applies the database schema. Allow 30–60 seconds for everything to settle.

4. **Open the install URL** to land in the [first run wizard](/guide/install/first-run):

   ```
   http://localhost:6050/startup
   ```

For automated install — useful when an AI agent stands up Ekso on behalf of an operator — see [agent onboarding](/guide/agent-onboarding).

## What's running

Four containers come up:

| Service    | Image                    | Role                                                 |
| ---------- | ------------------------ | ---------------------------------------------------- |
| `app`      | `eksoapp/app`            | REST API + UI on port 6050                           |
| `worker`   | `eksoapp/worker`         | Background jobs — email, ticketing, vector indexing  |
| `postgres` | `pgvector/pgvector:pg18` | OLTP + reporting database with pgvector preinstalled |
| `backup`   | `postgres:18-alpine`     | Daily snapshots of the database and uploaded files   |

Your data lives in normal folders next to `docker-compose.yml`:

| Folder             | What's in it                          |
| ------------------ | ------------------------------------- |
| `./data/postgres/` | PostgreSQL database files             |
| `./data/storage/`  | Uploaded attachments                  |
| `./backups/`       | Daily snapshots, retained for 14 days |

For the full data model — automatic backups, restore commands, and the `docker compose down -v` reassurance — see [Data management](/guide/manage/data-management).

<Note>
  The bundle is multi-arch — same compose works on `linux/amd64` and `linux/arm64` (Apple Silicon, Graviton, etc.). Docker pulls the right variant automatically.
</Note>

## Pointing it at a real domain

For anything beyond local evaluation, run Ekso behind a reverse proxy that terminates TLS — Traefik, Caddy, nginx, your existing Cloudflare tunnel. Forward to `app:6050` and use that proxy's URL as the **public URL** during the [first run wizard](/guide/install/first-run).

The `ekso.json` config file ships with a JWT signing key already pre-baked — you don't need to edit it for a full-stack install. See [Configuration reference](/guide/install/configuration) if you want to know what every field does or you need to override anything.

## Updating

```bash theme={null}
docker compose pull
docker compose up -d
```

The API auto-applies any new schema migrations on startup. No manual database steps. Your `./data/` and `./backups/` folders are untouched. See [Upgrading](/guide/manage/upgrading) for release cadence, version pinning, and the rollback procedure.

## Tearing it down

```bash theme={null}
docker compose down       # stop containers; data and backups untouched
docker compose down -v    # also stops containers; data and backups STILL untouched
```

Both forms preserve your data. There are no Docker-managed volumes for `-v` to delete — your database, attachments, and backups all live in the `./data/` and `./backups/` folders next to `docker-compose.yml`. To genuinely delete data, you'd `rm -rf ./data` at the OS level. See [Data management](/guide/manage/data-management#what-happens-with-docker-compose-down--v).
