loading...

🔐 Full HTTPS development environment

nightbr profile image Titouan B ãƒģ5 min read

Hey, in this post series, I will explain how you can have a full development environment in HTTPS with a valid certificate for your local development domain.

Why should I use HTTPS in development?

In fact, there are many reasons you should use HTTPS for your development environment:

  • To use Secure Cookie for authentication (using Auth service such as Keycloack, Auth0, ...) → See more here or here
  • To have the development & production environment as similar as possible. See the 10th factor of the 12-factor app.
  • Some external services (SaaS) required HTTPS (i.e. for webhooks)

Setup the certificate

We need to setup an certificate signed with a rootCA which is recognized by our system and browser.

First we will choose an hostname for our local development environment, then we will use the awesome tool mkcert to generate a valid certificate.

Choose a dev hostname

Choose an hostname for your development environment.

⚠ī¸ Don't use existing domain name which could create conflicts!

You can use the usual localhost or another hostname. I like to use dev.local which I will take for the next steps.

You will need to add the hostname in your local dns which is /etc/hosts in Linux & Mac. So add 127.0.0.1 dev.local in your /etc/hosts.

💡 Tips: I'm using this script from this gist to add & remove hostname easily 👍

🗒ī¸ Note: If you use sub-domain such as api.dev.local, app.dev.local, ... You have to add them in /etc/hosts too. You can't use wildcard such as *.dev.local directly on /etc/hosts but you can use a service such as dnsmasq to achieve this.

Mkcert

We will use mkcert to manage the rootCA & generate our certificate.

Installation

🍏 MacOS

On MacOS, use Homebrew

brew install mkcert
brew install nss # if you use Firefox

🐧 Linux

On Linux, first install certutil.

sudo apt install libnss3-tools
curl -Lo /tmp/mkcert https://github.com/FiloSottile/mkcert/releases/download/v1.4.1/mkcert-v1.4.1-linux-amd64
chmod +x /tmp/mkcert
sudo mv /tmp/mkcert /usr/local/bin/mkcert

See more installation methods here 👌

Usage

First we need to install the local CA to the system and browsers.

$ mkcert -install
Created a new local CA at "/home/***/.local/share/mkcert" đŸ’Ĩ
The local CA is now installed in the system trust store! ⚡ī¸
The local CA is now installed in the Firefox trust store (requires browser restart)! đŸĻŠ

Next, we will use mkcert to generate our certificate. Using my example domain dev.local & the wildcard *.dev.local.

$ mkcert -cert-file certs/local-cert.pem -key-file certs/local-key.pem dev.local *.dev.local
Using the local CA at "/home/***/.local/share/mkcert" ✨

Created a new certificate valid for the following names 📜
 - "dev.local"
 - "*.dev.local"

Reminder: X.509 wildcards only go one level deep, so this won't match a.b.dev.local ℹī¸

The certificate is at "certs/local-cert.pem" and the key at "certs/local-key.pem" ✅

We can now use the certificate located at certs/local-cert.pem & certs/local-key.pem.

Next we will see how we will use this certificate for different apps.

Alt Text

BONUS: Wrapping everything in a Makefile for a dev-stack

here is how I organized my dev-stack, it's highly opinionated so take only what you need from it 😉!

📁 Folders Structure

project_root
├── dev-stack
│   ├── certs
│   │   ├── .gitignore
│   │   ├── local-cert.pem
│   │   └── local-key.pem
│   ├── scripts
│   │   ├── get-ip.sh
│   │   └── manage-hosts.sh
│   ├── .env.local
│   ├── .gitignore
│   ├── docker-compose.yml
│   ├── Makefile
│   └── README.md

Makefile

ifndef DEV_STACK_DIR
DEV_STACK_DIR = $(CURDIR)
endif
SCRIPTS_DIR=${DEV_STACK_DIR}/scripts

ifndef HOSTNAME
HOSTNAME = dev.local
endif
ifndef SUBDOMAINS
SUBDOMAINS = docs \
             traefik \
             mail \
             media \
             portainer \
             graphql \
             auth
endif
ifndef DATABASE
DATABASE = postgres
endif
ifndef INFRA
INFRA = traefik \
        maildev \
        minio \
        mkdocs \
        portainer \
        ${DATABASE} \
        graphql-engine \
        keycloak \
        auth-connector
endif

export HOST_IP := $(shell ${SCRIPTS_DIR}/get-ip.sh)

# HELP
.PHONY: help

help: ## List of the command available, make {command}
    @awk 'BEGIN {FS = ":.*?## "} /^[a-zA-Z_-]+:.*?## / {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}' $(MAKEFILE_LIST)

.DEFAULT_GOAL := help

start:  ## Start the docker stack
    docker-compose up -d ${INFRA}

