This is an old revision of the document!
Nginx
Usage with acme.sh
1. You need to create a blank site.
server { server_tokens off; listen 80; listen [::]:80; server_name example.com; location ^~ /.well-known/acme-challenge/ { default_type "text/plain"; root /var/www/acme-challenge/; } }
Don't forget to link and restart nginx.
2. Install acme.sh to get a cert.
curl https://get.acme.sh | sh
3. Get a cert.
acme.sh --issue -d example.com -w /var/www/acme-challenge/
Note: if you plan to use wildcard, then do this:
acme.sh --issue -d example.com -d '*.example.com' --dns --yes-I-know-dns-manual-mode-enough-go-ahead-please
acme.sh --renew -d example.com -d '*.example.com' --dns --yes-I-know-dns-manual-mode-enough-go-ahead-please
4. Copy the cert to nginx folder.
acme.sh --install-cert -d example.com \ --key-file /etc/nginx/ssl/example.com.key \ --fullchain-file /etc/nginx/ssl/example.com.crt \ --reloadcmd "service nginx force-reload"
5. Rewrite the site's config file.
Here is an example secure conf.
- example.com
server { server_tokens off; listen 80; listen [::]:80; server_name example.com; location ^~ /.well-known/acme-challenge/ { default_type "text/plain"; root /var/www/acme-challenge/; } return 301 https://$host$request_uri; } server { server_tokens off; listen 443 ssl http2; listen [::]:443 ssl http2; server_name example.com; add_header X-Frame-Options "SAMEORIGIN" always; add_header X-Content-Type-Options "nosniff" always; add_header X-XSS-Protection "1; mode=block" always; add_header Referrer-Policy "no-referrer-when-downgrade" always; add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval' https://ssl.google-analytics.com https://assets.zendesk.com https://connect.facebook.net; img-src 'self' https://ssl.google-analytics.com https://s-static.ak.facebook.com https://assets.zendesk.com; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com https://assets.zendesk.com; font-src 'self' https://themes.googleusercontent.com; frame-src https://assets.zendesk.com https://www.facebook.com https://s-static.ak.facebook.com https://tautt.zendesk.com; object-src 'none'"; # Or add_header Content-Security-Policy "default-src 'self' http: https: data: blob: 'unsafe-inline'" always; add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"; ssl_session_cache shared:SSL:10m; ssl_session_timeout 10m; ssl_session_tickets off; # Diffie-Hellman parameter for DHE ciphersuites, recommended 2048 bits ssl_dhparam /etc/nginx/ssl/dhparam.pem; # enables server-side protection from BEAST attacks # http://blog.ivanristic.com/2013/09/is-beast-still-a-threat.html ssl_prefer_server_ciphers on; # disable SSLv3(enabled by default since nginx 0.8.19) since it's less secure then TLS http://en.wikipedia.org/wiki/Secure_Sockets_Layer#SSL_3.0 # ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # Update 2019-05-08: Uses TLSv1.3 only, this requires nginx >= 1.13.0 else use TLS1.2 ssl_protocols TLSv1.3; # ciphers chosen for forward secrecy and compatibility # http://blog.ivanristic.com/2013/08/configuring-apache-nginx-and-openssl-for-forward-secrecy.html ssl_ciphers EECDH+AESGCM:EDH+AESGCM; # Or this: # ssl_ciphers HIGH:!MEDIUM:!LOW:!aNULL:!NULL:!SHA; ssl_ecdh_curve secp384r1; # enable ocsp stapling (mechanism by which a site can convey certificate revocation information to visitors in a privacy-preserving, scalable manner) # http://blog.mozilla.org/security/2013/07/29/ocsp-stapling-in-firefox/ resolver 1.1.1.1 1.0.0.1 valid=60s; resolver_timeout 5s; ssl_stapling on; ssl_stapling_verify on; ssl_trusted_certificate /etc/nginx/ssl/example.com.crt; set $base /home/wwwroot/example.com; root $base; index index.php index.html; location / { # First attempt to serve request as file, then # as directory, then fall back to displaying a 404. try_files $uri $uri/ =404; } location ~ \.php$ { include snippets/fastcgi-php.conf; fastcgi_pass unix:/var/run/php/php7.3-fpm.sock; fastcgi_buffers 8 16k; fastcgi_buffer_size 32k; # fastcgi params fastcgi_param DOCUMENT_ROOT $realpath_root; fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name; fastcgi_param PHP_ADMIN_VALUE "open_basedir=$base/:/usr/lib/php/:/tmp/"; } location ~ /\.ht { deny all; } location = /favicon.ico { log_not_found off; access_log off; } location = /robots.txt { log_not_found off; access_log off; } # assets, media location ~* \.(?:css(\.map)?|js(\.map)?|jpe?g|png|gif|ico|cur|heic|webp|tiff?|mp3|m4a|aac|ogg|midi?|wav|mp4|mov|webm|mpe?g|avi|ogv|flv|wmv)$ { expires 7d; access_log off; } # svg, fonts location ~* \.(?:svgz?|ttf|ttc|otf|eot|woff2?)$ { add_header Access-Control-Allow-Origin "*"; expires 7d; access_log off; } # gzip gzip on; gzip_vary on; gzip_proxied any; gzip_comp_level 6; gzip_types text/plain text/css text/xml application/json application/javascript application/rss+xml application/atom+xml image/svg+xml; ssl_certificate /etc/nginx/ssl/example.com.crt; ssl_certificate_key /etc/nginx/ssl/example.com.key; }
dhparam.pem
Diffie–Hellman key exchange (DH) is a method of securely exchanging cryptographic keys over a public channel and was one of the first public-key protocols as originally conceptualized by Ralph Merkle and named after Whitfield Diffie and Martin Hellman. DH is one of the earliest practical examples of public key exchange implemented within the field of cryptography. (Source: Wikipedia)
openssl dhparam -out dhparam.pem 4096
If your openssl
or nginx
still uses a lot of CPU after that, then use:
openssl dhparam -dsaparam -out dhparam.pem 4096
Things that might help you out: Cipherli.st & Mozilla SSL Configuration Generator
Cool stuff
Colorful OpenDirectory
# You need to install nginx-extras on Debian / Ubuntu. location / { autoindex on; fancyindex on; fancyindex_exact_size off; }
Connectivity Detection
# Apple CNA location /hotspot-detect.html { return 200 '<HTML><HEAD><TITLE>Success</TITLE></HEAD><BODY>Success</BODY></HTML>'; add_header Content-Type text/html; } # Apple CNA location /library/test/success.html { return 200 '<HTML><HEAD><TITLE>Success</TITLE></HEAD><BODY>Success</BODY></HTML>'; add_header Content-Type text/html; } # ChromeOS location /generate_204 { return 204; } # Windows connectivity detection (http://blog.superuser.com/2011/05/16/windows-7-network-awareness/) location /ncsi.txt { return 200 'Microsoft NCSI'; }
Reverse Proxy
location / { proxy_pass http://127.0.0.1:8080/; proxy_set_header Host $http_host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; client_max_body_size 0; }
log
log_format main '$remote_addr - $remote_user [$time_local] "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent" "$http_x_forwarded_for"'; access_log /var/log/nginx/example_com_access.log; error_log /var/log/nginx/example_com_error.log warn;
Ban direct access
1. Just modify default
- default
server { listen 80 default_server; listen [::]:80 default_server; server_name _; return 304; } server { listen 443 default_server; listen [::]:443 default_server; server_name _; ssl on; ssl_certificate /etc/nginx/ssl/null/null.crt; ssl_certificate_key /etc/nginx/ssl/null/null.key; return 304; }
2. Generate a self-signed certificate
openssl req -x509 -nodes -days 7305 -newkey rsa:2048 -keyout /etc/nginx/ssl/null/null.key -out /etc/nginx/ssl/null/null.crt