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

# Production self-hosted deployment

> How to deploy and manage a Skald instance for production workflows

This guide will help you deploy a production-ready Skald instance on your own infrastructure.

Spinning up the complete stack so that you have Skald live on domains that you own with SSL certificates should realistically take only 20-30min, but that's with Postgres and RabbitMQ running in Docker. These should ideally be deployed externally and of course configuring those will take more time.

### Pre-requisites

1. A Linux server (x86) with [Docker](https://docs.docker.com/engine/install/ubuntu/) and [Docker Compose](https://docs.docker.com/compose/install/linux/) installed
2. Two domain names (or subdomains) pointing to your server's IP address:
   * One for the API (e.g., `api.yourdomain.com`)
   * One for the UI (e.g., `app.yourdomain.com`)
3. Ports 80 and 443 open on your server

<Info>The last step is easy to forget! Do it right when you spin up your instance to prevent yourself from spending time debugging later.</Info>

### DNS Configuration

Before running the deployment, ensure the following DNS records are configured:

1. Create an A record for your API domain pointing to your server's IP address
2. Create an A record for your UI domain pointing to your server's IP address

Example DNS configuration:

```
skald-api.yourdomain.com    A    123.456.789.0
skald.yourdomain.com        A    123.456.789.0
```

<Tip>If you are using CloudFlare to manage your DNS, make sure to **disable the 'Proxied'** option. A proxied record will not work with our Traefik configuration.</Tip>

### Deployment

Clone the Skald repo:

```bash theme={null}
git clone https://github.com/skaldlabs/skald
```

And then from inside the directory, run the deployment setup script:

```bash theme={null}
./bin/deploy.sh
```

The script will:

1. Prompt you for your API and UI domain names.
2. Request an email address (required for Let's Encrypt SSL certificates).
3. Prompt you for the environment variables required to run Skald (e.g. API keys). Check out the [Configuration](/docs/self-host/intro#configuration) section on the Intro page if you want to understand these better.
4. Verify your DNS configuration.
5. Generate secure credentials (e.g. Django's SECRET\_KEY, Postgres password).
6. Set up a .env.prod file to be used when deploying the stack.

After you're done with the setup, run the following command to start the stack in detached mode:

```sh theme={null}
docker compose -f docker-compose.selfhosted.yml --env-file .env.prod up -d
```

### Managing Your Deployment

#### View logs

```bash theme={null}
docker compose -f docker-compose.selfhosted.yml logs -f
```

View logs for a specific service:

```bash theme={null}
docker compose -f docker-compose.selfhosted.yml logs -f api
```

#### Stop the deployment

```bash theme={null}
docker compose -f docker-compose.selfhosted.yml down
```

#### Restart the deployment

```bash theme={null}
docker compose -f docker-compose.selfhosted.yml --env-file .env.prod up -d
```

#### Update the deployment

To update to the latest version:

```bash theme={null}
# Pull the latest images from DockerHub
docker compose -f docker-compose.selfhosted.yml --env-file .env.prod pull

# Restart services with the new images
docker compose -f docker-compose.selfhosted.yml --env-file .env.prod up -d
```

### What Gets Deployed

The deployment includes:

* **Traefik**: Reverse proxy with automatic SSL certificate generation.
* **PostgreSQL with pgvector**: Our database. `pgvector` support is needed for vector embeddings.
* **RabbitMQ**: Used for communicating between the Django server and the Memo Processing Server.
* **API**: The main Skald API Django server.
* **Memo Processing Server**: Background worker for processing memos.
* **UI**: The web interface.

### Configuration

All configuration is stored in `.env.prod`, which is automatically generated by the deployment script. This file contains:

* Domain names
* Database credentials
* API keys
* Security secrets

### SSL Certificates

SSL certificates are automatically generated and renewed by Let's Encrypt through Traefik. The certificates are stored in a Docker volume (`traefik-certificates`) and will auto-renew before expiration.

### Troubleshooting

#### SSL certificate issues

If you're having trouble with SSL certificates:

1. Ensure ports 80 and 443 are open
2. Verify DNS records are pointing to the correct IP
3. Check Traefik logs: `docker compose -f docker-compose.selfhosted.yml logs traefik`
4. Wait a few minutes -- certificate generation can take some time

#### Service won't start

1. Check service logs: `docker compose -f docker-compose.selfhosted.yml logs <service-name>`
2. Ensure all required environment variables are set in `.env.prod`

#### Cannot connect to API

1. Verify DNS is resolving correctly: `dig your-api-domain.com`
2. Check API logs: `docker compose -f docker-compose.selfhosted.yml logs api`
3. Ensure Traefik is running: `docker compose -f docker-compose.selfhosted.yml ps traefik`

### Backups

To backup your data (if you're not using an external Postgres deployment), you can run the following command (or set it to run on a cron):

```bash theme={null}
docker run --rm -v skald2_postgres_data:/data -v $(pwd):/backup ubuntu tar czf /backup/postgres-backup.tar.gz /data
```

To restore:

```bash theme={null}
docker run --rm -v skald2_postgres_data:/data -v $(pwd):/backup ubuntu tar xzf /backup/postgres-backup.tar.gz -C /
```