up: ## Start the docker stack
    docker-compose up ${INFRA}

stop: ## Stop the docker stack
    docker-compose stop

restart: ## Restart the docker stack
    docker-compose restart

down: ## Down the docker stack and remove all containers and networks
    docker-compose down

build: ## Build or rebuild all docker container
    docker-compose build

pull: ## Pull latest image
    docker-compose pull

add-hosts: ## Add Hosts entries for Dev stack
    ${SCRIPTS_DIR}/manage-hosts.sh addhost ${HOSTNAME}
    $(foreach subdomain, $(SUBDOMAINS), ${SCRIPTS_DIR}/manage-hosts.sh addhost $(subdomain).$(HOSTNAME);)

remove-hosts: ## Remove Hosts entries for Dev stack
    ${SCRIPTS_DIR}/manage-hosts.sh removehost ${HOSTNAME}
    $(foreach subdomain, $(SUBDOMAINS), ${SCRIPTS_DIR}/manage-hosts.sh removehost $(subdomain).$(HOSTNAME);)

certs-generate: ## Generate certs for all our domains
    mkcert -install
    mkcert -cert-file certs/local-cert.pem -key-file certs/local-key.pem $(HOSTNAME) *.$(HOSTNAME)

certs-uninstall: ## Uninstall the local CA (but do not delete it)
    mkcert -uninstall

Scripts

get-ip.sh

#!/bin/bash

# Get host IP address

if [ "$(uname)" = "Darwin" ];then
    ifconfig en0 | grep "inet "| cut -d ' ' -f 2
else
    ip route get 1.2.3.4 | awk '{print $7}'
fi

manage-hosts.sh

#!/bin/bash

# copy from https://gist.github.com/irazasyed/a7b0a079e7727a4315b9

# PATH TO YOUR HOSTS FILE
ETC_HOSTS=/etc/hosts

# DEFAULT IP FOR HOSTNAME
IP="127.0.0.1"

# Hostname to add/remove.
HOSTNAME=$2

removehost() {
    echo "removing host";
    if [ -n "$(grep $HOSTNAME /etc/hosts)" ]
    then
        echo "$HOSTNAME Found in your $ETC_HOSTS, Removing now...";
        sudo sed -i".bak" "/$HOSTNAME/d" $ETC_HOSTS
    else
        echo "$HOSTNAME was not found in your $ETC_HOSTS";
    fi
}

addhost() {
    echo "adding host";
    HOSTS_LINE="$IP\t$HOSTNAME"
    if [ -n "$(grep $HOSTNAME /etc/hosts)" ]
        then
            echo "$HOSTNAME already exists : $(grep $HOSTNAME $ETC_HOSTS)"
        else
            echo "Adding $HOSTNAME to your $ETC_HOSTS";
            sudo -- sh -c -e "echo '$HOSTS_LINE' >> /etc/hosts";

            if [ -n "$(grep $HOSTNAME /etc/hosts)" ]
                then
                    echo "$HOSTNAME was added succesfully \n $(grep $HOSTNAME /etc/hosts)";
                else
                    echo "Failed to Add $HOSTNAME, Try again!";
            fi
    fi
}

$@

Usage of the certificate

→ See in next posts how you can now use this new generated certificates

  • Local HTTPS for Angular app in Nx workspace (or angular cli)
  • Local HTTPS for React app in Nx workspace
  • Local HTTPS for Express app (api) in Nx workspace
  • Local HTTPS for NestJS app (api) in Nx workspace
  • Local HTTPS for Docker services using Traefik

Github repository

GitHub logo Nightbr / full-https-development-environment

A full development environment in HTTPS with a valid certificate for your local development domain with mkcert, Nx workspace, angular, reactjs, nestjs, express, docker, traefik.

Myorg

This project was generated using Nx.

🔎 Nx is a set of Extensible Dev Tools for Monorepos.

Adding capabilities to your workspace

Nx supports many plugins which add capabilities for developing different types of applications and different tools.

These capabilities include generating applications, libraries, etc as well as the devtools to test, and build projects as well.

Below are our core plugins:

  • React
    • npm install --save-dev @nrwl/react
  • Web (no framework frontends)
    • npm install --save-dev @nrwl/web
  • Angular
    • npm install --save-dev @nrwl/angular
  • Nest
    • npm install --save-dev @nrwl/nest
  • Express
    • npm install --save-dev @nrwl/express
  • Node
    • npm install --save-dev @nrwl/node

There are also many community plugins you could add.

Generate an application

Run nx g @nrwl/react:app my-app to generate an application.

You can use any of the plugins above to generate applications as well.

When using Nx, you can create multiple applications and libraries in the same workspace.

Generate a library

Run nxâ€Ļ

Discussion

pic
Editor guide