From 8d26bd9324907fa90df394c06b8207b25d29a0f0 Mon Sep 17 00:00:00 2001
From: Thomas Misilo <tmisilo@ksu.edu>
Date: Fri, 11 Feb 2022 10:01:57 -0600
Subject: [PATCH] Add ability to enable ACME generation of SSL Certs

If the user enables USE_ACME, Traefik will attempt to acquire an SSL Certificate for ${DOMAIN}

Added the following variables with the defaults

USE_ACME=false
ACME_EMAIL-your-email
ACME_SERVER=https://acme-v02.api.letsencrypt.org/director
TRAEFIK_LOG_LEVEL=ERROR
---
 .gitignore                 |  1 +
 Makefile                   |  7 ++++++-
 docker-compose.acme.yml    | 41 ++++++++++++++++++++++++++++++++++++++
 docker-compose.traefik.yml | 38 ++++++++++++++++++-----------------
 sample.env                 |  5 +++++
 5 files changed, 73 insertions(+), 19 deletions(-)
 create mode 100644 docker-compose.acme.yml

diff --git a/.gitignore b/.gitignore
index 825049940..c21c645b2 100644
--- a/.gitignore
+++ b/.gitignore
@@ -91,3 +91,4 @@ Dockerfile
 #===================
 # User provided certs for TLS.
 certs
+acme
diff --git a/Makefile b/Makefile
index 3a337a4d4..2ec67a33f 100644
--- a/Makefile
+++ b/Makefile
@@ -43,6 +43,11 @@ ifeq ($(INCLUDE_TRAEFIK_SERVICE), true)
 	TRAEFIK_SERVICE := traefik
 endif
 
+# The service traefik may be optional if we are sharing one from another project.
+ifeq ($(USE_ACME), true)
+	ACME := acme
+endif
+
 # The service traefik may be optional if we are sharing one from another project.
 ifeq ($(INCLUDE_CODE_SERVER_SERVICE), true)
 	CODE_SERVER_SERVICE := code-server
@@ -79,7 +84,7 @@ DATABASE_SERVICES := $(sort $(DATABASE_SERVICES))
 # The services to be run (order is important), as services can override one
 # another. Traefik must be last if included as otherwise its network
 # definition for `gateway` will be overriden.
-SERVICES := $(REQUIRED_SERVICES) $(FCREPO_SERVICE) $(WATCHTOWER_SERVICE) $(ETCD_SERVICE) $(DATABASE_SERVICES) $(ENVIRONMENT) $(SECRETS) $(CODE_SERVER_SERVICE) $(TRAEFIK_SERVICE)
+SERVICES := $(REQUIRED_SERVICES) $(FCREPO_SERVICE) $(WATCHTOWER_SERVICE) $(ETCD_SERVICE) $(DATABASE_SERVICES) $(ENVIRONMENT) $(SECRETS) $(CODE_SERVER_SERVICE) $(TRAEFIK_SERVICE) $(ACME)
 
 default: download-default-certs docker-compose.yml pull
 
