Reverse Proxy Setup

Running Konarr behind a reverse proxy is recommended for production deployments to provide TLS termination, load balancing, and additional security features.

Nginx

Basic Configuration

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

server {
    listen 443 ssl http2;
    server_name konarr.example.com;
    
    # SSL configuration
    ssl_certificate /path/to/certificate.crt;
    ssl_certificate_key /path/to/private.key;
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512:ECDHE-RSA-AES256-GCM-SHA384;
    ssl_prefer_server_ciphers off;
    
    # Security headers
    add_header X-Frame-Options DENY;
    add_header X-Content-Type-Options nosniff;
    add_header X-XSS-Protection "1; mode=block";
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
    
    # Proxy configuration
    location / {
        proxy_pass http://127.0.0.1:9000;
        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;
        proxy_set_header X-Forwarded-Host $host;
        proxy_set_header X-Forwarded-Port $server_port;
        
        # WebSocket support (if needed for future features)
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        
        # Timeouts
        proxy_connect_timeout 30s;
        proxy_send_timeout 30s;
        proxy_read_timeout 30s;
        
        # Buffer settings
        proxy_buffering on;
        proxy_buffer_size 4k;
        proxy_buffers 8 4k;
    }
    
    # API endpoints with longer timeouts for large SBOM uploads
    location ~ ^/api/(snapshots|upload) {
        proxy_pass http://127.0.0.1:9000;
        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;
        
        # Extended timeouts for large uploads
        proxy_connect_timeout 60s;
        proxy_send_timeout 300s;
        proxy_read_timeout 300s;
        
        # Increase client max body size for SBOM uploads
        client_max_body_size 50M;
    }
    
    # Health check endpoint
    location /api/health {
        proxy_pass http://127.0.0.1:9000;
        access_log off;
    }
}

Let's Encrypt with Certbot

Automatically obtain and renew SSL certificates:

# Install certbot
sudo apt update
sudo apt install certbot python3-certbot-nginx

# Obtain certificate
sudo certbot --nginx -d konarr.example.com

# Test automatic renewal
sudo certbot renew --dry-run

Traefik

Docker Compose Configuration

version: '3.8'

services:
  traefik:
    image: traefik:v3.0
    container_name: traefik
    restart: unless-stopped
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - ./traefik.yml:/traefik.yml:ro
      - ./acme.json:/acme.json
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.dashboard.rule=Host(`traefik.example.com`)"
      - "traefik.http.routers.dashboard.tls.certresolver=letsencrypt"

  konarr:
    image: ghcr.io/42bytelabs/konarr:latest
    container_name: konarr
    restart: unless-stopped
    volumes:
      - ./data:/data
      - ./config:/config
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.konarr.rule=Host(`konarr.example.com`)"
      - "traefik.http.routers.konarr.tls.certresolver=letsencrypt"
      - "traefik.http.services.konarr.loadbalancer.server.port=9000"
      # Health check
      - "traefik.http.services.konarr.loadbalancer.healthcheck.path=/api/health"
      - "traefik.http.services.konarr.loadbalancer.healthcheck.interval=30s"

Traefik Configuration (traefik.yml)

api:
  dashboard: true

entryPoints:
  web:
    address: ":80"
    http:
      redirections:
        entrypoint:
          to: websecure
          scheme: https
  websecure:
    address: ":443"

providers:
  docker:
    endpoint: "unix:///var/run/docker.sock"
    exposedByDefault: false

certificatesResolvers:
  letsencrypt:
    acme:
      email: admin@example.com
      storage: acme.json
      httpChallenge:
        entryPoint: web

Caddy

Caddyfile Configuration

konarr.example.com {
    reverse_proxy 127.0.0.1:9000 {
        header_up X-Real-IP {remote_addr}
        header_up X-Forwarded-For {remote_addr}
        header_up X-Forwarded-Proto {scheme}
        
        # Health check
        health_uri /api/health
        health_interval 30s
        health_timeout 10s
    }
    
    # Security headers
    header {
        X-Frame-Options DENY
        X-Content-Type-Options nosniff
        X-XSS-Protection "1; mode=block"
        Strict-Transport-Security "max-age=31536000; includeSubDomains"
    }
    
    # Longer timeouts for API uploads
    @api_uploads path /api/snapshots* /api/upload*
    reverse_proxy @api_uploads 127.0.0.1:9000 {
        timeout 300s
    }
}

