Skip to main content
HTTPS is strongly recommended for production deployments. It protects session cookies and prevents man-in-the-middle attacks on your analytics data.

Why HTTPS Matters for Sparklytics

Analytics collection endpoints (/api/collect) transmit:
  • Pageview URLs (may contain sensitive paths)
  • Referrer information
  • Custom event properties
HTTPS prevents interception and tampering.
Many browsers require HTTPS for:
  • localStorage access (used by SDK for visitor ID)
  • Service workers (future features)
  • Secure contexts for newer JavaScript APIs

Automatic HTTPS with Caddy

Caddy obtains and renews certificates automatically — zero manual configuration required.

Setup

1

Download Caddy configuration

curl -O https://raw.githubusercontent.com/Sparklytics/sparklytics/main/docker-compose.caddy.yml
curl -O https://raw.githubusercontent.com/Sparklytics/sparklytics/main/Caddyfile
2

Edit Caddyfile

Replace analytics.example.com with your domain:
analytics.yourdomain.com {
    reverse_proxy sparklytics:3000
}
3

Configure DNS

Point your domain to your server’s IP:
analytics.yourdomain.com  A  203.0.113.10
Wait for DNS propagation (can take up to 48 hours, usually minutes).
4

Start services

docker compose -f docker-compose.caddy.yml up -d
Caddy automatically:
  • Obtains a Let’s Encrypt certificate
  • Configures HTTPS on port 443
  • Redirects HTTP (port 80) to HTTPS
  • Renews certificates before expiry
5

Verify certificate

Visit https://analytics.yourdomain.comCheck:
  • Browser shows padlock icon
  • Certificate issuer: Let’s Encrypt
  • Valid expiry date (90 days from issue)

How Caddy Handles Certificates

  • Challenge type: HTTP-01 (requires port 80 accessible)
  • Storage: Certificates stored in Docker volume caddy-data
  • Renewal: Automatic, checks daily, renews at 30 days before expiry
  • Rate limits: Let’s Encrypt allows 50 certificates per domain per week

Manual HTTPS with Certbot (Nginx/Standalone)

For Nginx or standalone deployments without Caddy.

Install Certbot

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

Obtain Certificate with Nginx Plugin

1

Ensure Nginx is running

sudo systemctl status nginx
2

Run Certbot

sudo certbot --nginx -d analytics.example.com
Certbot will:
  • Verify domain ownership via HTTP-01 challenge
  • Obtain certificate from Let’s Encrypt
  • Automatically modify your Nginx config
  • Set up HTTP to HTTPS redirect
3

Test automatic renewal

sudo certbot renew --dry-run
If successful, certificates will auto-renew via systemd timer.

Standalone Mode (Without Nginx Plugin)

If you want to manually configure Nginx:
sudo certbot certonly --standalone -d analytics.example.com
Certificates will be saved to:
/etc/letsencrypt/live/analytics.example.com/fullchain.pem
/etc/letsencrypt/live/analytics.example.com/privkey.pem
Then update your Nginx config:
server {
    listen 443 ssl http2;
    server_name analytics.example.com;

    ssl_certificate /etc/letsencrypt/live/analytics.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/analytics.example.com/privkey.pem;

    # ... rest of config
}

SSL/TLS Best Practices

Modern TLS Configuration

Caddy (Automatic)

Caddy uses secure defaults automatically. No manual TLS configuration needed.

Nginx (Manual)

ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384';
ssl_prefer_server_ciphers off;

# OCSP Stapling
ssl_stapling on;
ssl_stapling_verify on;
ssl_trusted_certificate /etc/letsencrypt/live/analytics.example.com/chain.pem;

# Session cache
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;

Security Headers

Add these headers to enforce HTTPS and prevent common attacks:

Caddy

analytics.example.com {
    reverse_proxy sparklytics:3000

    header {
        Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
        X-Content-Type-Options "nosniff"
        X-Frame-Options "DENY"
        Referrer-Policy "strict-origin-when-cross-origin"
        Permissions-Policy "geolocation=(), microphone=(), camera=()"
    }
}

Nginx

add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "DENY" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Permissions-Policy "geolocation=(), microphone=(), camera=()" always;

Certificate Renewal

Automatic Renewal

Caddy handles renewal automatically. Check logs to verify:
docker logs caddy 2>&1 | grep -i "certificate"

Manual Renewal

To force renewal immediately:
sudo certbot renew --force-renewal
sudo systemctl reload nginx

Custom/Self-Signed Certificates

For internal deployments or testing.

Generate Self-Signed Certificate

openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
  -keyout /etc/ssl/private/sparklytics-selfsigned.key \
  -out /etc/ssl/certs/sparklytics-selfsigned.crt \
  -subj "/CN=analytics.internal.company.com"

Use with Nginx

ssl_certificate /etc/ssl/certs/sparklytics-selfsigned.crt;
ssl_certificate_key /etc/ssl/private/sparklytics-selfsigned.key;
Browsers will show security warnings for self-signed certificates. Only use for internal/testing environments.

Troubleshooting

Error: too many certificates already issuedSolution:
  • Wait one week for rate limit reset
  • Use staging environment for testing: certbot --staging
  • Let’s Encrypt allows 50 certs per domain per week
Error: DNS problem: NXDOMAINSolution:
  • Verify DNS is configured: dig analytics.example.com
  • Wait for DNS propagation (up to 48 hours)
  • Ensure no conflicting DNS records
Error: Address already in useSolution:
# Find what's using the port
sudo lsof -i :80
sudo lsof -i :443

# Stop conflicting service
sudo systemctl stop apache2  # or other service
Cause: Missing intermediate certificates.Solution:
  • Ensure using fullchain.pem not cert.pem
  • Caddy handles this automatically
  • For Nginx: ssl_certificate /etc/letsencrypt/live/domain/fullchain.pem;

Sparklytics HTTPS Configuration

After setting up HTTPS at the reverse proxy level:
1

Enable HTTPS mode

Ensure this is set in your docker-compose.yml or environment:
environment:
  - SPARKLYTICS_HTTPS=true
2

Configure CORS (if needed)

If your tracked websites are on different domains:
environment:
  - SPARKLYTICS_CORS_ORIGINS=https://yoursite.com,https://www.yoursite.com
3

Restart Sparklytics

docker compose restart sparklytics
4

Update tracking snippet

Change the script URL to HTTPS:
<script defer src="https://analytics.yourdomain.com/s.js" 
        data-website-id="YOUR_WEBSITE_ID"></script>

Testing Your HTTPS Setup

1

SSL Labs test

Comprehensive SSL/TLS analysis:https://www.ssllabs.com/ssltest/analyze.html?d=analytics.yourdomain.comAim for an A or A+ rating.
2

Security headers check

https://securityheaders.com/?q=https://analytics.yourdomain.comShould show HSTS and other security headers.
3

Browser test

  • Visit your dashboard over HTTPS
  • Check for padlock icon (no warnings)
  • Verify login works correctly
  • Send test pageview from HTTPS page

Next Steps

Reverse Proxy Setup

Complete reverse proxy configurations

Performance Tuning

Optimize for production workloads

Build docs developers (and LLMs) love