diff --git a/Dockerfile b/Dockerfile index 98a1d39..8692fa7 100644 --- a/Dockerfile +++ b/Dockerfile @@ -21,5 +21,11 @@ RUN \ a2enconf allow-override-all && \ a2enconf php-fpm +RUN \ + mkdir /cert && \ + mkdir /mkcert && \ + curl -sSL https://github.com/FiloSottile/mkcert/releases/download/v1.3.0/mkcert-v1.3.0-linux-amd64 -o /usr/local/bin/mkcert && \ + chmod +x /usr/local/bin/mkcert + EXPOSE 80 EXPOSE 443 diff --git a/README.md b/README.md index d64f2b6..fcfab9d 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,89 @@ # Apache FPM container based on phusion Simple apache-vhost that serves content from /var/www/web - php-requests are proxied to a linked fpm-container named "fpm" on port 9000. + + +# Dory + +Use the following if you use [dory](https://github.com/FreedomBen/dory) (much of the same applies for [nginx-proxy](https://github.com/jwilder/nginx-proxy) and [dinghy-http-proxy](https://github.com/codekitchen/dinghy-http-proxy) which Dory is based on). + +```yaml + environment: + VIRTUAL_HOST: example.docker + VIRTUAL_PORT: 80 + # Use the following if you want to handle redirects from http to https yourself. + HTTPS_METHOD: noredirect + +``` + +## Using autogenerated certificates +This require Dory version 1.0.3, use `dory upgrade` to upgrade + +If you don't already have a Dory configuration-file, have it generate one by running `dory config` then update the update `ssl_certs_dir` configuration: + +```yaml + nginx_proxy: + enabled: true + container_name: dory_dinghy_http_proxy + https_enabled: true + # Update the follow line to point at the dev_certificates + ssl_certs_dir: /.local/share/dev_certificates +``` + +Then mount that directory into the apache-fpm container so that its auto-generated certificates will be accessible to Dory. + +```yaml + volumes: + - '${HOME}/.local/share/dev_certificates:/cert:rw' +``` + +Then follow the steps in the mkcert sections to specify which certificates to generate and have your OS trust them. + +# mkcert + +This image has [mkcert](https://github.com/FiloSottile/mkcert) +builtin. + +Install `mkcert` on your host machine and generate and install a root +certificate by running `mkcert -install` on your host machine. + +Then you add the generated CAROOT as a volume (the path on the host +machine is the output of `mkcert -CAROOT`). + +In your `docker-compose.yml` supply one or more host names to be be +used for HTTPS. Host names will be search for in these location and in +this order: + +1. environment variable `MKCERT_DOMAINS` (several hostnames separated + by space is possible, you can even supply a wildcard domain), +1. the environment variable `VIRTUAL_HOST` (as used by [Dinghy HTTP + Proxy](https://github.com/codekitchen/dinghy-http-proxy)), or +1. the output of `hostname -f` in the container (which can be set with + the `hostname` and `domainname` options). + +```yaml + volumes: + - '${HOME}/Library/Application Support/mkcert:/mkcert/mac:ro' + - '${HOME}/.local/share/mkcert:/mkcert/linux:ro' + + environment: + MKCERT_DOMAINS: "example.docker *.example.docker local.docker" + + hostname: example + domainname: docker +``` + +# Full example configuration + +```yaml + volumes: + - '${HOME}/Library/Application Support/mkcert:/mkcert/mac:ro' + - '${HOME}/.local/share/mkcert:/mkcert/linux:ro' + - '${HOME}/.local/share/dev_certificates:/cert:rw' + + environment: + MKCERT_DOMAINS: "example.docker *.example.docker local.docker" + VIRTUAL_HOST: example.docker + VIRTUAL_PORT: 80 + HTTPS_METHOD: noredirect +``` diff --git a/files/etc/my_init.d/mkcert.sh b/files/etc/my_init.d/mkcert.sh new file mode 100755 index 0000000..bfe8b37 --- /dev/null +++ b/files/etc/my_init.d/mkcert.sh @@ -0,0 +1,54 @@ +#!/bin/bash + +set -euo pipefail + +# Try to locate `rootCA.pem` and `rootCA-key.pem` in a folder beneath +# `/mkcert`. +CAROOT="$(find /mkcert -type d -exec sh -c '[ -f "$0"/rootCA.pem ] && [ -f "$0"/rootCA-key.pem ]' '{}' \; -print)" +export CAROOT + +# If no root CA found just exit now without generating any +# certificates. +if [[ -z "${CAROOT}" ]]; then + exit 0; +fi + +# If no VIRTUAL_HOST is set use `hostname -f` as fallback. +VIRTUAL_HOST="${VIRTUAL_HOST:-$(hostname -f)}" + +# Dinghys wildcard syntax is prefixing only with a dot (as in +# `.example.com`). We rewrite those to use an asterisk as expected by +# mkcert (`*.example.com`). +VIRTUAL_HOST="${VIRTUAL_HOST/#./*.}" + +# If on MKCERT_DOMAINS is set use VIRTUAL_HOST as fallback. +MKCERT_DOMAINS="${MKCERT_DOMAINS:-${VIRTUAL_HOST}}" + +# If we couldn't find any domain names just exit now without +# generating any certificates. +if [[ -z "${MKCERT_DOMAINS}" ]]; then + exit 0; +fi + +# Split a space separated string into a bash array. +IFS=' ' read -r -a MKCERT_DOMAINS <<< "${MKCERT_DOMAINS}" + +# Install the CA certificate in the Docker containers system trust +# store. Mostly we do that to ignore warnings about the CA not being +# installed when generating certificates later (but also to trust the +# certificates from within). +/usr/local/bin/mkcert -install + +# Run `mkcert` to generate certificate and key. +/usr/local/bin/mkcert -cert-file /etc/ssl/certs/ssl-cert-snakeoil.pem -key-file /etc/ssl/private/ssl-cert-snakeoil.key "${MKCERT_DOMAINS[@]}" + +# Expose the generated certificate in /cert named after the first +# domain name (compatible with Dory / nginx-proxy). +echo "Copying certficate(s) and key(s) into /cert:" +for domain in "${MKCERT_DOMAINS[@]}" +do + # Strip wildcard. + domain="${domain#\*\.}" + cp -v /etc/ssl/certs/ssl-cert-snakeoil.pem "/cert/${domain}.crt" + cp -v /etc/ssl/private/ssl-cert-snakeoil.key "/cert/${domain}.key" +done