install | source | nginx | advanced | analyze | php | redirect
It is usually assumed that everybody wants HTTPS, right? This is untrue esp. if your website is read-only or provides content publicly. You can have a strong SSL setup if you like, while still allowing plain HTTP at the same time. For those out there who are stuck in the past, and sometimes don’t even have SSL support on their ante-diluvian systems, why not serve anything that’s already public without crypto?
Of course HSTS comes in da game and any modern browser might forget about HTTP. However it is NOT a problem to serve HSTS while talking HTTP, as it does not make any difference to e.g. Lynx which does NOT implement HSTS (as of Jan 2021).
install from binaries –or– build from scratch.
prepare optimal DH
grep --color=always aes /proc/cpuinfo grep --color=always avx /proc/cpuinfo ls -lF /dev/*random* ls -lhF /etc/nginx/dhparms.pem # no exist openssl dhparam 2048 > /etc/nginx/dhparms.pem # -rand /dev/random:/dev/urandom
tune the daemon
cd /etc/nginx/ cp -pi mime.types mime.types.dist vi mime.types
text/plain bash; text/plain ksh; text/plain sh; text/plain log; text/plain out; text/plain md; text/plain tex; application/gzip gz; application/gzip tgz;
mv -i /etc/nginx/conf.d/default.conf /etc/nginx/conf.d/default.conf.dist grep -vE '^[[:space:]]*(#|$)' /etc/nginx/conf.d/default.conf.dist \ > /etc/nginx/conf.d/default.conf.clean
note we tuned the log format quite a bit
mv -i /etc/nginx/nginx.conf /etc/nginx/nginx.conf.dist grep -vE '^[[:space:]]*(#|$)' /etc/nginx/nginx.conf.dist > /etc/nginx/nginx.conf.clean grep -vE '^[[:space:]]*(#|$)' /etc/nginx/nginx.conf.dist > /etc/nginx/nginx.conf vi /etc/nginx/nginx.conf
user nginx nginx; worker_processes auto; events { worker_connections 1024; } http { default_type text/html; server_tokens off; gzip on; log_format mainssl '$ssl_protocol $ssl_cipher ' '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for" "$gzip_ratio"'; include mime.types; sendfile on; keepalive_timeout 65; # https://pub.nethence.com/security/ciphers ssl_protocols TLSv1.3 TLSv1.2; ssl_prefer_server_ciphers off; ssl_ciphers ECDHE:DHE:kGOST:AEAD:!aNULL:!eNULL:!RC4:!MD5:!3DES:!AES256-GCM-SHA384:!ECDHE-RSA-AES256-SHA:!ECDHE-ECDSA-AES256-SHA; ssl_dhparam /etc/nginx/dhparms.pem; # no restriction on ssl_ecdh_curve # without includeSubDomains # 15552000 seconds (180 days) # 31536000 seconds (365 days) # 63072000 seconds (730 days) add_header Strict-Transport-Security "max-age=15552000" always; # jitsi meet #ssl_session_cache shared:SSL:10m; #ssl_session_timeout 1d; #ssl_session_tickets off; # what defaults are those? #ssl_session_cache shared:SSL:40m; #ssl_session_timeout 4h; #ssl_session_tickets on; # shorter #ssl_session_cache shared:SSL:20m; #ssl_session_timeout 10m; add_header X-Frame-Options DENY; include conf.d/*.conf; }
handy symlink
mkdir -p /data/www/ ln -s /var/www/html /data/www/tmp.nethence.com
define the default server stanza - we need an ssl cert anyway
mkdir -p /etc/nginx/conf.d/ cd /etc/nginx/conf.d/
domain=nethence.com cat > catch-all.conf <<EOF server { listen 80 default_server; listen [::]:80 default_server; listen 443 default_server ssl; listen [::]:443 default_server ssl; server_name _; http2 on; access_log /var/log/nginx/catch-all.access.log mailssl; error_log /var/log/nginx/catch-all.error.log warn; # http-01 sample ssl_certificate /etc/dehydrated/certs/$domain/fullchain.pem; ssl_certificate_key /etc/dehydrated/certs/$domain/privkey.pem; ssl_certificate /etc/dehydrated/certs/ECC/$domain/fullchain.pem; ssl_certificate_key /etc/dehydrated/certs/ECC/$domain/privkey.pem; # we need to define location otherwise takes over of .well-known/ location / { return 301 https://$domain/; } # deal with http-01 challenges (no http2 there) location ^~ /.well-known/acme-challenge/ { default_type "text/plain"; # trailing slash matters alias /var/www/dehydrated/; } autoindex off; autoindex_exact_size off; location = /robots.txt { access_log off; log_not_found off; } location = /favicon.ico { access_log off; log_not_found off; } location ~ /apple-touch-icon { access_log off; log_not_found off; } } EOF
Notes
# http2 pops-up a download window on FF # curl: (1) Received HTTP/0.9 when not allowed
put your certs in place and define SNIs.
here’s the publicly available HTTP+HTTPS vhost sample for static pages.
short=static vhost=static.nethence.com
cd /etc/nginx/conf.d/ cat >> $short.conf <<EOF server { listen 80; listen [::]:80; listen 443 ssl; listen [::]:443 ssl; server_name $vhost; http2 on; access_log /var/log/nginx/$short.access.log mainssl; error_log /var/log/nginx/$short.error.log warn; # http-01 sample ssl_certificate /etc/dehydrated/certs/$vhost/fullchain.pem; ssl_certificate_key /etc/dehydrated/certs/$vhost/privkey.pem; ssl_certificate /etc/dehydrated/certs/ECC/$vhost/fullchain.pem; ssl_certificate_key /etc/dehydrated/certs/ECC/$vhost/privkey.pem; location / { root /data/www/$server_name; index index index.html index.htm; try_files $uri $uri/ =404; } # deal with http-01 challenges (no http2 there) location ^~ /.well-known/acme-challenge/ { default_type "text/plain"; # trailing slash matters alias /var/www/dehydrated/; } ssi off; autoindex on; autoindex_exact_size off; location = /robots.txt { access_log off; log_not_found off; } location = /favicon.ico { access_log off; log_not_found off; } location ~ /apple-touch-icon { access_log off; log_not_found off; } } EOF
More options
location ~ /\. { access_log off; log_not_found off; deny all; } location ~ ~$ { access_log off; log_not_found off; deny all; }
And of course, if you really need a redirect instead of serving HTTP, here’s the sample when there is truly and mandatory need for SSL. Note the root location must be there for the redirect, to avoid overriding the .well-known location.
cd /etc/nginx/conf.d/ cat >> $short.conf <<EOF server { listen 80; listen [::]:80; server_name $vhost; # we need to define location otherwise takes over .well-known/ location / { return 301 https://$host$request_uri; } # deal with http-01 challenges (no http2 there) location ^~ /.well-known/acme-challenge/ { default_type "text/plain"; # trailing slash matters alias /var/www/dehydrated/; } } EOF
check configuration
nginx -t
start and enable at boot time
# official repo list-unit-files | grep nginx systemctl status nginx # from source debian list-unit-files | grep rc-local systemctl status rc-local.service vi /etc/rc.local # from source slackware vi /etc/rc.d/rc.local echo -n nginx ... /usr/local/sbin/nginx && echo done || echo FAIL
status
pgrep -a nginx ps auxfww | less cat /var/run/nginx.pid # gnu/linux cat /var/lock/nginx.lock # absent? # netbsd cat /var/db/nginx/nginx.lock
reload
nginx -s reload
shutdown gracefully
nginx -s quit
exit brutally
nginx -s stop
remotely
redirect to HTTS or serve HTTP?
curl -i http://nethence.com/ curl -i http://SHORT.nethence.com/
HTTPS just works
curl -i https://nethence.com/ curl -i https://SHORT.nethence.com/
what happens if you’re talking SSL to a non-existing vhost?
curl -i https://ipsec.nethence.com/
check 301 on 404
curl -i https://nethence.com/lala curl -i https://SHORT.nethence.com/lala
Pitfalls and Common Mistakes https://www.nginx.com/resources/wiki/start/topics/tutorials/config_pitfalls/
Getting Started https://www.nginx.com/resources/wiki/start/index.html
Syntax: server { … } https://nginx.org/en/docs/http/ngx_http_core_module.html#server
Default NGINX Configuration https://gist.github.com/ArunMichaelDsouza/471395af64fb52943bf1
NGINXConfig https://nginxconfig.io/
http://wiki.nginx.org/QuickStart
http://wiki.nginx.org/Configuration
https://docs.nginx.com/nginx/admin-guide/monitoring/logging/
http://nginx.org/en/docs/ngx_core_module.html#include
https://www.nginx.com/resources/wiki/start/topics/examples/full/
https://docs.nginx.com/nginx/admin-guide/basic-functionality/managing-configuration-files/
Module ngx_http_sub_module https://nginx.org/en/docs/http/ngx_http_sub_module.html
Module ngx_http_addition_module https://nginx.org/en/docs/http/ngx_http_addition_module.html
Beautiful listing of files and directories in nginx https://weekly-geekly.github.io/articles/353478/index.html
Directory Theme https://github.com/jessfraz/directory-theme/blob/master/README.md
https://nginx.org/en/docs/http/configuring_https_servers.html
HTTP Strict Transport Security (HSTS) and NGINX https://www.nginx.com/blog/http-strict-transport-security-hsts-and-nginx/
The Importance of a Proper HTTP Strict Transport Security Implementation on Your Web Server https://blog.qualys.com/vulnerabilities-research/2016/03/28/the-importance-of-a-proper-http-strict-transport-security-implementation-on-your-web-server
Integration Guide https://letsencrypt.org/docs/integration-guide/
Hybrid RSA and ECDSA certificates with NginX https://scotthelme.co.uk/hybrid-rsa-and-ecdsa-certificates-with-nginx/
Controlling NGINX Processes at Runtime https://docs.nginx.com/nginx/admin-guide/basic-functionality/runtime-control/
nginx -s stop and -s quit what is the difference? https://serverfault.com/questions/271810/nginx-s-stop-and-s-quit-what-is-the-difference
Debugging Nginx Errors https://blog.martinfjordvald.com/debugging-nginx-errors/ https://blog.martinfjordvald.com/optimizing-nginx-for-high-traffic-loads/ https://blog.martinfjordvald.com/?s=nginx
https://nginx.org/en/docs/http/ngx_http_core_module.html#server_tokens ==> disable
https://nginx.org/en/docs/http/ngx_http_v2_module.html ==> new syntax for http2