Understanding Nginx on NixOS
Nginx is my preferred reverse proxy solution, which I use extensively in both Kubernetes clusters as an ingress controller and on traditional servers. As a reverse proxy, it excels at:
- Routing traffic to different services on the same machine
- Terminating TLS connections efficiently
- Managing and automating TLS certificate lifecycle
- Load balancing and high availability
- Providing robust caching capabilities
While setting up Nginx can be complex on traditional Linux distributions, NixOS makes it remarkably straightforward with its declarative configuration approach.
Basic Nginx Configuration with ACME
Here’s a basic example from my server’s configuration.nix that demonstrates setting up Nginx with Let’s Encrypt certificate automation:
security.acme.acceptTerms = true;
security.acme.certs = {
"nix-ish.xyz".email = "alexander@holte-davidsen.no";
};
services.nginx = {
enable = true;
recommendedProxySettings = true;
recommendedTlsSettings = true;
virtualHosts."nix-ish.xyz" = {
enableACME = true;
forceSSL = true;
locations."/" = {
proxyPass = "http://127.0.0.1:3030";
proxyWebsockets = false;
extraConfig =
"proxy_ssl_server_name on;" +
"proxy_pass_header Authorization;";
};
};
};
Understanding Each Configuration Component
Let’s break down the key components of this configuration:
ACME (Let’s Encrypt) Setup
The ACME configuration handles automatic SSL certificate management:
security.acme.acceptTerms = true; # Required for Let's Encrypt
security.acme.certs = {
"nix-ish.xyz".email = "alexander@holte-davidsen.no"; # Contact email for certificate alerts
};
Nginx Core Settings
The basic Nginx service configuration enables important security features:
services.nginx = {
enable = true;
recommendedProxySettings = true; # Enables secure proxy headers
recommendedTlsSettings = true; # Enables secure TLS configuration
Virtual Host Configuration
Virtual hosts allow you to serve multiple domains from one server:
virtualHosts."nix-ish.xyz" = {
enableACME = true; # Enable automatic certificate management
forceSSL = true; # Redirect HTTP to HTTPS
Advanced Configuration Examples
Multiple Services on Different Paths
Here’s how to route different services on the same domain:
virtualHosts."nix-ish.xyz" = {
enableACME = true;
forceSSL = true;
locations = {
"/" = {
proxyPass = "http://127.0.0.1:3000"; # Main application
};
"/api/" = {
proxyPass = "http://127.0.0.1:8080"; # API server
};
"/static/" = {
root = "/var/www"; # Static file serving
extraConfig = "expires 30d;"; # Enable caching
};
};
};
Load Balancing Configuration
For high-availability setups:
upstream backend {
server 127.0.0.1:3001;
server 127.0.0.1:3002;
keepalive 32;
}
virtualHosts."nix-ish.xyz" = {
locations."/" = {
proxyPass = "http://backend";
extraConfig = ''
proxy_next_upstream error timeout invalid_header http_500;
proxy_connect_timeout 2;
'';
};
};
Security Considerations
Always implement these security measures:
- HTTP/2 Support
services.nginx = {
enableHTTP2 = true;
# ... other settings
};
- Security Headers
virtualHosts."nix-ish.xyz" = {
extraConfig = ''
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
add_header X-Frame-Options "SAMEORIGIN";
add_header X-Content-Type-Options "nosniff";
add_header X-XSS-Protection "1; mode=block";
'';
};
Monitoring and Maintenance
Logging Configuration
Enable detailed logging for better monitoring:
services.nginx = {
appendHttpConfig = ''
log_format detailed '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent" '
'$request_time';
access_log /var/log/nginx/access.log detailed;
'';
};
Automatic Certificate Renewal
Let’s Encrypt certificates are automatically renewed by the ACME service, but you can check the status:
systemctl status acme-nix-ish.xyz.service
Conclusion
NixOS makes Nginx configuration clear and maintainable through its declarative approach. This setup provides a solid foundation for serving web applications with automatic HTTPS support. Remember to:
- Keep your NixOS configuration in version control
- Regularly test your Nginx configuration
- Monitor certificate renewal status
- Review logs for security issues
- Keep your NixOS system updated
The beauty of NixOS is that once configured, you can replicate this exact setup on any other NixOS system with confidence that it will work the same way.