# Remote Docker deployment

> Source: https://docs.clonepartner.com/deployment/remote-docker/

The standard remote topology uses `docker-compose.remote.yml` to run two containers from the same customer image:

```mermaid Remote Docker topology
flowchart LR
  browser["Browser"] --> proxy["HTTPS reverse proxy"]
  proxy --> cp["Control plane :3000"]
  cp <--> ex["Executor :9090"]
  cp --> state["state volume"]
  cp --> data["data and dbs volumes"]
  ex --> data
```

The published control-plane port binds to `127.0.0.1` by default. Put Caddy, Nginx, or another reverse proxy on the host and expose only HTTPS.

## Host prerequisites

- A supported Linux host with Docker and Docker Compose.
- SSH access for the supplied deployment script.
- Enough disk for state, data files, connector databases, logs, and image updates.
- Outbound network access from the executor to sources and destinations.
- A DNS name and HTTPS reverse proxy.
- Access to the Envoy image registry supplied through your ClonePartner delivery channel.

The repository deployment script also requires Bun and Docker on the build machine.

## Persistent directories

The default compose file maps:

```text
/opt/envoy/state  -> /app/state
/opt/envoy/data   -> /app/data
/opt/envoy/dbs    -> /app/dbs
```

Create and permission these directories for the container user before first boot. The compose hardening drops Linux capabilities; incorrect bind-mount ownership will cause writes to fail.

## Required keys

Set two independent high-entropy values:

```dotenv
ENVOY_ENCRYPTION_KEY=<application-secret-encryption-key>
ENVOY_EXECUTOR_KEY=<control-plane-executor-shared-key>
```

Do not reuse either key for another deployment. Keep the encryption key with backups.

## Deploy with the supplied script

The repository script builds the customer binary and UI, builds and pushes an image, then deploys through SSH:

```bash
./scripts/deploy-remote.sh
```

Supported deployment controls include:

```bash
FORCE_DEPLOY=true ./scripts/deploy-remote.sh
DEPLOY_SCOPE=cp ./scripts/deploy-remote.sh
DEPLOY_SCOPE=ex ./scripts/deploy-remote.sh
SKIP_BUILD=true ./scripts/deploy-remote.sh
```

Set `DEPLOY_ENV_FILE` when your delivery contains more than one deployment environment. Keep that file outside version control because it may contain registry and database credentials.

The script checks active executor leases before an executor restart. If runs are active, wait for them to finish or explicitly use the script's drain mode:

```bash
WAIT_FOR_DRAIN=true ./scripts/deploy-remote.sh
```

## State choices

### SQLite

SQLite is the default remote state backend. The server database lives under `/app/state`; run logs can be stored in the same database with `ENVOY_LOG_STORE=db`.

Optional Litestream replication is enabled only when the required S3-compatible settings are present. See [Backups and upgrades](/deployment/backups-and-upgrades).

### PostgreSQL

Set the state or log backend to PostgreSQL only with a valid connection string:

```dotenv
ENVOY_STORE_TYPE=postgres
ENVOY_LOG_STORE=postgres
ENVOY_POSTGRES_CONNECTION_STRING=postgres://...
ENVOY_POSTGRES_SSL=require
```

Litestream is skipped when the state backend is not SQLite. Use the database provider's backup and recovery controls.

## Executor hardening

The executor service uses:

- `no-new-privileges`;
- all Linux capabilities dropped;
- a read-only root filesystem;
- writable tmpfs scratch paths;
- bounded process and memory limits.

Because the root filesystem is read-only, configure file connectors with absolute paths under `/app/data` or `/app/dbs`.

## Public dashboard controls

Remote Docker passes three independent controls:

- `ENVOY_PUBLIC_DASHBOARDS_ENABLED` for share-link viewing;
- `ENVOY_PUBLIC_DASHBOARD_INPUT_ENABLED` for editing dashboard inputs;
- `ENVOY_PUBLIC_DASHBOARD_ACTIONS_ENABLED` for approved public actions.

Viewing defaults on in the current remote compose path, while public input editing and public actions default off. Keep the write controls off unless a reviewed dashboard requires them.

## Verify the deployment

1. Open the HTTPS URL and complete [First-time setup](/getting-started/first-time-setup).
2. Check **Settings** for server health.
3. Check **Executors** for a healthy heartbeat and expected capacity.
4. Test one non-destructive connector.
5. Run a bounded task and inspect its logs.

Do not use `docker compose down -v` during routine operations. It deletes persistent volumes when named volumes are in use and is not an upgrade command.
