> ## 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 - BYOD

> Install Ekso against your existing Postgres or SQL Server. The BYOD bundle ships app + worker only; you provide the database.

The BYOD bundle is for shops that already operate Postgres or SQL Server and want Ekso to share it. The zip ships only the `app` and `worker` containers — no embedded database — and an `ekso.json` with placeholder connection strings for you to fill in.

Pick this if you have a managed Postgres on AWS RDS / Azure Database / Supabase / Neon, a SQL Server estate with spare capacity, or strict policy that data lives in your existing instance. For a clean-slate install with no external dependencies, see [Docker - full stack](/guide/install/quickstart) instead.

## Prerequisites

* **Docker Engine 20+** on Linux, **Docker Desktop** on macOS or Windows
* An empty database on **Postgres 16+** or **SQL Server 2025**, plus credentials with `CREATE` rights so Ekso can apply its schema on first boot
* **pgvector** installed on Postgres (one-time per database):

  ```sql theme={null}
  CREATE EXTENSION IF NOT EXISTS vector;
  ```
* A free license — fetch one at [ekso.app/get-started](https://ekso.app/get-started)

<Note>
  SQL Server 2025 is the minimum because Ekso uses native vector search. Earlier versions don't have the required types and DiskANN index support.
</Note>

## Install

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

2. **Unzip** somewhere persistent. The zip contains `docker-compose.yml`, `ekso.json`, and a `README.md`.

3. **Edit `ekso.json`** — fill in the connection strings for your database. The full schema is documented in the [configuration reference](/guide/install/configuration); the relevant fields are under `Database`. The same two fields (`TransactConnection` + `MartConnection`) take connection strings in the dialect implied by `Provider`:

   **Postgres example:**

   ```json theme={null}
   "Database": {
       "Provider": "Postgres",
       "TransactConnection": "Host=postgres.internal;Port=5432;Database=ekso;Username=ekso;Password=••••",
       "MartConnection":     "Host=postgres.internal;Port=5432;Database=ekso;Username=ekso;Password=••••"
   }
   ```

   **SQL Server example:**

   ```json theme={null}
   "Database": {
       "Provider": "SqlServer",
       "TransactConnection": "Server=sql.internal,1433;Database=ekso;User Id=ekso;Password=••••;Encrypt=True;TrustServerCertificate=False;",
       "MartConnection":     "Server=sql.internal,1433;Database=ekso;User Id=ekso;Password=••••;Encrypt=True;TrustServerCertificate=False;"
   }
   ```

4. **Bring it up:**

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

   The API auto-applies the schema on first boot. Allow 30–60 seconds for that plus image pulls.

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

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

## Transact vs Mart connections

Ekso splits database access into two connection strings:

| Connection | Purpose                                   | When to point them differently                                                      |
| ---------- | ----------------------------------------- | ----------------------------------------------------------------------------------- |
| `Transact` | OLTP — every live request hits this       | Default — the live-work database                                                    |
| `Mart`     | Reporting, analytics, the Insights module | Point at a read replica when reporting load is heavy enough to bother the OLTP path |

For most installs, both connection strings point at the same database. Separating them onto a read replica is an optimization for reporting-heavy workloads — not a starting requirement.

## Connection-string gotchas

| Symptom                                       | Likely cause                                                                                                 |
| --------------------------------------------- | ------------------------------------------------------------------------------------------------------------ |
| `connection refused` from `app` container     | Database hostname resolves correctly inside Docker? Use the host's network address, not `localhost`.         |
| `permission denied` on first boot             | The Ekso user doesn't have `CREATE` rights — schema apply fails. Grant `CREATE ON DATABASE`.                 |
| `extension "vector" does not exist`           | pgvector wasn't installed before first boot. Run `CREATE EXTENSION IF NOT EXISTS vector;` and restart `app`. |
| TLS handshake errors against managed Postgres | Cloud providers usually require `Ssl Mode=Require;Trust Server Certificate=true` in the connection string.   |

## What's running

Three containers:

| Service  | Image            | Role                                    |
| -------- | ---------------- | --------------------------------------- |
| `app`    | `eksoapp/app`    | REST API + UI on port 6050              |
| `worker` | `eksoapp/worker` | Background jobs                         |
| `backup` | `alpine:3.20`    | Daily snapshots of uploaded attachments |

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

| Folder                 | What's in it                          | Whose responsibility                            |
| ---------------------- | ------------------------------------- | ----------------------------------------------- |
| `./data/storage/`      | Uploaded attachments                  | The bundle                                      |
| `./backups/storage/`   | Daily snapshots, retained for 14 days | The bundle                                      |
| Your external database | All other Ekso data                   | **You** — back up with your existing DB tooling |

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

## Updating

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

Schema migrations apply automatically on startup against your existing database — same migration system as Quickstart, just pointed at the database you provided. Your `./data/` and `./backups/` folders are untouched, and the bundle never touches your external DB. See [Upgrading](/guide/manage/upgrading) for release cadence, version pinning, and the rollback procedure.

## Switching providers

<Warning>
  Don't switch `Database.Provider` on a populated install. Ekso emits the schema for whichever provider you pick on first boot — the on-disk schemas aren't interchangeable. To migrate, back up tenant data, point at a fresh database in the new engine, restore.
</Warning>
