Last active
August 10, 2020 20:18
-
-
Save jdforsythe/09e9fd0dc7f75e7468fc48c9bc8b1598 to your computer and use it in GitHub Desktop.
Develop With Local HTTPs Domains
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
## https://gist.github.com/jdforsythe/09e9fd0dc7f75e7468fc48c9bc8b1598 | |
## | |
## This will: | |
## | |
## 1. Install `mkcert` and create a self-signed CA and certificates for fake domains and trust them | |
## with the system's trust store. This allows you to develop using the same SSL/TLS techniques you | |
## would in production, bringing dev-prod parity and allowing things like cross-sub-domain secure | |
## cookies with CORS | |
## 2. Install `nginx`. This allows you to make requests to all the domains on port 443 as you would | |
## in production and nginx will proxy them to the port your app is running on locally. It also | |
## allows you to terminate the SSL/TLS at the proxy and only deal with HTTP in your applications. | |
## This simplifies your app and mimics the production scenario of terminating the SSL/TLS at a | |
## load balancer, API gateway, reverse proxy, etc. | |
## 3. Generate nginx configuration to set up the proxying and to add "secure" flag to every cookie. | |
## You can avoid the errors from your server applications that you can't add secure on HTTP requests | |
## by allowing nginx to add the flag using the generated proxy configuration. All of your cookies | |
## will then be set to secure. Restarts nginx with the new config. | |
## 4. Generates `hosts` file entries to map your fake subdomains to localhost and appends them to `/etc/hosts` | |
## | |
##################################### | |
## CONFIGURATION | |
##################################### | |
## Set the `DOMAIN` variable to the top level domain you want to work with (no "www", e.g. "example.test") | |
DOMAIN=example.test | |
## Set the `SUBDOMAINS` variable to a list of the local subdomains you want certificates for along with | |
## the port they will be running on, separated by a semicolon, e.g. 'www;4300' | |
declare -a SUBDOMAINS=( | |
'www;4300' | |
'app;4200' | |
'api;8080' | |
) | |
## The NGINX_PATH is the base `etc/nginx` folder. This should not need changed unless nginx changes | |
## its folder location | |
NGINX_PATH=/usr/local/etc/nginx/ | |
## The NGINX_SERVER_PATH is the folder in the NGINX_PATH that the nginx configuration should go | |
## into. By default on homebrew install this is `/usr/local/etc/nginx/servers` | |
NGINX_SERVER_PATH=${NGINX_PATH}servers/ | |
## These are the files output by mkcert. These should not need changed unless mkcert changes the | |
## default output filename schema | |
CERT_FILE=${DOMAIN}+4.pem | |
KEY_FILE=${DOMAIN}+4-key.pem | |
## The SSL_PATH is where the certificates will be stored, in a domain subfolder. You can change this | |
## if you wish | |
SSL_PATH=${NGINX_PATH}ssl/${DOMAIN}/ | |
CONFIG_COMMENT=$(cat <<EOF | |
#################################################### | |
## Config generated automatically | |
## https://gist.github.com/jdforsythe/09e9fd0dc7f75e7468fc48c9bc8b1598 | |
#################################################### | |
EOF | |
) | |
## Holds the nginx configuration | |
NGINX_CONF="${CONFIG_COMMENT}" | |
##################################### | |
## FUNCTIONS | |
##################################### | |
## Create an `upstream` block for each subdomain | |
set_nginx_upstream() { | |
NGINX_CONF+=$(cat <<EOF | |
upstream ${1} { | |
server 127.0.0.1:${2}; | |
} | |
EOF | |
) | |
} | |
## Create a `server` block for each subdomain to terminate SSL and proxy | |
## to the corresponding `upstream` | |
set_nginx_server() { | |
NGINX_CONF+=$(cat <<EOF | |
server { | |
server_name ${1}.${DOMAIN}; | |
listen 443 ssl; | |
ssl_certificate ${SSL_PATH}${CERT_FILE}; | |
ssl_certificate_key ${SSL_PATH}${KEY_FILE}; | |
location / { | |
proxy_pass http://${1}; | |
proxy_cookie_path / "/; secure"; | |
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for; | |
proxy_set_header X-Forwarded-Host \$host:\$server_port; | |
proxy_set_header X-Forwarded-Server \$host; | |
} | |
} | |
EOF | |
) | |
} | |
dependencies() { | |
brew update | |
## install mkcert, nss, and nginx | |
brew install mkcert nginx | |
} | |
certificates() { | |
mkcert --install | |
## generate CA and certificate for *.domain.ext | |
mkcert $DOMAIN "*.${DOMAIN}" localhost 127.0.0.1 ::1 | |
mkdir -p "$SSL_PATH" | |
mv $CERT_FILE "${SSL_PATH}${CERT_FILE}" | |
mv $KEY_FILE "${SSL_PATH}${KEY_FILE}" | |
} | |
nginx_config() { | |
for d in "${SUBDOMAINS[@]}" | |
do | |
IFS=";" read -r -a PARTS <<< "$d" | |
set_nginx_upstream "${PARTS[0]}" "${PARTS[1]}" | |
done; | |
for d in "${SUBDOMAINS[@]}" | |
do | |
IFS=";" read -r -a PARTS <<< "$d" | |
set_nginx_server "${PARTS[0]}" | |
done; | |
mkdir -p "${NGINX_SERVER_PATH}" | |
echo "$NGINX_CONF" > "${NGINX_SERVER_PATH}${DOMAIN}.conf" | |
## if you don't have nginx running as a service, run this instead: | |
## `nginx -s reload` | |
brew services restart nginx | |
} | |
hosts() { | |
HOSTS_FILE="${CONFIG_COMMENT}" | |
for d in "${SUBDOMAINS[@]}" | |
do | |
IFS=";" read -r -a PARTS <<< "$d" | |
SUBDOMAIN=${PARTS[0]}.${DOMAIN} | |
HOSTS_FILE+=$(cat <<EOF | |
127.0.0.1 ${SUBDOMAIN} | |
::1 ${SUBDOMAIN} | |
EOF | |
) | |
done; | |
HOSTS_FILE+=$(cat <<EOF | |
#################################################### | |
EOF | |
) | |
echo "${HOSTS_FILE}" | sudo tee -a /etc/hosts | |
} | |
##################################### | |
## EXECUTION | |
##################################### | |
dependencies | |
certificates | |
nginx_config | |
hosts |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment