Skip to main content
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.
Already running Postgres or SQL Server you want Ekso to share? Use Docker - bring your own database instead — same code, different install path.

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 — the site emails you the personalized download link in the same step. Free tier is 3 users, no credit card. Standard and Advanced 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.

Install

Want your AI to run this for you? See Agentic install — 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.
  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:
    FilePurpose
    docker-compose.ymlService definitions: app, worker, backup, postgres
    ekso.jsonInstall configuration. JWT signing key is pre-baked per download. See the configuration reference.
    restore.sh / restore.ps1Recovery scripts for the bundled backup service. See Data management.
    README.mdBundle-local quick reference
    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.
  3. Bring it up from the unzipped directory:
    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:
    http://localhost:6050/startup
    
For automated install — useful when an AI agent stands up Ekso on behalf of an operator — see agent onboarding.

What’s running

Four containers come up:
ServiceImageRole
appeksoapp/appREST API + UI on port 6050
workereksoapp/workerBackground jobs — email, ticketing, vector indexing
postgrespgvector/pgvector:pg18OLTP + reporting database with pgvector preinstalled
backuppostgres:18-alpineDaily snapshots of the database and uploaded files
Your data lives in normal folders next to docker-compose.yml:
FolderWhat’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.
The bundle is multi-arch — same compose works on linux/amd64 and linux/arm64 (Apple Silicon, Graviton, etc.). Docker pulls the right variant automatically.

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. 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 if you want to know what every field does or you need to override anything.

Updating

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 for release cadence, version pinning, and the rollback procedure.

Tearing it down

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.