Skip to content

Instantly share code, notes, and snippets.

@jesusalber1
Created November 20, 2016 21:46
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jesusalber1/de3af9cdbfb134870bf7cc0fabab159c to your computer and use it in GitHub Desktop.
Save jesusalber1/de3af9cdbfb134870bf7cc0fabab159c to your computer and use it in GitHub Desktop.
Ghost nginx configuration
# sets the proxy cache path location, max size 512m
proxy_cache_path /var/nginx/cache levels=1:2 keys_zone=STATIC:100m inactive=24h max_size=512m;
# transfers the `Host` header to the backend
proxy_set_header Host $host;
# uses the defined STATIC cache zone
proxy_cache STATIC;
# cache 200 10 minutes, 404 1 minute, others status codes not cached
proxy_cache_valid 200 10m;
proxy_cache_valid 404 1m;
proxy_cache_key "$scheme$host$request_uri";
proxy_cache_use_stale error timeout invalid_header updating http_500 http_502 http_503 http_504;
proxy_http_version 1.1;
# transfers real client IP to your ghost app,
# otherwise you would see your server ip
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
client_max_body_size 20m;
client_body_buffer_size 128k;
# default expires (browser cache) set to 1 minute
expires 1m;
# gzip every proxied responses
gzip_proxied any;
# gzip only if user asks it, but in SSL is better to be off (now we want speed)
gzip_vary on;
# gzip only theses mime types
gzip_types text/plain text/css application/x-javascript text/xml application/xml application/xml+rss text/javascript application/json application/javascript;
gzip_static on;
# add a cache HIT/MISS header
add_header X-Cache $upstream_cache_status;
# do not show incoming Etags, if-modified-since is sufficient
proxy_hide_header Etag;
# security configuration below
# don't send the nginx version number in error pages and Server header
server_tokens off;
# config to don't allow the browser to render the page inside an frame or iframe
# and avoid clickjacking http://en.wikipedia.org/wiki/Clickjacking
# if you need to allow [i]frames, you can use SAMEORIGIN or even set an uri with ALLOW-FROM uri
# https://developer.mozilla.org/en-US/docs/HTTP/X-Frame-Options
add_header X-Frame-Options SAMEORIGIN;
# when serving user-supplied content, include a X-Content-Type-Options: nosniff header along with the Content-Type: header,
# to disable content-type sniffing on some browsers.
# https://www.owasp.org/index.php/List_of_useful_HTTP_headers
# currently suppoorted in IE > 8 http://blogs.msdn.com/b/ie/archive/2008/09/02/ie8-security-part-vi-beta-2-update.aspx
# http://msdn.microsoft.com/en-us/library/ie/gg622941(v=vs.85).aspx
# 'soon' on Firefox https://bugzilla.mozilla.org/show_bug.cgi?id=471020
add_header X-Content-Type-Options nosniff;
# This header enables the Cross-site scripting (XSS) filter built into most recent web browsers.
# It's usually enabled by default anyway, so the role of this header is to re-enable the filter for
# this particular website if it was disabled by the user.
# https://www.owasp.org/index.php/List_of_useful_HTTP_headers
add_header X-XSS-Protection "1; mode=block";
# transport security
add_header Strict-Transport-Security "max-age=31536000; includeSubdomains";
# with Content Security Policy (CSP) enabled(and a browser that supports it(http://caniuse.com/#feat=contentsecuritypolicy),
# you can tell the browser that it can only download content from the domains you explicitly allow
# http://www.html5rocks.com/en/tutorials/security/content-security-policy/
# https://www.owasp.org/index.php/Content_Security_Policy
# I need to change our application code so we can increase security by disabling 'unsafe-inline' 'unsafe-eval'
# directives for css and js(if you have inline css or js, you will need to keep it too).
# more: http://www.html5rocks.com/en/tutorials/security/content-security-policy/#inline-code-considered-harmful
# TODO: 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'";
# listen all request (https by default)
server {
listen 443 default_server ssl deferred ssl http2;
listen [::]:443 default_server ipv6only=on deferred ssl http2;
server_name example.com;
# ssl certificate and key
ssl_certificate /etc/ssl/server.crt;
ssl_certificate_key /etc/ssl/server.key;
# enable session resumption to improve https performance
# http://vincent.bernat.im/en/blog/2011-ssl-session-reuse-rfc5077.html
ssl_session_cache shared:SSL:50m;
ssl_session_timeout 15m;
keepalive_timeout 70;
# Diffie-Hellman parameter for DHE ciphersuites, recommended 2048 bits
ssl_dhparam /etc/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
# is better to have only TLSv1.2 but some users may not support it yet
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
# ciphers chosen for forward secrecy and compatibility
# http://blog.ivanristic.com/2013/08/configuring-apache-nginx-and-openssl-for-forward-secrecy.html
ssl_ciphers "ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4";
# ssl stapling
ssl_stapling on;
ssl_stapling_verify on;
# dns resolvers
resolver 8.8.4.4 8.8.8.8 valid=300s;
resolver_timeout 10s;
# logs
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
# add some caching on static assets
location ~* \.(jpg|jpeg|png|gif|ico|css|js|eot|woff)$ {
# ghost sends Cache-Control max-age=0 on CSS/JS for now
# see https://github.com/TryGhost/Ghost/issues/1405?source=c#issuecomment-28196957
proxy_ignore_headers "Cache-Control";
expires 10y;
proxy_pass http://ghost;
}
# remove caching on admin urls
# AND on /signout/ which is badly routed for now
# https://github.com/TryGhost/Ghost/issues/1439
location ~ ^/(?:ghost|signout) {
expires 0;
add_header Cache-Control "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0";
proxy_pass http://ghost;
}
location / {
# ghost sends a `set-cookie` header on every request
# nginx says "no caching" if `set-cookie` is set
# we do not need cookies on non-admin pages (blog posts)
# so we ignore cookies and we hide them on pages other than /ghost/ (admin)
proxy_ignore_headers "Set-Cookie";
proxy_hide_header "Set-Cookie";
proxy_pass http://ghost;
}
}
# server to redirect from http to https
server {
listen 80;
listen [::]:80;
listen 443 ssl http2;
server_name www.example.com example.com;
# ssl certificate and key (if ssl connection)
ssl_certificate /etc/ssl/server.crt;
ssl_certificate_key /etc/ssl/server.key;
return 301 https://example.com$request_uri;
}
upstream ghost {
server localhost:2368;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment