Nginx Deployment¶
Nginx reverse proxy with SSL termination for all WisePulse services.
Deploy¶
ansible-playbook playbooks/setup_nginx.yml -i inventory.ini --ask-become-pass
Multi-Virus Path-Based Routing¶
LAPIS and SILO support multiple virus instances via path-based routing:
| URL Pattern | Backend | Port |
|---|---|---|
lapis.{domain}/covid/* |
LAPIS COVID | 8083 |
lapis.{domain}/rsva/* |
LAPIS RSVA | 8084 |
silo.{domain}/covid/* |
SILO COVID | 8081 |
silo.{domain}/rsva/* |
SILO RSVA | 8082 |
Path Stripping¶
The /covid and /rsva prefixes are stripped before proxying to backends:
https://lapis.wasap.genspectrum.org/covid/sample/info→ backend receives/sample/info
This is achieved using nginx's proxy_pass with a trailing slash:
# Upstream definitions (in conf.d/wasap.conf)
upstream lapis-covid {
server 127.0.0.1:8083;
}
# Location block (in sites-available/lapis.j2)
location /covid/ {
proxy_pass http://lapis-covid/; # trailing slash strips /covid/ prefix
proxy_set_header X-Forwarded-Prefix /covid/;
}
Key implementation details:
- Trailing slash in
proxy_pass: When both the location and proxy_pass end with/, nginx strips the location prefix - Upstream blocks: Defined in
conf.d/wasap.conf.j2for cleaner configuration and future load balancing support - X-Forwarded-Prefix header: Tells backends the original path prefix
- Trailing slash redirects: Requests to
/covidreturn 301 to/covid/
Backward Compatibility¶
For backward compatibility with existing API consumers, requests to root paths are proxied directly to the COVID backend (not redirected). This preserves CORS preflight behavior for cross-origin requests:
https://lapis.wasap.genspectrum.org/sample/info→ proxies to COVID LAPIS backend
Using proxy instead of redirect avoids breaking CORS preflight (OPTIONS) requests, which don't follow redirects properly.
Configuration¶
| Variable | Default | Description |
|---|---|---|
nginx_domain_name |
wasap.genspectrum.org |
Base domain name. Subdomains (db., lapis., silo.) are derived from this. |
nginx_lapis_covid_port |
8083 |
COVID LAPIS port |
nginx_lapis_rsva_port |
8084 |
RSVA LAPIS port |
nginx_silo_covid_port |
8081 |
COVID SILO port |
nginx_silo_rsva_port |
8082 |
RSVA SILO port |
nginx_ssl_certificate_path |
/etc/letsencrypt/live/{{ nginx_domain_name }}/fullchain.pem |
SSL certificate path |
nginx_ssl_certificate_key_path |
/etc/letsencrypt/live/{{ nginx_domain_name }}/privkey.pem |
SSL key path |
nginx_dhparam_path |
/etc/letsencrypt/ssl-dhparams.pem |
Diffie-Hellman parameters file |
nginx_sites |
List of all sites | Site templates to deploy to sites-available |
nginx_enabled_sites |
List of active sites | Sites to symlink to sites-enabled |
SSL Configuration¶
Uses Let's Encrypt certificates:
- Wasap Scout (Main Domain):
nginx_ssl_certificate_pathandnginx_ssl_certificate_key_path - Lapis:
nginx_lapis_ssl_certificate_pathandnginx_lapis_ssl_certificate_key_path - Silo:
nginx_silo_ssl_certificate_pathandnginx_silo_ssl_certificate_key_path - Loculus (db, auth.db, api.db):
nginx_loculus_ssl_certificate_pathandnginx_loculus_ssl_certificate_key_path
All subdomain certificate paths default to the standard Let's Encrypt structure (/etc/letsencrypt/live/<subdomain>.{{ nginx_domain_name }}/).
Production¶
In production, certificates are expected to be managed by Certbot at the default Let's Encrypt paths.
- hosts: webservers
roles:
- nginx
Staging / Testing¶
For environments without real certificates:
ansible-playbook -i inventory.ini playbooks/setup_nginx.yml -e "generate_self_signed_certs=true"
Testing¶
Verify Path-Based Routing¶
# Create a test server on an unused port
cat > /tmp/test.conf << 'EOF'
upstream test-backend {
server 127.0.0.1:8083;
}
server {
listen 9999;
location = /covid {
return 301 /covid/;
}
location /covid/ {
proxy_pass http://test-backend/;
proxy_set_header X-Forwarded-Prefix /covid/;
}
}
EOF
sudo cp /tmp/test.conf /etc/nginx/sites-available/test
sudo ln -sf /etc/nginx/sites-available/test /etc/nginx/sites-enabled/test
sudo nginx -t && sudo systemctl reload nginx
# Test - should return valid JSON from LAPIS backend
curl -s http://127.0.0.1:9999/covid/sample/info | head -3
# Cleanup
sudo rm /etc/nginx/sites-enabled/test
sudo systemctl reload nginx
Production Verification¶
# Test COVID endpoint (new path)
curl -s https://lapis.wasap.genspectrum.org/covid/sample/info | head -3
# Test RSVA endpoint (new path)
curl -s https://lapis.wasap.genspectrum.org/rsva/sample/info | head -3
# Test backward compatibility (proxied to COVID, not redirected)
curl -s https://lapis.wasap.genspectrum.org/sample/info | head -3
Local Testing Considerations¶
-
DNS Resolution: Public domain names resolve to production IPs. Use
/etc/hostsoverrides or test via127.0.0.1with appropriateHostheaders. -
SSL/SNI: Self-signed certificates may not match expected hostnames.
-
Server Block Priority: If testing via
127.0.0.1, ensure no other server block listens specifically on127.0.0.1:443.
Role Structure¶
roles/nginx/
├── tasks/ # Main installation and configuration tasks
├── templates/ # Nginx configuration templates
├── handlers/ # Service reload/restart handlers
└── defaults/ # Default variable definitions