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

# Deploying

> Run LiteJoin in production with Docker, systemd, or Kubernetes.

# Deploying a Pipeline

Once you have a `litejoin.yaml` config (created manually or exported from [Studio](/getting-started/studio)), deploying LiteJoin is straightforward.

## CLI

The simplest deployment — run the binary directly:

```bash theme={null}
litejoin run -c litejoin.yaml
```

LiteJoin runs in the foreground, stores data in `./data/`, and logs to stdout.

## Docker

### Dockerfile

```dockerfile theme={null}
FROM golang:1.24-alpine AS build
RUN apk add --no-cache gcc musl-dev
WORKDIR /app
COPY . .
RUN CGO_ENABLED=1 go build -o litejoin ./cmd/litejoin

FROM alpine:3.21
RUN apk add --no-cache ca-certificates
COPY --from=build /app/litejoin /usr/local/bin/
COPY litejoin.yaml /etc/litejoin/litejoin.yaml
ENTRYPOINT ["litejoin", "run", "-c", "/etc/litejoin/litejoin.yaml"]
```

### Docker Compose

```yaml theme={null}
version: "3.8"
services:
  litejoin:
    build: .
    ports:
      - "9100:9100"  # SSE sink
      - "8080:8080"  # HTTP source
    volumes:
      - litejoin-data:/data
    environment:
      - STRIPE_SECRET_KEY=${STRIPE_SECRET_KEY}
      - GITHUB_TOKEN=${GITHUB_TOKEN}

volumes:
  litejoin-data:
```

<Warning>
  LiteJoin uses SQLite, which requires a persistent volume. Data is lost if the container restarts without a volume mount. For crash recovery, enable [Litestream replication](/operations/replication).
</Warning>

## systemd

Create `/etc/systemd/system/litejoin.service`:

```ini theme={null}
[Unit]
Description=LiteJoin Stream Engine
After=network.target

[Service]
Type=simple
User=litejoin
ExecStart=/usr/local/bin/litejoin run -c /etc/litejoin/litejoin.yaml
WorkingDirectory=/var/lib/litejoin
Restart=always
RestartSec=5

# Environment variables for secrets
EnvironmentFile=/etc/litejoin/env

[Install]
WantedBy=multi-user.target
```

```bash theme={null}
sudo systemctl enable litejoin
sudo systemctl start litejoin
sudo journalctl -u litejoin -f
```

## Kubernetes

```yaml theme={null}
apiVersion: apps/v1
kind: Deployment
metadata:
  name: litejoin
spec:
  replicas: 1  # Single writer — do not scale horizontally
  selector:
    matchLabels:
      app: litejoin
  template:
    metadata:
      labels:
        app: litejoin
    spec:
      containers:
        - name: litejoin
          image: your-registry/litejoin:latest
          ports:
            - containerPort: 9100
            - containerPort: 8080
          volumeMounts:
            - name: data
              mountPath: /data
          env:
            - name: STRIPE_SECRET_KEY
              valueFrom:
                secretKeyRef:
                  name: litejoin-secrets
                  key: stripe-key
      volumes:
        - name: data
          persistentVolumeClaim:
            claimName: litejoin-data
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: litejoin-data
spec:
  accessModes: [ReadWriteOnce]
  resources:
    requests:
      storage: 10Gi
```

<Note>
  LiteJoin is a **single-writer** system. Do not run multiple replicas writing to the same data directory. For high availability, use [Litestream replication](/operations/replication) with restore-on-startup.
</Note>

## Environment Variables

LiteJoin config files support `${ENV_VAR}` expansion for secrets:

```yaml theme={null}
sources:
  - name: stripe
    type: api
    api:
      headers:
        Authorization: "Bearer ${STRIPE_SECRET_KEY}"
```

Set environment variables before starting LiteJoin. Never commit secrets to config files.

## Health Checks

The SSE sink exposes a `/health` endpoint:

```bash theme={null}
curl http://localhost:9100/health
# {"status": "ok"}
```

Use this for Docker `HEALTHCHECK`, Kubernetes liveness probes, and load balancer health checks.
