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

# Production Deployment

> Run SlackHive as a long-lived service - systemd/launchd, reverse proxy, SQLite backup, key rotation.

For production use, you want SlackHive to survive reboots, serve HTTPS, and get backed up. This page covers the operational recipe on top of the standard CLI install.

If you haven't installed yet, start with [Install with the CLI](/getting-started/install-cli).

## Security checklist

Before exposing SlackHive to a production network:

* [ ] Strong `ADMIN_PASSWORD` in `.env` (regenerate if it was auto-filled during testing)
* [ ] `AUTH_SECRET` and `ENV_SECRET_KEY` generated with `openssl rand -hex 32` (`slackhive init` does this automatically)
* [ ] `NODE_ENV=production` in `.env`
* [ ] Reverse proxy terminating TLS - never expose port 3001 directly
* [ ] `.env` not in version control
* [ ] MCP secrets stored in **Settings → Env Vars** (encrypted), not in plain MCP config `env` fields
* [ ] `~/.slackhive/` directory permissions limited to the runtime user

## Run as a service

### macOS - launchd

Create `~/Library/LaunchAgents/co.pelago.slackhive.plist`:

```xml theme={null}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
  <dict>
    <key>Label</key>
    <string>co.pelago.slackhive</string>
    <key>ProgramArguments</key>
    <array>
      <string>/usr/local/bin/slackhive</string>
      <string>start</string>
    </array>
    <key>RunAtLoad</key>
    <true/>
    <key>KeepAlive</key>
    <true/>
    <key>StandardOutPath</key>
    <string>/tmp/slackhive.out.log</string>
    <key>StandardErrorPath</key>
    <string>/tmp/slackhive.err.log</string>
  </dict>
</plist>
```

Load:

```bash theme={null}
launchctl load ~/Library/LaunchAgents/co.pelago.slackhive.plist
```

### Linux - systemd

For Claude subscription auth on Linux, make sure the service user has access to either:

* A running keyring daemon (`secret-tool` works for that user), **or**
* A pre-populated `~/.claude/.credentials.json` in the service user's home

Headless servers that use Claude subscription auth almost always want option 2 - run `claude login` once as that user before enabling the service. If you use API-key billing instead, store the relevant key in `.env` or **Settings → AI Backend**.

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

```ini theme={null}
[Unit]
Description=SlackHive
After=network.target

[Service]
Type=simple
User=slackhive
ExecStart=/usr/local/bin/slackhive start
ExecStop=/usr/local/bin/slackhive stop
Restart=on-failure
RestartSec=5

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

Enable:

```bash theme={null}
systemctl daemon-reload
systemctl enable --now slackhive
```

The service runs `slackhive start`, which acquires the singleton lock, negotiates ports, and starts the web + runner. On stop, `slackhive stop` sweeps orphans and unlinks the lock.

## Reverse proxy with nginx

```nginx theme={null}
server {
    listen 443 ssl http2;
    server_name slackhive.example.com;

    ssl_certificate     /etc/ssl/certs/slackhive.crt;
    ssl_certificate_key /etc/ssl/private/slackhive.key;

    location / {
        proxy_pass http://127.0.0.1:3001;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;

        # Required for live logs (SSE)
        proxy_buffering off;
        proxy_cache off;
        proxy_read_timeout 3600s;
    }
}
```

<Note>
  `proxy_buffering off` is required for the live logs stream - otherwise the UI shows log lines in lumps instead of real time.
</Note>

## Reverse proxy with Caddy

```caddyfile theme={null}
slackhive.example.com {
    reverse_proxy 127.0.0.1:3001 {
        flush_interval -1
    }
}
```

`flush_interval -1` disables buffering for SSE.

## Change the web port

`slackhive init` picks `3001` by default and auto-negotiates if taken. To pin a different port, set `PORT` in `.env`:

```bash theme={null}
PORT=8080
```

Then restart:

```bash theme={null}
slackhive stop
slackhive start
```

## Backup and recovery

SQLite CLI installs include built-in database backups.

Default behavior:

| Setting           | Default                 |
| ----------------- | ----------------------- |
| Automatic backups | Enabled                 |
| Schedule          | Every 24 hours          |
| Retention         | Keep latest 5 backups   |
| Location          | `~/.slackhive/backups/` |

SlackHive creates consistent live snapshots with SQLite `VACUUM INTO`, so scheduled backups can run while agents are active.

Use **Settings -> Backups** to:

* Enable or disable scheduled backups
* Change the backup interval and retention count
* Trigger **Back up now**
* Download backup files
* Export the password-protected recovery key

From the CLI:

```bash theme={null}
slackhive backup
slackhive restore -f ~/.slackhive/backups/data-20260629-093000.db \
  --recovery-key ~/Downloads/slackhive-recovery-20260629-093100.json
slackhive start
```

<Warning>
  A database backup is not enough to recover encrypted Slack tokens, MCP env vars, and backend credentials. Export the recovery-key file and store its password separately from the backup.
</Warning>

See [Backup & Recovery](/operations/backup-recovery) for the full restore flow, safety snapshots, recovery-key handling, and optional host-level artifacts.

## Update

```bash theme={null}
slackhive update
```

`update` runs `git pull`, reinstalls dependencies, rebuilds, and restarts. Your `data.db` is preserved.

Review [releases](https://github.com/pelago-labs/slackhive/releases) before updating in production. Database migrations run automatically on the next start.

## Resource requirements

Minimum recommended for a small team (5–10 agents, moderate traffic):

| Resource | Minimum | Recommended |
| -------- | ------- | ----------- |
| CPU      | 2 cores | 4 cores     |
| RAM      | 2 GB    | 4 GB        |
| Disk     | 10 GB   | 20 GB       |

Each active agent maintains a Slack Bolt Socket Mode connection. Memory scales with the number of active agents and the size of their assigned MCP processes.

## Key rotation

### `AUTH_SECRET`

Rotating invalidates every active session - everyone is logged out.

1. Generate: `openssl rand -hex 32`
2. Update `.env`
3. Restart: `slackhive stop && slackhive start`

### `ENV_SECRET_KEY`

Rotating makes every stored secret unreadable. You must re-enter each secret after rotation.

1. Export every value from **Settings → Env Vars** by hand (the API never returns plaintext)
2. Generate: `openssl rand -hex 32`
3. Update `.env`
4. Restart: `slackhive stop && slackhive start`
5. Paste each secret back into **Settings → Env Vars**

Plan the rotation during off-hours - MCP servers referencing `${env:NAME}` will fail between steps 3 and 5.

## Monitoring

SlackHive doesn't ship built-in metrics or alerting. For production monitoring:

* **Live Logs** tab in the UI - real-time diagnostics
* **Runner log** - `~/.slackhive/logs/runner.log` streams JSON-per-line; pipe to Loki, Datadog, CloudWatch
* **Health check** - `curl http://127.0.0.1:3001/api/health` returns 200 when the stack is live
* **Status command** - `slackhive status` reports process state and ports
