Skip to content

Instantly share code, notes, and snippets.

@pongstr
Last active October 26, 2023 05:57
Show Gist options
  • Save pongstr/663edf7f5cfe94c7926775c53b43388d to your computer and use it in GitHub Desktop.
Save pongstr/663edf7f5cfe94c7926775c53b43388d to your computer and use it in GitHub Desktop.
HTTP/2 Recipe: Nginx + Node.js

Imgur

Recipe

Install homebrew/services, this will be helpful, you'll see later. :D

$ brew tap homebrew/services 

Install dnsmasq because it's awesome, no really, so you can use .dev as your development domain, this is really helpful, you'll see later. :D

# Install dnsmasq via homebrew
$ brew install dnsmasq; 

# Add dnsmasq config 
$ cat << EOF > /usr/local/etc/dnsmasq.conf
bind-interfaces 
keep-in-foreground 
no-resolv 

address=/dev/127.0.0.1 
listen-address=127.0.0.1
EOF

# Create an additional resolver
$ sudo mkdir -p /etc/resolver/ && $(echo 'nameserver 127.0.0.1' | sudo tee -a '/etc/resolver/dev')

# Install nginx with http2 module
$ brew install nginx --with-http2

# You're done here for now, we'd want to use port:80 so run these 
# services as root
$ sudo brew services start dnsmasq 
$ sudo brew services start nginx 

Generate SSL Certificates and add it to OSX keychain.

# Let's make this a script to make life a bit easier
$ vi ssl-certificate.sh 

# Copy the script below:
SSL_DIR="/usr/local/etc/nginx/ssl"
ROOT_SSL_NAME="node.dev"
ROOT_SSL_FQDN="node.dev"

# Create Nginx SSL Dir if it does not exists.
if [ ! -d $SSL_DIR ]; then
  sudo mkdir -p $SSL_DIR
fi


# Create your very own Root Certificate Authority
sudo openssl genrsa \
  -out "$SSL_DIR/$ROOT_SSL_NAME.key" \
  2048

# Self-sign your Root Certificate Authority
# Since this is private, the details can be as bogus as you like
sudo openssl req \
  -x509 \
  -new \
  -sha256 \
  -nodes \
  -key "$SSL_DIR/$ROOT_SSL_NAME.key" \
  -days 3652 \
  -out "$SSL_DIR/$ROOT_SSL_NAME.crt" \
  -subj "/C=EE/ST=Tallinn/L=FakeTaxi/O=ACME Signing Authority Inc/CN=${ROOT_SSL_FQDN}"

# NOTE
# -nodes means "no-des" which means "no passphrase"
# -days 3652 means that this example will break about 10 years from now

# Add this shit to OSX keychain
sleep 1

sudo security add-trusted-cert \
  -d \
  -r trustRoot \
  -k "/Library/Keychains/System.keychain" "$SSL_DIR/$ROOT_SSL_NAME.crt"

And you're all set.

'use strict'
const express = require('express')
const app = express()
const index = `
<!DOCTYPE html>
<html lang="en">
<head>
<!-- Required meta tags always come first -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta http-equiv="x-ua-compatible" content="ie=edge">
<title>Bootstrap 101 Template</title>
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.4/css/bootstrap.min.css" >
</head>
<body>
<div class="container text-xs-center">
<h1 class="display-4 m-y-3">Hello, &lt;http/2&gt;</h1>
</div><!-- end of .container -->
<!-- jQuery first, then Tether, then Bootstrap JS. -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.0.0/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/tether/1.2.0/js/tether.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.4/js/bootstrap.min.js"></script>
</body>
</html>
`
app.set('port', process.env.PORT || 5000)
app.enable('trust proxy')
app.disable('x-powered-by')
app.get('/', function (req, res) {
res.send(index)
res.end()
})
app.listen(app.get('port'), function () {
console.info('Server Running')
})
upstream node {
server 127.0.0.1:5000;
keepalive 64;
}
proxy_cache_path /opt/pongstr/config/nginx/cache levels=1:2 keys_zone=one:8m max_size=1000m inactive=600m;
proxy_temp_path /opt/pongstr/config/nginx/temp;
server {
listen 80;
listen [::]:80;
server_name node.dev;
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2 default_server;
listen [::]:443 ssl http2 default_server;
server_name node.dev *.node.dev;
ssl on;
ssl_ciphers HIGH:!aNULL:!eNULL:!EXPORT:!CAMELLIA:!DES:!MD5:!PSK:!RC4;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_session_cache builtin:1000 shared:SSL:10m;
ssl_certificate /opt/pongstr/config/nginx/ssl/root-node.dev.crt;
ssl_certificate_key /opt/pongstr/config/nginx/ssl/root-node.dev.key;
ssl_prefer_server_ciphers on;
location / {
proxy_pass http://node$request_uri;
proxy_redirect off;
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;
proxy_set_header X-Forwarded-Proto-Version $http2;
proxy_set_header Host $http_host;
proxy_set_header X-NginX-Proxy true;
proxy_set_header Connection "";
# Cache Controls
# This section sets response expiration which prevents 304 not modified
expires 0;
add_header Pragma public;
add_header Cache-Control "public";
access_log off;
# Security Patches
# This section are security patches in case the client overrides
# these values, the server re-enables it and enforce its rules
add_header X-XSS-Protection "1; mode=block";
add_header X-Frame-Options "deny";
add_header X-Content-Type-Options "nosniff";
}
access_log /opt/pongstr/config/nginx/logs/access.log;
error_log /opt/pongstr/config/nginx/logs/error.log warn;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment