Skip to content

Instantly share code, notes, and snippets.

@jult
Last active December 23, 2020 14:16
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jult/0b3e08c2128140cab17f0682270bc9fc to your computer and use it in GitHub Desktop.
Save jult/0b3e08c2128140cab17f0682270bc9fc to your computer and use it in GitHub Desktop.
NGINX config for pi-hole
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
#
# Custom headers and headers various browsers *should* be OK with but aren't
#
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
#
# Tell client that this pre-flight info is valid for 20 days
#
add_header 'Access-Control-Max-Age' 1728000;
add_header 'Content-Type' 'text/plain; charset=utf-8';
add_header 'Content-Length' 0;
return 204;
}
if ($request_method = 'POST') {
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';
}
if ($request_method = 'GET') {
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';
}
fastcgi_param QUERY_STRING $query_string;
fastcgi_param REQUEST_METHOD $request_method;
fastcgi_param CONTENT_TYPE $content_type;
fastcgi_param CONTENT_LENGTH $content_length;
fastcgi_param SCRIPT_NAME $fastcgi_script_name;
fastcgi_param REQUEST_URI $request_uri;
fastcgi_param DOCUMENT_URI $document_uri;
fastcgi_param DOCUMENT_ROOT $document_root;
fastcgi_param SERVER_PROTOCOL $server_protocol;
fastcgi_param REQUEST_SCHEME $scheme;
fastcgi_param HTTPS $https if_not_empty;
fastcgi_param GATEWAY_INTERFACE CGI/1.1;
fastcgi_param SERVER_SOFTWARE nginx/$nginx_version;
fastcgi_param REMOTE_ADDR $remote_addr;
fastcgi_param REMOTE_PORT $remote_port;
fastcgi_param SERVER_ADDR $server_addr;
fastcgi_param SERVER_PORT $server_port;
fastcgi_param SERVER_NAME $server_name;
# PHP only, required if PHP was built with --enable-force-cgi-redirect
fastcgi_param REDIRECT_STATUS 200;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
add_header Referrer-Policy "no-referrer" always;
#add_header Referrer-Policy no-referrer-when-downgrade always;
#add_header Content-Security-Policy "default-src 'self' 'unsafe-inline' 'unsafe-eval'; img-src 'self' data:;" always;
add_header X-Content-Type-Options nosniff always;
add_header X-XSS-Protection "1; mode=block" always;
add_header X-Robots-Tag none; add_header X-Download-Options noopen;
add_header X-Permitted-Cross-Domain-Policies none;
add_header X-Frame-Options SAMEORIGIN;
user www-data;
pid /run/nginx.pid;
worker_processes auto;
worker_priority -10;
timer_resolution 100ms;
worker_rlimit_nofile 8192;
events { worker_connections 2048; multi_accept on; use epoll; }
http {
index index.php index.html index.htm;
server_names_hash_bucket_size 64;
upstream php-handler {
server unix:/run/php/php7.3-fpm.sock;
}
## Detect when HTTPS is used
map $scheme $fastcgi_https { default off; https on; }
set_real_ip_from 127.0.0.1;
set_real_ip_from 192.168.1.0/24;
real_ip_header X-Forwarded-For;
real_ip_recursive on;
include /etc/nginx/mime.types;
default_type application/octet-stream;
charset_types text/css text/plain text/vnd.wap.wml application/javascript application/json application/rss+xml application/xml;
charset utf-8;
underscores_in_headers on;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for" '
# '"$host" sn="$server_name" '
# 'rt=$request_time '
# 'ua="$upstream_addr" us="$upstream_status" '
# 'ut="$upstream_response_time" ul="$upstream_response_length" '
# 'cs=$upstream_cache_status' ;
access_log /var/log/nginx/access.log main;
error_log /var/log/nginx/error.log warn;
sendfile on;
send_timeout 8000s;
open_file_cache max=1000 inactive=12m;
open_file_cache_valid 30s;
open_file_cache_min_uses 2;
open_file_cache_errors on;
keepalive_timeout 160;
reset_timedout_connection on;
tcp_nopush on;
tcp_nodelay on;
keepalive_requests 300;
server_tokens off;
types_hash_max_size 2048;
client_max_body_size 18g;
fastcgi_hide_header X-Powered-By;
fastcgi_read_timeout 8000;
fastcgi_send_timeout 8000;
fastcgi_connect_timeout 8000;
fastcgi_buffers 64 64K;
fastcgi_buffer_size 256k;
fastcgi_busy_buffers_size 3840K;
fastcgi_cache_key $http_cookie$request_method$host$request_uri;
fastcgi_cache_use_stale error timeout invalid_header http_500;
fastcgi_cache_path /tmp/cache levels=1:2 keys_zone=phpcache:200m inactive=200m;
fastcgi_ignore_headers Cache-Control Expires Set-Cookie;
client_body_temp_path /var/www/nginxt 1 2;
client_header_timeout 8000s;
client_body_timeout 8000s;
client_body_buffer_size 128k;
gzip on;
gzip_vary on;
gzip_comp_level 5;
gzip_min_length 256;
gzip_proxied expired no-cache no-store private no_last_modified no_etag auth;
gzip_disable "msie6";
gzip_disable "MSIE [1-6]\.(?!.*SV1)";
gzip_buffers 16 8k;
gzip_http_version 1.1;
gzip_types
application/atom+xml
application/javascript
application/json
application/ld+json
application/manifest+json
application/rss+xml
application/xml+rss
application/vnd.geo+json
application/vnd.ms-fontobject
application/x-font-ttf
application/x-web-app-manifest+json
application/xhtml+xml
application/xml
font/opentype
image/bmp
image/svg+xml
image/x-icon
text/cache-manifest
text/css
text/plain
text/vcard
text/vnd.rim.location.xloc
text/vtt
text/x-component
text/x-cross-domain-policy
text/x-js
text/richtext
text/xsd
text/xsl
text/xml;
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
}
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $path_info;
fastcgi_param HTTPS on;
fastcgi_param modHeadersAvailable true;
fastcgi_param front_controller_active true;
fastcgi_pass php-handler;
fastcgi_intercept_errors on;
fastcgi_request_buffering off;
fastcgi_cache_valid 404 1m;
fastcgi_cache_valid any 1h;
fastcgi_cache_methods GET HEAD;
server {
listen 443;
server_name somename.net anothername.net another.domainname.tld;
include /etc/nginx/TLS;
return 301 https://yourpihole.domainname.tld$request_uri;
}
server {
listen 443 ssl http2;
server_name yourpihole.domainname.tld pi.hole;
include /etc/nginx/TLS;
root /var/www/html/admin;
autoindex off;
index index.php index.html index.htm;
location / {
expires max;
try_files $uri $uri/ =404;
auth_basic "Restricted"; # For Basic Auth
auth_basic_user_file /etc/nginx/.htpasswd; # For Basic Auth
}
location ~ \.php$ {
include fastcgi_params;
include phpoptim;
include headers;
include CORS;
fastcgi_param FQDN true;
auth_basic "Restricted"; # For Basic Auth
auth_basic_user_file /etc/nginx/.htpasswd; # For Basic Auth
}
location /*.js {
index pihole/index.js;
auth_basic "Restricted"; #For Basic Auth
auth_basic_user_file /etc/nginx/.htpasswd; #For Basic Auth
}
location ~ /\.ht {
deny all;
}
error_page 404 /index.php;
}
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
ssl_certificate /blah/fullchain.pem;
ssl_certificate_key /blah/privkey.pem;
# generated using:# openssl dhparam -dsaparam -out /etc/ssl/dh4096.pem 4096
ssl_dhparam /etc/ssl/dh4096.pem;
ssl_ecdh_curve secp384r1;
ssl_stapling on;
ssl_stapling_verify on;
ssl_trusted_certificate /blah/chain.pem;
resolver 127.0.0.1 valid=96s;
resolver_timeout 6s;
ssl_session_timeout 16h;
ssl_session_cache shared:MozSSL:30m;
ssl_session_tickets off;
ssl_buffer_size 4k;
include headers;
@jult
Copy link
Author

jult commented Aug 30, 2020

The important TLDR here is that in piholewebgui.conf you can see include CORS; in the location ~ .php$ directive. Put it below other entries that could possibly add headers, because NGINX lets the last one given take over.
The contents of the CORS that work for me are in the example CORS file above.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment