# TLS/HTTPS Setup Guide

This guide covers setting up TLS/HTTPS for StemeDB API server in production.

## Overview

StemeDB supports TLS 1.3 for encrypted communication. When TLS is enabled:
- All traffic is encrypted using TLS 1.3 (TLS 1.2 and below are disabled)
- Server listens on HTTPS instead of HTTP
- Self-signed certificates work for development
- Let's Encrypt certificates are recommended for production

## Prerequisites

- A domain name pointing to your server (for Let's Encrypt)
- Root or sudo access to install certbot
- Ports 80 and 443 accessible from the internet

## Quick Start (Let's Encrypt)

### 1. Install Certbot

**Ubuntu/Debian:**
```bash
sudo apt update
sudo apt install certbot
```

**RHEL/CentOS:**
```bash
sudo yum install certbot
```

**macOS:**
```bash
brew install certbot
```

### 2. Obtain Certificate

**Standalone mode** (stops existing web servers):
```bash
sudo certbot certonly --standalone -d stemedb.example.com
```

**Webroot mode** (if you have a web server running):
```bash
sudo certbot certonly --webroot -w /var/www/html -d stemedb.example.com
```

Certificates will be stored at:
- **Certificate:** `/etc/letsencrypt/live/stemedb.example.com/fullchain.pem`
- **Private Key:** `/etc/letsencrypt/live/stemedb.example.com/privkey.pem`

### 3. Configure StemeDB

Set environment variables:

```bash
export STEMEDB_TLS_CERT_PATH=/etc/letsencrypt/live/stemedb.example.com/fullchain.pem
export STEMEDB_TLS_KEY_PATH=/etc/letsencrypt/live/stemedb.example.com/privkey.pem
export STEMEDB_BIND_ADDR=0.0.0.0:443
```

Or add to `.env` file:

```bash
STEMEDB_TLS_CERT_PATH=/etc/letsencrypt/live/stemedb.example.com/fullchain.pem
STEMEDB_TLS_KEY_PATH=/etc/letsencrypt/live/stemedb.example.com/privkey.pem
STEMEDB_BIND_ADDR=0.0.0.0:443
```

### 4. Start Server

```bash
# If running as systemd service:
sudo systemctl start stemedb-api

# Or run directly:
sudo ./target/release/stemedb-api
```

**Note:** Port 443 requires root/sudo privileges. Use `sudo` or configure the binary with `setcap`:

```bash
sudo setcap CAP_NET_BIND_SERVICE=+eip /path/to/stemedb-api
```

### 5. Verify HTTPS

```bash
curl https://stemedb.example.com/v1/health
```

Expected response:
```json
{
  "status": "healthy",
  "version": "0.1.0"
}
```

## Self-Signed Certificates (Development)

For local development or testing without a domain name:

### 1. Generate Self-Signed Certificate

```bash
openssl req -x509 -newkey rsa:4096 \
  -keyout key.pem -out cert.pem \
  -days 365 -nodes \
  -subj "/CN=localhost"
```

This creates:
- `cert.pem` - Self-signed certificate
- `key.pem` - Private key

### 2. Configure StemeDB

```bash
export STEMEDB_TLS_CERT_PATH=./cert.pem
export STEMEDB_TLS_KEY_PATH=./key.pem
export STEMEDB_BIND_ADDR=127.0.0.1:443
```

### 3. Test with Curl

```bash
# Accept self-signed cert with -k flag:
curl -k https://localhost:443/v1/health
```

### 4. Import Certificate (Optional)

To avoid `-k` flag, import the certificate:

**macOS:**
```bash
sudo security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain cert.pem
```

**Linux:**
```bash
sudo cp cert.pem /usr/local/share/ca-certificates/stemedb.crt
sudo update-ca-certificates
```

## Certificate Renewal (Let's Encrypt)

Let's Encrypt certificates expire after 90 days. Certbot can auto-renew them.

### Setup Auto-Renewal

**Test renewal:**
```bash
sudo certbot renew --dry-run
```

**Add cron job** (runs twice daily):
```bash
sudo crontab -e
```

Add line:
```
0 0,12 * * * certbot renew --quiet --deploy-hook "systemctl reload stemedb-api"
```

### Manual Renewal

```bash
sudo certbot renew
sudo systemctl reload stemedb-api
```

**Important:** StemeDB needs to be reloaded/restarted after certificate renewal to pick up the new certificate.

## Systemd Service Integration

### Create Service File

`/etc/systemd/system/stemedb-api.service`:

```ini
[Unit]
Description=StemeDB API Server
After=network.target

[Service]
Type=simple
User=stemedb
Group=stemedb
WorkingDirectory=/opt/stemedb
EnvironmentFile=/opt/stemedb/.env
ExecStart=/opt/stemedb/stemedb-api
ExecReload=/bin/kill -HUP $MAINPID
Restart=on-failure
RestartSec=5s

# Security hardening
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=strict
ProtectHome=true
ReadWritePaths=/opt/stemedb/data

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

### Configure Permissions

Let's Encrypt certificates are owned by root. Grant read access to stemedb user:

```bash
# Create stemedb user
sudo useradd -r -s /bin/false stemedb

# Grant read access to certificates
sudo setfacl -R -m u:stemedb:rX /etc/letsencrypt/live
sudo setfacl -R -m u:stemedb:rX /etc/letsencrypt/archive
```

### Enable and Start

```bash
sudo systemctl daemon-reload
sudo systemctl enable stemedb-api
sudo systemctl start stemedb-api
sudo systemctl status stemedb-api
```

## Reverse Proxy with Nginx (Alternative)

Instead of running StemeDB with TLS directly, you can use Nginx as a TLS termination proxy.

### Nginx Configuration

`/etc/nginx/sites-available/stemedb`:

```nginx
server {
    listen 443 ssl http2;
    server_name stemedb.example.com;

    # TLS Configuration
    ssl_certificate /etc/letsencrypt/live/stemedb.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/stemedb.example.com/privkey.pem;
    ssl_protocols TLSv1.3;
    ssl_prefer_server_ciphers off;

    # Proxy to StemeDB (running on localhost:18180 without TLS)
    location / {
        proxy_pass http://127.0.0.1:18180;
        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;

        # Timeouts
        proxy_connect_timeout 30s;
        proxy_send_timeout 30s;
        proxy_read_timeout 30s;
    }
}

# Redirect HTTP to HTTPS
server {
    listen 80;
    server_name stemedb.example.com;
    return 301 https://$server_name$request_uri;
}
```

Enable and reload:

```bash
sudo ln -s /etc/nginx/sites-available/stemedb /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx
```

## Troubleshooting

### Server Won't Start

**Check certificate paths:**
```bash
ls -la $STEMEDB_TLS_CERT_PATH
ls -la $STEMEDB_TLS_KEY_PATH
```

**Verify permissions:**
```bash
sudo -u stemedb cat $STEMEDB_TLS_CERT_PATH > /dev/null
```

If permission denied, grant access:
```bash
sudo setfacl -m u:stemedb:r $STEMEDB_TLS_CERT_PATH
sudo setfacl -m u:stemedb:r $STEMEDB_TLS_KEY_PATH
```

**Check logs:**
```bash
sudo journalctl -u stemedb-api -f
```

### Certificate Expired

```bash
sudo certbot renew --force-renewal
sudo systemctl reload stemedb-api
```

### Clients Can't Connect

**Check firewall:**
```bash
sudo ufw status
sudo ufw allow 443/tcp
```

**Verify DNS:**
```bash
dig stemedb.example.com
```

**Test from external host:**
```bash
curl -v https://stemedb.example.com/v1/health
```

### TLS Handshake Failures

**Check TLS version:**
```bash
openssl s_client -connect stemedb.example.com:443 -tls1_3
```

If connection fails, client may not support TLS 1.3. Verify client TLS support:
```bash
curl --tlsv1.3 https://stemedb.example.com/v1/health
```

## Security Best Practices

1. **Use Strong Certificates**
   - Let's Encrypt certificates are free and automatically renew
   - Minimum 2048-bit RSA keys (4096-bit recommended)

2. **Keep Certificates Updated**
   - Set up auto-renewal
   - Monitor expiration dates
   - Test renewal process regularly

3. **Restrict Private Key Access**
   - Private key should be readable only by stemedb user and root
   - Never commit private keys to version control

4. **Use HTTPS Everywhere**
   - Redirect all HTTP traffic to HTTPS
   - Use HSTS headers to force HTTPS

5. **Monitor Certificate Expiration**
   - Set up alerts for certificate expiration (30 days before)
   - Test renewal process monthly

6. **Audit TLS Configuration**
   - Use [SSL Labs](https://www.ssllabs.com/ssltest/) to test configuration
   - Aim for A+ rating

## See Also

- [Let's Encrypt Documentation](https://letsencrypt.org/docs/)
- [Certbot User Guide](https://eff-certbot.readthedocs.io/)
- [Mozilla SSL Configuration Generator](https://ssl-config.mozilla.org/)
- [StemeDB Operations Guide](../README.md)
