# Docker (/docs/deploy/docker)



`npx nylorun up` runs the Runtime as one Docker Compose project named
`nylorun`. This is the supported deployment in this release.

```sh
npx nylorun up        # start, or leave running if already up
npx nylorun status    # service, port, and readiness state
npx nylorun down      # stop containers and keep data
```

## Services [#services]

| Service    | Role                                                 |
| ---------- | ---------------------------------------------------- |
| `postgres` | Session Store; one `tenant_<id>` schema per Tenant.  |
| `restate`  | Durable session execution, wakes, and Tenant sweeps. |
| `s2`       | s2-lite streams for session history and SSE.         |
| `runtime`  | Tenant and Admin HTTP APIs and workers.              |
| `studio`   | Local dashboard and trusted proxy.                   |

## Images [#images]

Runtime and Studio ship as multi-architecture images (`linux/amd64`,
`linux/arm64`) tagged with their package versions:

| Image                                       | Notes                         |
| ------------------------------------------- | ----------------------------- |
| `ghcr.io/nylorun/runtime:<runtime version>` | `--role api`, `worker`, `all` |
| `ghcr.io/nylorun/studio:<studio version>`   | Not published to npm          |

`nylorun up` runs the versions its release pins beside the official Postgres,
Restate, and s2-lite images. Tags are never moved and there is no `latest`
tag. Override the pins with `NYLORUN_RUNTIME_IMAGE` and `NYLORUN_STUDIO_IMAGE`,
for example with a local build. The local stack runs the Runtime with the
combined `all` role.

## Ports [#ports]

| Service    | Default          |
| ---------- | ---------------- |
| Runtime    | `127.0.0.1:8787` |
| Studio     | `127.0.0.1:4161` |
| Restate UI | `127.0.0.1:9070` |

The first start stores configured or free ports in `stack/.env`. Change them
there with `NYLORUN_PORT`, `NYLORUN_STUDIO_PORT`, and `NYLORUN_RESTATE_PORT`.

## Container configuration [#container-configuration]

* Database: `NYLORUN_DATABASE_URL`
* Restate: `NYLORUN_RESTATE_*`
* S2: `NYLORUN_S2_*`
* Listener: `NYLORUN_LISTEN_HOST`, `NYLORUN_LISTEN_PORT`,
  `NYLORUN_ALLOWED_HOSTS`, and `NYLORUN_PUBLIC_URL`

`GET /ready` checks Postgres, Restate, and S2 and returns `503` while a required
dependency is unavailable. `GET /health` reports version and protocol
compatibility.

## Storage [#storage]

Two things hold all state, and they belong together:

1. **The Host root** (`NYLORUN_HOME` or `~/.nylorun`): identity, the admin key,
   stack configuration, and per-Tenant files.
2. **Docker volumes**: each Tenant's Postgres schema, S2 session streams,
   Restate state, and workspaces.

```text
~/.nylorun/
  host.json
  host-credentials.json     # admin key
  stack/
    compose.yaml
    .env                    # mode 0600
    restate-identity.pem
  tenants/<id>/
    vault-kek
    plugin-data/
    logs/
    home/
    tmp/
    sandboxes/
  trash/
```

* Keep the Host root private and persistent. Keep each project's
  `.nylorun/link.json` and `credentials.json` private too.
* Back up and restore the Host root and the volumes **together**; credentials
  and database state are not independent.
* `nylorun down` stops containers and keeps data. `nylorun reset` deletes all
  volumes and every Tenant.
* Run one stack per machine.

SQLite Tenants from earlier releases are not migrated. On first start they move
to `trash/<id>-sqlite-<time>/` and the Runtime logs
`sqlite_tenant_moved_to_trash`. Copy out anything you need and recreate the
Tenant with `nylo tenant create`.

## Connect your app server [#connect-your-app-server]

| Where your app server runs               | `NYLORUN_RUNTIME_URL`                                   |
| ---------------------------------------- | ------------------------------------------------------- |
| Same machine                             | `http://localhost:<port>` (the URL `nylorun up` prints) |
| Container on the stack's Compose network | `http://runtime:4000`                                   |
| Another machine                          | Needs a reverse proxy; not part of this release         |

* Never publish the Runtime, Studio, or Restate ports beyond loopback.
* Keep Studio for operators: loopback or an SSH tunnel.

## Next step [#next-step]

<Cards>
  <Card title="App server" description="Configure your app and serve your users." href="/docs/deploy/app-server" />

  <Card title="Troubleshooting" description="Stack, connection, and Studio failures." href="/docs/troubleshooting" />
</Cards>
