Configuration Reference
This document provides detailed configuration references for all components of the PQC SSL deployment. All examples are based on our production deployment at pqcnow.com.
Table of Contents
1. HAProxy Configuration 2. Nginx Configuration 3. Apache Configuration 4. systemd Service Configuration 5. Docker Deployment 6. Advanced Scenarios
---
HAProxy Configuration
HAProxy acts as a layer-4 (TCP) proxy that routes traffic based on Server Name Indication (SNI) without decrypting SSL/TLS.
Complete HAProxy Configuration
File: /etc/haproxy/haproxy.cfg
global
# Logging configuration
log /dev/log local0
log /dev/log local1 notice
# Security: run in chroot jail
chroot /var/lib/haproxy
# Admin socket for runtime management
stats socket /run/haproxy/admin.sock mode 660 level admin
stats timeout 30s
# User/group to run as
user haproxy
group haproxy
# Run as daemon
daemon
# Maximum concurrent connections
maxconn 2000
# SSL/TLS tuning (optional)
# tune.ssl.default-dh-param 2048
defaults
log global
mode tcp # Layer 4 (TCP) mode for SNI routing
option tcplog # TCP-specific logging
option dontlognull # Don't log null connections
timeout connect 5000 # 5 seconds to establish connection
timeout client 50000 # 50 seconds client inactivity
timeout server 50000 # 50 seconds server inactivity
# Error handling
retries 3
option redispatch
# Main HTTPS frontend - routes based on SNI
frontend https_front
bind *:443 # Listen on all interfaces, port 443
mode tcp
option tcplog
# SNI inspection settings
tcp-request inspect-delay 5s # Wait up to 5s to inspect SNI
tcp-request content accept if { req_ssl_hello_type 1 }
# ACLs for routing based on SNI
# Add your PQC domain here
acl is_pqc_demo req_ssl_sni -i demo.pqcnow.com
acl is_pqc_demo req_ssl_sni -i pqc.pqcnow.com
# Routing logic
use_backend pqc_demo if is_pqc_demo
default_backend main_site
# Backend for traditional SSL website
backend main_site
mode tcp
balance roundrobin # Load balancing algorithm
# Backend server(s)
server nginx1 127.0.0.1:8080 check inter 2000 rise 2 fall 3
# Add more servers for load balancing:
# server nginx2 127.0.0.1:8081 check inter 2000 rise 2 fall 3
# Health check settings
option tcp-check
# Backend for PQC demo website
backend pqc_demo
mode tcp
balance roundrobin
# Backend PQC server(s)
server pqc1 127.0.0.1:9443 check inter 2000 rise 2 fall 3
# Add more servers for load balancing:
# server pqc2 127.0.0.1:9444 check inter 2000 rise 2 fall 3
# Health check settings
option tcp-check
# Optional: HAProxy statistics page
listen stats
bind *:8404 # Stats page on port 8404
mode http
stats enable
stats uri /stats # Access via http://server:8404/stats
stats refresh 30s
stats auth admin:your-password-here # Change this!
HAProxy ACL Examples
Different SNI matching patterns:
# Exact match
acl is_pqc req_ssl_sni -i pqc.example.com
# Multiple domains
acl is_pqc req_ssl_sni -i pqc.example.com demo.example.com
# Wildcard matching
acl is_pqc req_ssl_sni -m end .pqc.example.com
# Regex matching
acl is_pqc req_ssl_sni -m reg ^pqc[0-9]+\.example\.com$
Testing HAProxy Configuration
# Check configuration syntax
haproxy -c -f /etc/haproxy/haproxy.cfg
# Reload without downtime
systemctl reload haproxy
# View logs
journalctl -u haproxy -f
---
Nginx Configuration
Main Site Configuration (Traditional SSL)
File: /etc/nginx/sites-available/pqcnow.com (Production Example)
# HTTP to HTTPS redirect
server {
listen 80;
listen [::]:80;
server_name pqcnow.com www.pqcnow.com;
# ACME challenge for Let's Encrypt
location /.well-known/acme-challenge/ {
root /var/www/letsencrypt;
}
# Redirect all other traffic to HTTPS
location / {
return 301 https://$host$request_uri;
}
}
# HTTPS server on backend port 8080
# HAProxy forwards :443 traffic here based on SNI
server {
listen 8080 ssl http2;
listen [::]:8080 ssl http2;
server_name pqcnow.com www.pqcnow.com;
# Document root
root /var/www/pqcnow-laravel/public;
index index.php index.html index.htm;
# Let's Encrypt SSL certificate
ssl_certificate /etc/letsencrypt/live/pqcnow.com-0001/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/pqcnow.com-0001/privkey.pem;
# SSL configuration
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
# Security headers
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
# Laravel specific
location / {
try_files $uri $uri/ /index.php?$query_string;
}
# PHP-FPM configuration
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/var/run/php/php8.2-fpm.sock;
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
include fastcgi_params;
}
# Deny access to hidden files
location ~ /\. {
deny all;
access_log off;
log_not_found off;
}
# Logging
access_log /var/log/nginx/pqcnow.com.access.log;
error_log /var/log/nginx/pqcnow.com.error.log;
# WebSocket support (if needed)
location /ws {
proxy_pass http://127.0.0.1:6001;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
}
PQC Demo HTTP Redirect
File: /etc/nginx/sites-available/demo.pqcnow.com
# HTTP to HTTPS redirect for PQC demo
server {
listen 80;
listen [::]:80;
server_name demo.pqcnow.com;
# Redirect to HTTPS
# HAProxy will route HTTPS traffic to BoringSSL server
location / {
return 301 https://$server_name$request_uri;
}
# Optional: serve ACME challenge if using Let's Encrypt for PQC cert
location /.well-known/acme-challenge/ {
root /var/www/letsencrypt;
}
}
Advanced Nginx Features
#### Rate Limiting
# In http block
limit_req_zone $binary_remote_addr zone=general:10m rate=10r/s;
limit_req_zone $binary_remote_addr zone=api:10m rate=2r/s;
# In server block
location / {
limit_req zone=general burst=20 nodelay;
# ... rest of config
}
location /api/ {
limit_req zone=api burst=5 nodelay;
# ... rest of config
}
#### Caching Static Assets
# Cache static files
location ~* \.(jpg|jpeg|png|gif|ico|css|js|svg|woff|woff2|ttf|eot|webp)$ {
expires 1y;
add_header Cache-Control "public, immutable";
access_log off;
}
---
Apache Configuration
Main Site Configuration (Traditional SSL)
File: /etc/apache2/sites-available/example.com-ssl.conf
# Listen on backend port 8080
Listen 8080
<VirtualHost *:8080>
ServerName example.com
ServerAlias www.example.com
DocumentRoot /var/www/example.com/public
# SSL Configuration
SSLEngine on
SSLCertificateFile /etc/letsencrypt/live/example.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/example.com/privkey.pem
# SSL Protocol settings
SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1
SSLCipherSuite HIGH:!aNULL:!MD5
SSLHonorCipherOrder on
# HSTS header
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"
# Security headers
Header always set X-Frame-Options "SAMEORIGIN"
Header always set X-Content-Type-Options "nosniff"
Header always set X-XSS-Protection "1; mode=block"
# Directory settings
<Directory /var/www/example.com/public>
Options -Indexes +FollowSymLinks
AllowOverride All
Require all granted
</Directory>
# Logging
ErrorLog ${APACHE_LOG_DIR}/example.com.error.log
CustomLog ${APACHE_LOG_DIR}/example.com.access.log combined
</VirtualHost>
PQC Demo Apache Configuration
File: /etc/apache2/sites-available/demo-pqc-apache.conf (Production Example)
# PQC Demo Site with ML-DSA Certificate
# Serves on port 9443 with PQC certificate
Listen 9443
<VirtualHost *:9443>
ServerName demo.pqcnow.com
DocumentRoot /var/www/html/demo
# SSL Configuration with ML-DSA Certificate
SSLEngine on
SSLCertificateFile /var/www/pqcnow-laravel/storage/app/certificates/demo.pqcnow.com/demo.pqcnow.com.crt
SSLCertificateKeyFile /var/www/pqcnow-laravel/storage/app/certificates/demo.pqcnow.com/demo.pqcnow.com.key
# SSL Protocol settings
SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1
SSLCipherSuite HIGH:!aNULL:!MD5
SSLHonorCipherOrder on
# Directory settings
<Directory /var/www/html/demo>
Options -Indexes +FollowSymLinks
AllowOverride All
Require all granted
</Directory>
# Security headers
Header always set X-Frame-Options "SAMEORIGIN"
Header always set X-Content-Type-Options "nosniff"
Header always set X-XSS-Protection "1; mode=block"
# Logs
ErrorLog ${APACHE_LOG_DIR}/demo-pqc.error.log
CustomLog ${APACHE_LOG_DIR}/demo-pqc.access.log combined
</VirtualHost>
HTTP Redirect for Apache
File: /etc/apache2/sites-available/000-default.conf
<VirtualHost *:80>
ServerName example.com
ServerAlias www.example.com demo.example.com
# Redirect all HTTP to HTTPS
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}$1 [R=301,L]
# ACME challenge for Let's Encrypt
Alias /.well-known/acme-challenge/ /var/www/letsencrypt/.well-known/acme-challenge/
<Directory /var/www/letsencrypt/.well-known/acme-challenge/>
Require all granted
</Directory>
</VirtualHost>
---
systemd Service Configuration
PQC Demo Server Service
File: /etc/systemd/system/pqc-demo.service (Production Example)
[Unit]
Description=PQC HTTPS Demo Server
Documentation=https://pqcnow.com/docs/
After=network.target network-online.target
Wants=network-online.target
[Service]
Type=simple
User=root
Group=root
WorkingDirectory=/home/pqc
# Command to start the PQC server
# Arguments: certificate-bundle key port [web-root]
ExecStart=/home/pqc/bssl_https_server_pqc demo.pqcnow.com-bundle.crt demo.pqcnow.com.key 9443 /var/www/html/demo
# Restart policy
Restart=always
RestartSec=5
StartLimitInterval=0
# Output to journal
StandardOutput=journal
StandardError=journal
SyslogIdentifier=pqc-demo
# Security settings
PrivateTmp=yes
NoNewPrivileges=true
ProtectSystem=strict
ProtectHome=yes
ReadWritePaths=/var/log/pqc-demo
# Resource limits
LimitNOFILE=65536
[Install]
WantedBy=multi-user.target
Managing the Service
# Reload systemd after changes
systemctl daemon-reload
# Enable service (start on boot)
systemctl enable pqc-demo
# Start service
systemctl start pqc-demo
# Check status
systemctl status pqc-demo
# View logs
journalctl -u pqc-demo -f
# Restart service
systemctl restart pqc-demo
# Stop service
systemctl stop pqc-demo
---
Docker Deployment
Docker Compose Configuration
File: docker-compose.yml
version: '3.8'
services:
# HAProxy SNI router
haproxy:
image: haproxy:2.8-alpine
container_name: haproxy
ports:
- "80:80"
- "443:443"
volumes:
- ./haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg:ro
networks:
- web
restart: unless-stopped
# Main website (Nginx + traditional SSL)
main-site:
image: nginx:alpine
container_name: main-site
volumes:
- ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
- ./nginx/ssl:/etc/nginx/ssl:ro
- ./www:/var/www/html:ro
networks:
- web
expose:
- "8080"
restart: unless-stopped
# PQC demo server
pqc-demo:
build:
context: .
dockerfile: Dockerfile.pqc
container_name: pqc-demo
volumes:
- ./pqc-certs:/opt/pqc/certificates:ro
- ./pqc-www:/opt/pqc/www:ro
networks:
- web
expose:
- "9443"
restart: unless-stopped
command: [
"/opt/pqc/bssl_https_server_pqc",
"/opt/pqc/certificates/pqc.example.com-bundle.crt",
"/opt/pqc/certificates/pqc.example.com.key",
"9443",
"/opt/pqc/www"
]
networks:
web:
driver: bridge
Dockerfile for PQC Server
File: Dockerfile.pqc
FROM ubuntu:22.04
# Install dependencies
RUN apt-get update && apt-get install -y \
ca-certificates \
&& rm -rf /var/lib/apt/lists/*
# Copy pre-built BoringSSL server
COPY bssl_https_server_pqc /opt/pqc/bssl_https_server_pqc
RUN chmod +x /opt/pqc/bssl_https_server_pqc
# Create directories
RUN mkdir -p /opt/pqc/certificates /opt/pqc/www
WORKDIR /opt/pqc
EXPOSE 9443
# Will be overridden by docker-compose command
CMD ["/opt/pqc/bssl_https_server_pqc", "--help"]
---
Advanced Scenarios
Multiple PQC Demo Sites
HAProxy configuration for multiple PQC sites:
frontend https_front
bind *:443
mode tcp
option tcplog
tcp-request inspect-delay 5s
tcp-request content accept if { req_ssl_hello_type 1 }
# Route different PQC demos to different backends
use_backend pqc_demo1 if { req_ssl_sni -i pqc1.example.com }
use_backend pqc_demo2 if { req_ssl_sni -i pqc2.example.com }
use_backend pqc_demo3 if { req_ssl_sni -i pqc3.example.com }
default_backend main_site
backend pqc_demo1
mode tcp
server pqc1 127.0.0.1:9443 check
backend pqc_demo2
mode tcp
server pqc2 127.0.0.1:9444 check
backend pqc_demo3
mode tcp
server pqc3 127.0.0.1:9445 check
Load Balancing
HAProxy configuration with multiple backend servers:
backend main_site
mode tcp
balance roundrobin
option httpchk GET /health
server web1 10.0.1.10:8080 check
server web2 10.0.1.11:8080 check
server web3 10.0.1.12:8080 check backup
backend pqc_demo
mode tcp
balance leastconn
server pqc1 10.0.2.10:9443 check
server pqc2 10.0.2.11:9443 check
Firewall Configuration
# UFW (Ubuntu/Debian)
ufw allow 80/tcp
ufw allow 443/tcp
ufw allow 8404/tcp # HAProxy stats (if enabled)
# iptables
iptables -A INPUT -p tcp --dport 80 -j ACCEPT
iptables -A INPUT -p tcp --dport 443 -j ACCEPT
---
Configuration Testing
Test HAProxy
haproxy -c -f /etc/haproxy/haproxy.cfg
Test Nginx
nginx -t
Test Apache
apachectl configtest
Test SSL/TLS
# Test traditional SSL
openssl s_client -connect example.com:443 -servername example.com
# Test PQC server locally
openssl s_client -connect localhost:9443 -servername pqc.example.com
---
Related Documentation
- Installation Guide - Step-by-step setup
- Testing Guide - Verification procedures
- Troubleshooting - Common issues
Support
- Technical Support: support@pqcnow.com
- Website: https://pqcnow.com