# Self-Hosting

{% hint style="success" %}
Self-hosting is available with the [**Advanced plan**](https://slingdata.io/platform/#pricing). This feature allows you to deploy the entire Sling Platform within your private network for full control and security. **Start your 10-day trial at** [**https://dash.slingdata.io/self-platform**](https://dash.slingdata.io/self-platform)**, no credit card needed!**
{% endhint %}

## Overview

Self-hosting Sling Platform enables organizations to:

* Maintain complete control over data and infrastructure
* Meet strict compliance and security requirements
* Deploy in air-gapped or private environments
* Customize deployment configurations

The `slingdata/sling-platform` image provides a self-hosted Sling data platform for managing data pipelines, connections, and agents.

## Quick Start

Run below and access on <http://localhost:7878>:

```bash
docker run -d \
  -p 7878:7878 \
  -p 4443:4443 \
  -e SLING_PLATFORM_LICENSE="your-license-key" \
  -e SLING_PLATFORM_ENCRYPTION_KEY="your-32-char-encryption-key" \
  -e SLING_PLATFORM_ADMIN_CREDENTIALS='{"email":"admin@example.com","password":"your-secure-password"}' \
  -v sling-platform-data:/home/sling \
  slingdata/sling-platform:latest
```

## Required Environment Variables

* **`SLING_PLATFORM_LICENSE`** - Your Sling Platform license key. This can be either a 36-character UUID for cloud-verified licenses or an offline license token for air-gapped environments. Obtain a trial key from <https://dash.slingdata.io/self-platform> (no credit card needed).
* **`SLING_PLATFORM_ENCRYPTION_KEY`** - A 32-character encryption key used to encrypt sensitive data like connection credentials. Generate a secure random string (`openssl rand -hex 16`).
* **`SLING_PLATFORM_ADMIN_CREDENTIALS`** - JSON payload containing the initial admin user credentials. need `email` and `password` keys.

{% hint style="success" %}
**Air-Gapped/Offline License**: By default, license tokens are validated through CloudFlare's global network for high reliability and fast response times. If you require an air-gapped or high-security environment, we offer offline license tokens that don't require internet connectivity for validation. These require yearly renewal by default, but perpetual licenses are also available. Please contact <support@slingdata.io> to request a quote.
{% endhint %}

## Optional Environment Variables

* **`SLING_PLATFORM_HOST`** - The external URL where your platform will be accessible. This is used for agent connections and web UI access. The default is `http://localhost:7878`
* **`SLING_PLATFORM_SMTP_CREDENTIALS`** - SMTP configuration for email notifications. If your SMTP service requires SSL, specify the optional `security` key with the value `SSL`. If not provided, email notifications will be disabled. For example: `{"host":"smtp.gmail.com","port":587,"user":"your-email@gmail.com","password":"your-app-password","from":"Sling Platform <noreply@yourdomain.com>", "security": "SSL"}`
* **SLING\_LOGGING** - The default logger uses ANSI colors. You can change this if you'd like, accepts values: `NO_COLOR` or `JSON`.

## Connecting Agents

To connect Sling agents to your platform, use the `slingdata/sling` image with these environment variables:

```bash
docker run -d \
  -e SLING_PLATFORM_HOST="http://your-platform-host:7878" \
  -e SLING_AGENT_KEY="your-agent-key-from-platform-ui" \
  -v sling-agent-data:/home/sling \
  slingdata/sling agent run
```

### Agent Environment Variables

* **`SLING_AGENT_KEY`** - Agent authentication key obtained from the platform UI under Agents section
* **`SLING_PLATFORM_HOST`** - Same URL as your platform instance
* **`SLING_PLATFORM_HOST_WS`** - Optional, the web-socket host to use for NATS connection, e.g. `ws://your-platform-host:4443`. Default uses the same host as `SLING_PLATFORM_HOST`.

## Docker Compose Example

```yaml
services:
  sling-platform:
    image: slingdata/sling-platform
    ports:
      - "7878:7878"  # HTTP port for UI and API
      - "4443:4443"  # NATS WebSocket port for agent communication
    expose:
      - "7878"
      - "9876" # Postgres port accessible with user `sling`
      - "4443"
    environment:
      SLING_PLATFORM_LICENSE: "your-license-key"
      SLING_PLATFORM_ENCRYPTION_KEY: "your-32-char-encryption-key"
      SLING_PLATFORM_ADMIN_CREDENTIALS: '{"email":"admin@example.com","password":"secure-password"}'
      SLING_PLATFORM_HOST: "http://external.ip:7878"  # External URL for web UI access
      SLING_PLATFORM_SMTP_CREDENTIALS: '{"host":"smtp.gmail.com","port":587,"user":"your-email","password":"your-password","from":"Sling <noreply@yourdomain.com>"}'
    volumes:
      - sling-platform-data:/home/sling
    restart: unless-stopped
    
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:7878/status/get"]
      interval: 5s
      timeout: 2s
      retries: 3

  # Add Agent(s) as needed
  # sling-agent:
  #   image: slingdata/sling:latest
  #   environment:
  #     SLING_PLATFORM_HOST: "http://sling-platform:7878"  # Internal container communication
  #     SLING_AGENT_KEY: "your-agent-key"
  #   command: agent run
  #   volumes:
  #     - sling-agent-data:/home/sling
  #   depends_on:
  #     - sling-platform
  #   restart: unless-stopped

volumes:
  sling-platform-data:
  sling-agent-data:
```

## Ports

* **7878** - Main HTTP port for web UI and API access
* **4443** - Web-Socket port for agent communication (via NATS)

## Volumes

* `/home/sling` - Platform data directory.

{% hint style="info" %}
**Embedded Database**: The sling-platform container includes an embedded PostgreSQL database. Database files are stored under `/home/sling/platform/postgres` within the container. This database is accessible on port 9876 with username `sling` (read-only) and password `pgpass.$PREFIX`, where `$PREFIX` is the first 6 characters of `SLING_PLATFORM_ENCRYPTION_KEY`. The database name is `sling_platform`.

Here is the env var to have Sling read from the Platform database (replace `$PREFIX` and `$SLING_PLATFORM_HOST`): `SLING_PLATFORM_DB='postgresql://sling:pgpass.$PREFIX@$SLING_PLATFORM_HOST:9876/sling_platform?sslmode=disable'`
{% endhint %}

## Custom Agent Docker Image

If you need to build your own custom Sling agent Docker image (for example, to include additional dependencies or configurations), you can use the official Dockerfiles as a starting point:

* **AMD64 Architecture**: [Dockerfile](https://github.com/slingdata-io/sling-cli/blob/main/cmd/sling/Dockerfile)
* **ARM64 Architecture**: [Dockerfile.arm64](https://github.com/slingdata-io/sling-cli/blob/main/cmd/sling/Dockerfile.arm64)

See [here](/sling-platform/platform/agents.md#custom-agent-docker-image) for an example.

## Getting Started

1. Start the platform container with required environment variables
2. Access the web UI at your configured `SLING_PLATFORM_HOST`
3. Log in with your admin credentials
4. Create agent keys in the Agents section
5. Deploy agents using the `slingdata/sling` image
6. Start creating connections and data pipelines

## Security Notes

* Use strong, unique values for `SLING_PLATFORM_ENCRYPTION_KEY` (32 characters)
* Store sensitive environment variables securely
* Use HTTPS in production environments

## Support

For support, reach out to <support@slingdata.io>.

## Kubernetes

```yaml
# Namespace
apiVersion: v1
kind: Namespace
metadata:
  name: sling-platform
---
# ConfigMap for environment variables
apiVersion: v1
kind: ConfigMap
metadata:
  name: sling-platform-config
  namespace: sling-platform
data:
  SLING_PLATFORM_HOST: "http://external.ip:8080"  # Update with your actual external IP/domain
---
# Secret for sensitive environment variables
apiVersion: v1
kind: Secret
metadata:
  name: sling-platform-secrets
  namespace: sling-platform
type: Opaque
stringData:
  SLING_PLATFORM_LICENSE: "your-license-key"
  SLING_PLATFORM_ENCRYPTION_KEY: "your-32-char-encryption-key"
  SLING_PLATFORM_ADMIN_CREDENTIALS: '{"email":"admin@example.com","password":"secure-password"}'
  SLING_PLATFORM_SMTP_CREDENTIALS: '{"host":"smtp.gmail.com","port":587,"user":"your-email","password":"your-password","from":"Sling <noreply@yourdomain.com>"}'
  SLING_AGENT_KEY: "your-agent-key"
---
# PersistentVolumeClaim for platform data
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: sling-platform-data
  namespace: sling-platform
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 25Gi
  # storageClassName: your-storage-class  # Uncomment and specify if needed
---
# PersistentVolumeClaim for agent data
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: sling-agent-data
  namespace: sling-platform
spec:
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 5Gi
  # storageClassName: your-storage-class  # Uncomment and specify if needed
---
# Sling Platform Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
  name: sling-platform
  namespace: sling-platform
  labels:
    app: sling-platform
spec:
  replicas: 1
  selector:
    matchLabels:
      app: sling-platform
  template:
    metadata:
      labels:
        app: sling-platform
    spec:
      securityContext:
        fsGroup: 999
        runAsUser: 999
      containers:
      - name: sling-platform
        image: slingdata/sling-platform:latest
        imagePullPolicy: Always
        ports:
        - containerPort: 7878
          name: http
          protocol: TCP
        - containerPort: 4443
          name: nats
          protocol: TCP
        - containerPort: 9876
          name: postgres
          protocol: TCP
        env:
        - name: SLING_PLATFORM_HOST
          valueFrom:
            configMapKeyRef:
              name: sling-platform-config
              key: SLING_PLATFORM_HOST
        - name: SLING_PLATFORM_LICENSE
          valueFrom:
            secretKeyRef:
              name: sling-platform-secrets
              key: SLING_PLATFORM_LICENSE
        - name: SLING_PLATFORM_ENCRYPTION_KEY
          valueFrom:
            secretKeyRef:
              name: sling-platform-secrets
              key: SLING_PLATFORM_ENCRYPTION_KEY
        - name: SLING_PLATFORM_ADMIN_CREDENTIALS
          valueFrom:
            secretKeyRef:
              name: sling-platform-secrets
              key: SLING_PLATFORM_ADMIN_CREDENTIALS
        - name: SLING_PLATFORM_SMTP_CREDENTIALS
          valueFrom:
            secretKeyRef:
              name: sling-platform-secrets
              key: SLING_PLATFORM_SMTP_CREDENTIALS
              optional: true
        volumeMounts:
        - name: platform-data
          mountPath: /home/sling
        resources:
          requests:
            memory: "512Mi"
            cpu: "250m"
          limits:
            memory: "4Gi"
            cpu: "2"
      volumes:
      - name: platform-data
        persistentVolumeClaim:
          claimName: sling-platform-data
      restartPolicy: Always
---
# Sling Platform Service
apiVersion: v1
kind: Service
metadata:
  name: sling-platform
  namespace: sling-platform
  labels:
    app: sling-platform
spec:
  type: ClusterIP
  ports:
  - port: 7878
    targetPort: 7878
    protocol: TCP
    name: http
  - port: 4443
    targetPort: 4443
    protocol: TCP
    name: nats
  - port: 9876
    targetPort: 9876
    protocol: TCP
    name: postgres
  selector:
    app: sling-platform
---
# Sling Agent Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
  name: sling-agent
  namespace: sling-platform
  labels:
    app: sling-agent
spec:
  # Each agent requires a unique SLING_AGENT_KEY, so this deployment must have replicas: 1
  # To deploy additional agents, duplicate this deployment with a new name and a different SLING_AGENT_KEY
  replicas: 1  
  selector:
    matchLabels:
      app: sling-agent
  template:
    metadata:
      labels:
        app: sling-agent
    spec:
      containers:
      - name: sling-agent
        image: slingdata/sling:latest
        imagePullPolicy: Always
        args: ["agent", "run"]
        env:
        - name: SLING_PLATFORM_HOST
          value: "http://sling-platform:7878"
        - name: SLING_AGENT_KEY
          valueFrom:
            secretKeyRef:
              name: sling-platform-secrets
              key: SLING_AGENT_KEY
        volumeMounts:
        - name: agent-data
          mountPath: /home/sling
        resources:
          requests:
            memory: "256Mi"
            cpu: "100m"
          limits:
            memory: "8Gi"
            cpu: "4"
      volumes:
      - name: agent-data
        persistentVolumeClaim:
          claimName: sling-agent-data
      restartPolicy: Always
```

## Troubleshooting

### Common Issues

1. **Platform won't start**
   * Check container logs: `docker logs sling-platform`
   * Verify environment variables are set correctly
   * Ensure data volume has sufficient permissions
2. **Agents not connecting**
   * Verify network connectivity between agent and platform
   * Check agent key is valid and properly set
   * Ensure platform URL is accessible from agent
   * Review agent logs for error messages
3. **Performance issues**
   * Increase resource limits (CPU/memory)
   * Scale agents horizontally for more concurrent jobs
   * Monitor disk space for data volume

### Getting Help

If you are facing issues setting up, please reach out to us at <support@slingdata.io>, on [discord](https://discord.gg/q5xtaSNDvp) or open a Github Issue [here](https://github.com/slingdata-io/sling-cli/issues).

{% hint style="warning" %}
Self-hosting requires careful consideration of security, backup, and maintenance procedures. Ensure your team has the necessary expertise to manage the deployment.
{% endhint %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.slingdata.io/sling-platform/platform/self-hosting.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