diff --git a/docker-compose.acme.yml b/docker-compose.acme.yml
new file mode 100644
index 000000000..de43d6d70
--- /dev/null
+++ b/docker-compose.acme.yml
@@ -0,0 +1,41 @@
+version: "3.7"
+services:
+  traefik:
+    # Do not set `api.insecure`, `api.dashboard`, `api.debug` to `true` in production.
+    # Also do not expose database 3306/5432, as an entry point.
+    # If the commands below are changed, please copy the changes to `docker-compose.acme.yml`.
+    command:
+      - --api.insecure=${EXPOSE_TRAEFIK_DASHBOARD:-false}
+      - --api.dashboard=${EXPOSE_TRAEFIK_DASHBOARD:-false}
+      - --api.debug=${EXPOSE_TRAEFIK_DASHBOARD:-false}
+      - --entryPoints.http.address=:80
+      - --entryPoints.https.address=:443
+      - --entryPoints.mysql.address=:3306
+      - --entryPoints.postgresql.address=:5432
+      - --entryPoints.fcrepo.address=:8081
+      - --entryPoints.blazegraph.address=:8082
+      - --entryPoints.activemq.address=:8161
+      - --entryPoints.solr.address=:8983
+      - --entryPoints.code-server.address=:8443
+      - --log.level=${TRAEFIK_LOG_LEVEL-ERROR}
+      - --providers.docker
+      - --providers.docker.network=gateway
+      - --providers.docker.exposedByDefault=false
+      - --providers.file.filename=/etc/traefik/tls.yml
+      - '--providers.docker.defaultRule=Host(`${DOMAIN}`)'
+      - --certificatesresolvers.myresolver.acme.httpchallenge=true
+      - --certificatesresolvers.myresolver.acme.httpchallenge.entrypoint=http
+      - --certificatesresolvers.myresolver.acme.email=${ACME_EMAIL-your-email@example.com}
+      - --certificatesresolvers.myresolver.acme.storage=/acme/acme.json
+      - --certificatesResolvers.myresolver.acme.caServer=${ACME_SERVER-https://acme-v02.api.letsencrypt.org/directory}
+    volumes:
+      - ./acme:/acme:rw
+  cantaloupe:
+    labels:
+      - traefik.http.routers.${COMPOSE_PROJECT_NAME-isle-dc}-cantaloupe_https.tls.certresolver=myresolver
+  drupal:
+    labels:
+      - traefik.http.routers.${COMPOSE_PROJECT_NAME-isle-dc}-drupal_https.tls.certresolver=myresolver
+  matomo:
+    labels:
+      - traefik.http.routers.${COMPOSE_PROJECT_NAME-isle-dc}-matomo_https.tls.certresolver=myresolver
diff --git a/docker-compose.traefik.yml b/docker-compose.traefik.yml
index a56b17f11..d186249d7 100644
--- a/docker-compose.traefik.yml
+++ b/docker-compose.traefik.yml
@@ -19,24 +19,26 @@ services:
     container_name: traefik
     # Do not set `api.insecure`, `api.dashboard`, `api.debug` to `true` in production.
     # Also do not expose database 3306/5432, as an entry point.
-    command: >-
-      --api.insecure=${EXPOSE_TRAEFIK_DASHBOARD:-false}
-      --api.dashboard=${EXPOSE_TRAEFIK_DASHBOARD:-false}
-      --api.debug=${EXPOSE_TRAEFIK_DASHBOARD:-false}
-      --entryPoints.http.address=:80
-      --entryPoints.https.address=:443
-      --entryPoints.mysql.address=:3306
-      --entryPoints.postgresql.address=:5432
-      --entryPoints.fcrepo.address=:8081
-      --entryPoints.blazegraph.address=:8082
-      --entryPoints.activemq.address=:8161
-      --entryPoints.solr.address=:8983
-      --entryPoints.code-server.address=:8443
-      --providers.docker
-      --providers.docker.network=gateway
-      --providers.docker.exposedByDefault=false
-      --providers.file.filename=/etc/traefik/tls.yml
-      '--providers.docker.defaultRule=Host(`${DOMAIN}`)'
+    # If the commands below are changed, please copy the changes to `docker-compose.acme.yml`.
+    command:
+      - --api.insecure=${EXPOSE_TRAEFIK_DASHBOARD:-false}
+      - --api.dashboard=${EXPOSE_TRAEFIK_DASHBOARD:-false}
+      - --api.debug=${EXPOSE_TRAEFIK_DASHBOARD:-false}
+      - --entryPoints.http.address=:80
+      - --entryPoints.https.address=:443
+      - --entryPoints.mysql.address=:3306
+      - --entryPoints.postgresql.address=:5432
+      - --entryPoints.fcrepo.address=:8081
+      - --entryPoints.blazegraph.address=:8082
+      - --entryPoints.activemq.address=:8161
+      - --entryPoints.solr.address=:8983
+      - --entryPoints.code-server.address=:8443
+      - --log.level=${TRAEFIK_LOG_LEVEL-ERROR}
+      - --providers.docker
+      - --providers.docker.network=gateway
+      - --providers.docker.exposedByDefault=false
+      - --providers.file.filename=/etc/traefik/tls.yml
+      - '--providers.docker.defaultRule=Host(`${DOMAIN}`)'
     ports:
       - 80:80       # drupal, cantaloupe, matomo
       - 443:443     # https for ^^^
diff --git a/sample.env b/sample.env
index 5c7b9748e..08e7d24d9 100644
--- a/sample.env
+++ b/sample.env
@@ -36,6 +36,11 @@ PROJECT_DRUPAL_DOCKERFILE=Dockerfile
 # from another project.
 INCLUDE_TRAEFIK_SERVICE=true
 
+# Should we use ACME to generate a SSL Certificate
+USE_ACME=false
+# Specify email to tie SSL Certificate to with ACME provider
+ACME_EMAIL=your-email@example.com
+
 # Includes `watchtower` as a service.
 INCLUDE_WATCHTOWER_SERVICE=false