Apache HTTP Server

Virtual Host Configuration

<VirtualHost *:80>
    ServerName konarr.example.com
    Redirect permanent / https://konarr.example.com/
</VirtualHost>

<VirtualHost *:443>
    ServerName konarr.example.com
    
    # SSL Configuration
    SSLEngine on
    SSLCertificateFile /path/to/certificate.crt
    SSLCertificateKeyFile /path/to/private.key
    SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1
    SSLCipherSuite ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384
    
    # Security Headers
    Header always set X-Frame-Options DENY
    Header always set X-Content-Type-Options nosniff
    Header always set X-XSS-Protection "1; mode=block"
    Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"
    
    # Proxy Configuration
    ProxyPreserveHost On
    ProxyPass / http://127.0.0.1:9000/
    ProxyPassReverse / http://127.0.0.1:9000/
    
    # Set headers for backend
    ProxyPassReverse / http://127.0.0.1:9000/
    ProxyPassReverseMatch ^(.*)$ http://127.0.0.1:9000$1
    
    SetEnvIf X-Forwarded-Proto https HTTPS=on
</VirtualHost>

HAProxy

Load Balancing Configuration

global
    daemon
    maxconn 4096

defaults
    mode http
    timeout connect 5000ms
    timeout client 50000ms
    timeout server 50000ms

frontend konarr_frontend
    bind *:80
    bind *:443 ssl crt /path/to/certificate.pem
    
    # Redirect HTTP to HTTPS
    redirect scheme https if !{ ssl_fc }
    
    # Security headers
    http-response set-header X-Frame-Options DENY
    http-response set-header X-Content-Type-Options nosniff
    http-response set-header Strict-Transport-Security "max-age=31536000; includeSubDomains"
    
    default_backend konarr_backend

backend konarr_backend
    balance roundrobin
    
    # Health check
    option httpchk GET /api/health
    
    # Backend servers
    server konarr1 127.0.0.1:9000 check
    # server konarr2 127.0.0.1:9001 check  # Additional instances

Security Considerations

Rate Limiting

Configure rate limiting at the reverse proxy level:

Nginx:

# Rate limiting configuration
limit_req_zone $binary_remote_addr zone=api:10m rate=10r/s;
limit_req_zone $binary_remote_addr zone=upload:10m rate=1r/s;

location /api/ {
    limit_req zone=api burst=20 nodelay;
}

location ~ ^/api/(snapshots|upload) {
    limit_req zone=upload burst=5 nodelay;
}

Traefik:

# Add to service labels
- "traefik.http.middlewares.ratelimit.ratelimit.burst=20"
- "traefik.http.middlewares.ratelimit.ratelimit.average=10"
- "traefik.http.routers.konarr.middlewares=ratelimit"

IP Whitelisting

Restrict access to specific IP ranges:

Nginx:

# Allow specific networks
allow 10.0.0.0/8;
allow 192.168.0.0/16;
allow 172.16.0.0/12;
deny all;

Authentication Middleware

Add basic authentication at the proxy level:

Nginx:

location / {
    auth_basic "Konarr Access";
    auth_basic_user_file /etc/nginx/.htpasswd;
    proxy_pass http://127.0.0.1:9000;
}

Monitoring and Logging

Access Logs

Configure detailed logging for monitoring:

Nginx:

log_format konarr_format '$remote_addr - $remote_user [$time_local] '
                         '"$request" $status $body_bytes_sent '
                         '"$http_referer" "$http_user_agent" '
                         '$request_time $upstream_response_time';

access_log /var/log/nginx/konarr.access.log konarr_format;

Health Checks

Set up monitoring for the reverse proxy and backend:

# Simple health check script
#!/bin/bash
curl -f -s https://konarr.example.com/api/health > /dev/null
if [ $? -eq 0 ]; then
    echo "Konarr is healthy"
    exit 0
else
    echo "Konarr health check failed"
    exit 1
fi

Configuration Notes

Backend URL Configuration

Update Konarr server configuration to use the external URL:

# konarr.yml
server:
  frontend:
    url: "https://konarr.example.com"

CORS Configuration

If needed, configure CORS headers:

# Add CORS headers if required
add_header Access-Control-Allow-Origin "https://trusted-domain.com";
add_header Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS";
add_header Access-Control-Allow-Headers "Authorization, Content-Type";