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

# Deployment

> Deploy Control Plane Server to production using Docker Compose or Kubernetes.

Control Plane Server is a self-hosted service. This page covers production deployment options, configuration, and scaling.

## Docker Compose (recommended for small teams)

The quickstart Docker Compose file is suitable for teams up to \~20 active users. For production use, add persistent volumes and point to an external Postgres database.

### Production compose file

```yaml theme={null}
# docker-compose.prod.yml
version: "3.9"

services:
  langship:
    image: lyzrcore/langship:latest
    ports:
      - "3000:3000"
    environment:
      DATABASE_URL: postgresql://user:pass@postgres:5432/langship
      REDIS_URL: redis://redis:6379
      SECRET_KEY: ${SECRET_KEY}         # generate with: openssl rand -hex 32
      LANGSHIP_BASE_URL: https://langship.yourcompany.com
    depends_on:
      - postgres
      - redis
    volumes:
      - langship-data:/app/data
    restart: always

  collector:
    image: lyzrcore/langship-collector:latest
    ports:
      - "4317:4317"    # OTLP gRPC
      - "4318:4318"    # OTLP HTTP
    environment:
      LANGSHIP_SERVER_URL: http://langship:3000
    restart: always

  postgres:
    image: postgres:15
    environment:
      POSTGRES_DB: langship
      POSTGRES_USER: ${POSTGRES_USER}
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
    volumes:
      - postgres-data:/var/lib/postgresql/data
    restart: always

  redis:
    image: redis:7-alpine
    volumes:
      - redis-data:/data
    restart: always

volumes:
  langship-data:
  postgres-data:
  redis-data:
```

Start:

```bash theme={null}
SECRET_KEY=$(openssl rand -hex 32) \
POSTGRES_USER=langship \
POSTGRES_PASSWORD=$(openssl rand -hex 16) \
docker compose -f docker-compose.prod.yml up -d
```

### Running database migrations

After first start or on upgrade:

```bash theme={null}
docker compose exec langship langship-server migrate
```

## Kubernetes

For larger deployments or teams that already run Kubernetes, use the Helm chart:

```bash theme={null}
helm repo add langship https://lyzrcore.github.io/langship-helm
helm repo update

helm install langship langship/langship \
  --namespace langship \
  --create-namespace \
  --set config.secretKey="$(openssl rand -hex 32)" \
  --set postgresql.enabled=true \
  --set redis.enabled=true
```

### Custom values

Create `values.yaml`:

```yaml theme={null}
replicaCount: 2

config:
  baseUrl: "https://langship.yourcompany.com"
  secretKey: "your-secret-key"

postgresql:
  enabled: false               # use external Postgres
  external:
    host: "your-postgres-host"
    database: "langship"
    username: "langship"
    password: "your-password"

redis:
  enabled: true

ingress:
  enabled: true
  className: nginx
  hosts:
    - host: langship.yourcompany.com
      paths:
        - path: /
          pathType: Prefix
  tls:
    - secretName: langship-tls
      hosts:
        - langship.yourcompany.com

collector:
  enabled: true
  replicaCount: 2
```

Apply:

```bash theme={null}
helm upgrade --install langship langship/langship \
  --namespace langship \
  -f values.yaml
```

## Environment variables

| Variable                   | Required | Description                                          |
| -------------------------- | -------- | ---------------------------------------------------- |
| `DATABASE_URL`             | Yes      | PostgreSQL connection string                         |
| `REDIS_URL`                | Yes      | Redis connection string                              |
| `SECRET_KEY`               | Yes      | 32-byte hex secret for session signing               |
| `LANGSHIP_BASE_URL`        | Yes      | Public URL of the server (used in webhook callbacks) |
| `SMTP_HOST`                | No       | SMTP server for email notifications                  |
| `SMTP_PORT`                | No       | SMTP port (default 587)                              |
| `SMTP_USER`                | No       | SMTP username                                        |
| `SMTP_PASSWORD`            | No       | SMTP password                                        |
| `OTEL_FORWARD_URL`         | No       | Forward traces to an additional OTLP endpoint        |
| `MAX_TRACE_RETENTION_DAYS` | No       | Auto-delete traces older than N days (default: 90)   |

## Upgrading

```bash theme={null}
# Docker Compose
docker compose pull
docker compose up -d
docker compose exec langship langship-server migrate

# Kubernetes
helm repo update
helm upgrade langship langship/langship --namespace langship -f values.yaml
```

Always run migrations after upgrading. Migrations are backward-compatible; the server handles rolling upgrades without downtime.

## Backups

Back up the Postgres database on a regular schedule:

```bash theme={null}
pg_dump -h localhost -U langship langship | gzip > langship-backup-$(date +%Y%m%d).sql.gz
```

Control Plane does not store credentials, API keys, or OAuth tokens; it stores only traces, datasets, and eval results.

## Connecting your SDK to a self-hosted server

Point the SDK at your server URL:

```python theme={null}
langship.init(
    endpoint="https://langship.yourcompany.com",
    api_key="your-api-key",    # generated in the Control Plane dashboard
    project="my-agent"
)
```

Or via environment variables:

```bash theme={null}
export LANGSHIP_ENDPOINT=https://langship.yourcompany.com
export LANGSHIP_API_KEY=your-api-key
export LANGSHIP_PROJECT=my-agent
```

When environment variables are set, `langship.init()` with no arguments picks them up automatically.
