diff --git a/README.md b/README.md index 8e7bfce..46a8786 100644 --- a/README.md +++ b/README.md @@ -49,9 +49,9 @@ Your tomcat server must be configured to * respond with HTTP return code less than 400, on `http://localhost:${LOCAL_HTTP_PORT}/` (default port 8080). If successful, the certificate files will be stored here: - * Certificate file: `/certs/${DOMAIN}/cert.pem` - * Certificate private key file: `/certs/${DOMAIN}/privkey.pem` - * Certificate chain file: `/certs/${DOMAIN}/fullchain.pem` + * Certificate file: `${CERT_DIR}/${DOMAIN}/cert.pem` + * Certificate private key file: `${CERT_DIR}/${DOMAIN}/privkey.pem` + * Certificate chain file: `${CERT_DIR}/${DOMAIN}/fullchain.pem` # Configuration at runtime @@ -63,8 +63,20 @@ If successful, the certificate files will be stored here: * `ENABLE_LETSENCRYPT` - if set to `false` the letsencrypt process is not started * `CREATE_SELFSIGNED` - if set to `false` no selfsigned certifcate is generated at start up. Depending on your setup this might result in failing startup of the tomcat connectors -* Persistence: Your certs are stored inside your container at `CERT_DIR` (default: `/certs/`), so you might want to - persist this folder. + * `DEHYDRATED_BASEDIR` - defaults to `/dehydrated` for compatibility with letsencrypt-tomcat <= 0.40. + * `CERT_DIR` - if `DEHYDRATED_BASEDIR` is set, defaults to `$DEHYDRATED_BASEDIR/certs`, which is the default of dehydrated. If `DEHYDRATED_BASEDIR` is not set, defaults to `/certs` to be compatible with older letsencrypt-tomcat releases <=0.4.0. + * `DEHYDRATED_WELLKNOWN` - path where dehydrated will place ACME challenge files. Should usually be the document root of a webserver with `/.well-known/acme-challenge` appended. + +Note: if you want to save certificates and accounts in persistent storage it is highly recommended to set `DEHYDRATED_BASEDIR` env variable as described below. + +`DEHYDRATED_BASEDIR` and `CERT_DIR` interact: + * default (<=0.4.0) if `DEHYDRATED_BASEDIR` is not set: + * `DEHYDRATED_BASEDIR="/dehydrated" CERT_DIR="/certs"` + * `/dehydrated` is not stored in persistent storage and will be deleted with the container (including the letsencrypt account) + * recommended (>0.4.0): + * set `DEHYDRATED_BASEDIR="/certs/dehydrated"`. This will set `CERT_DIR="$DEHYDRATED_BASEDIR/certs"`. This allows all the certificates and dehydrated state (most importantly, accounts) to be stored in one directory, usually a volume mounted at `/certs`. + +It is possible to set environment variables in any place Docker supports, and will make them set in the container. This is: in a Dockerfile, as run parameters, as docker-compose.yml configuration, or in an .env file. # Run Examples @@ -94,4 +106,4 @@ docker build -t schnatterer/letsencrypt-tomcat . docker build -t schnatterer/letsencrypt-tomcat:standalone --file=examples/standalone/Dockerfile . docker build -t schnatterer/letsencrypt-tomcat:spring-boot --file=examples/spring-boot/Dockerfile . docker build -t schnatterer/letsencrypt-tomcat:embedded-tomcat --file=examples/embedded-tomcat/Dockerfile . -``` \ No newline at end of file +``` diff --git a/etc/dehydrated/config b/etc/dehydrated/config index 8a2121c..84cc44c 100644 --- a/etc/dehydrated/config +++ b/etc/dehydrated/config @@ -1,4 +1,5 @@ # See https://github.com/dehydrated-io/dehydrated/blob/master/docs/examples/config -WELLKNOWN="/static/.well-known/acme-challenge" -BASEDIR="/dehydrated" +WELLKNOWN="$DEHYDRATED_WELLKNOWN" +BASEDIR="$DEHYDRATED_BASEDIR" +CERTDIR="$CERT_DIR" diff --git a/examples/embedded-tomcat/Dockerfile b/examples/embedded-tomcat/Dockerfile index 5184532..2af80ed 100644 --- a/examples/embedded-tomcat/Dockerfile +++ b/examples/embedded-tomcat/Dockerfile @@ -21,6 +21,7 @@ RUN mvn package FROM letsencrypt-tomcat as aggregator # Copy letsencrypt-related stuff RUN mv /letsencrypt /dist +ENV DEHYDRATED_BASEDIR="/certs/dehydrated" # Copy Libraries: Apache Portable Runtime (APR) and JNI wrappers for APR used by Tomcat (libtcnative) RUN cp -r /lib/* /dist/ diff --git a/examples/embedded-tomcat/src/main/java/info/schnatterer/tomcat/Main.java b/examples/embedded-tomcat/src/main/java/info/schnatterer/tomcat/Main.java index 7148497..0affa61 100644 --- a/examples/embedded-tomcat/src/main/java/info/schnatterer/tomcat/Main.java +++ b/examples/embedded-tomcat/src/main/java/info/schnatterer/tomcat/Main.java @@ -15,7 +15,7 @@ public class Main { private static final int HTTPS_PORT = 8443; public static final String DOMAIN = System.getenv("DOMAIN"); - public static final String CERT_FOLDER = "/certs/"; + public static final String CERT_FOLDER = System.getenv("CERT_DIR"); public static final String PK = CERT_FOLDER + DOMAIN + "/privkey.pem"; public static final String CRT = CERT_FOLDER + DOMAIN + "/cert.pem"; public static final String CA = CERT_FOLDER + DOMAIN + "/fullchain.pem"; diff --git a/examples/spring-boot/Dockerfile b/examples/spring-boot/Dockerfile index 51a6298..64ef303 100644 --- a/examples/spring-boot/Dockerfile +++ b/examples/spring-boot/Dockerfile @@ -21,6 +21,7 @@ RUN mvn package FROM letsencrypt-tomcat as aggregator # Copy letsencrypt-related stuff RUN mv /letsencrypt /dist +ENV DEHYDRATED_BASEDIR="/certs/dehydrated" # Copy Libraries: Apache Portable Runtime (APR) and JNI wrappers for APR used by Tomcat (libtcnative) RUN cp -r /lib/* /dist/ diff --git a/examples/spring-boot/src/main/resources/application.properties b/examples/spring-boot/src/main/resources/application.properties index e14803b..4cfb082 100644 --- a/examples/spring-boot/src/main/resources/application.properties +++ b/examples/spring-boot/src/main/resources/application.properties @@ -4,6 +4,6 @@ server.http.port=8080 # Needed so the letsencrypt challenge is served by tomcat spring.resources.staticLocations=file:/static -server.ssl.certificateKeyFile=/certs/${DOMAIN}/privkey.pem -server.ssl.certificateFile=/certs/${DOMAIN}/cert.pem -server.ssl.certificateChainFile=/certs/${DOMAIN}/fullchain.pem \ No newline at end of file +server.ssl.certificateKeyFile=${certdir}/${DOMAIN}/privkey.pem +server.ssl.certificateFile=${certdir}/${DOMAIN}/cert.pem +server.ssl.certificateChainFile=${certdir}/${DOMAIN}/fullchain.pem diff --git a/examples/standalone/Dockerfile b/examples/standalone/Dockerfile index 4621005..076a664 100644 --- a/examples/standalone/Dockerfile +++ b/examples/standalone/Dockerfile @@ -7,17 +7,14 @@ FROM schnatterer/letsencrypt-tomcat:${LETSENCRYPT_TOMCAT_VERSION} as letsencrypt FROM letsencrypt-tomcat as aggregator # Copy letsencrypt-related stuff RUN mv /letsencrypt /dist +ENV DEHYDRATED_BASEDIR="/certs/dehydrated" # Copy reloding connector, so tomcat can automatically reload certificates at runtime RUN mkdir -p /dist/opt/bitnami/tomcat/lib/ RUN cp -r /tomcat-reloading-connector/* /dist/opt/bitnami/tomcat/lib/ -# Make standalone tomcat serve static files in directories used for letsencrypt challenges -RUN mkdir -p /dist/opt/bitnami/tomcat/webapps/ROOT/.well-known/acme-challenge -# It would be simpler to link ROOT -> static but it seems that tomcat does not follow symlinks when serving static content -# So just do it the other way round -RUN rm -rf /dist/static/.well-known/acme-challenge -RUN ln -s /opt/bitnami/tomcat/webapps/ROOT/.well-known/acme-challenge /dist/static/.well-known/acme-challenge +# set directory where dehydrated will create ACME challenge files +ENV DEHYDRATED_WELLKNOWN="/opt/bitnami/tomcat/webapps/ROOT/.well-known/acme-challenge" # Copy examples/standalone tomcat config COPY examples/standalone/tomcat /dist/opt/bitnami/tomcat/ @@ -31,4 +28,4 @@ FROM tomcat VOLUME /certs/ COPY --from=aggregator --chown=1001:0 /dist / ENTRYPOINT [ "/meta-entrypoint.sh", "/opt/bitnami/scripts/tomcat/entrypoint.sh" ] -CMD [ "/opt/bitnami/scripts/tomcat/run.sh" ] \ No newline at end of file +CMD [ "/opt/bitnami/scripts/tomcat/run.sh" ] diff --git a/examples/standalone/tomcat/conf/server.xml b/examples/standalone/tomcat/conf/server.xml index e47a6d6..d9fa724 100644 --- a/examples/standalone/tomcat/conf/server.xml +++ b/examples/standalone/tomcat/conf/server.xml @@ -103,9 +103,9 @@ maxThreads="150" SSLEnabled="true" > - diff --git a/meta-entrypoint.sh b/meta-entrypoint.sh index bea0df5..afa4ebf 100644 --- a/meta-entrypoint.sh +++ b/meta-entrypoint.sh @@ -8,8 +8,11 @@ CREATE_SELFSIGNED=${CREATE_SELFSIGNED:-'true'} STAGING=${STAGING:-'false'} NO_COLOR=${NO_COLOR:-''} SELF_SIGNED_CERT_VALIDITY_DAYS=${SELF_SIGNED_CERT_VALIDITY_DAYS:-30} -CERT_DIR=${CERT_DIR:-"/certs/"} -export JAVA_OPTS="-Djava.awt.headless=true -XX:+UseG1GC -Dfile.encoding=UTF-8 -Ddomain=${DOMAIN}" +: "${CERT_DIR:="${DEHYDRATED_BASEDIR}/certs"}" +: "${DEHYDRATED_BASEDIR:="/dehydrated"}" +: "${DEHYDRATED_WELLKNOWN:="/static"}" +export CERT_DIR DEHYDRATED_BASEDIR DEHYDRATED_WELLKNOWN +export JAVA_OPTS="-Djava.awt.headless=true -XX:+UseG1GC -Dfile.encoding=UTF-8 -Dcertdir=${CERT_DIR} -Ddomain=${DOMAIN}" function main() { @@ -68,6 +71,8 @@ createSelfSignedCert() { } function fetchCerts() { + mkdir -vp "$DEHYDRATED_BASEDIR" + mkdir -vp "$DEHYDRATED_WELLKNOWN" if [[ "${STAGING}" == "true" ]]; then echo 'CA="https://acme-staging-v02.api.letsencrypt.org/directory"' >> /etc/dehydrated/config @@ -83,7 +88,7 @@ function fetchCerts() { while [[ "${SIG_INT_RECEIVED}" == 'false' ]]; do green "Fetching certificates" - dehydrated --domain ${DOMAIN} --cron --accept-terms --out ${CERT_DIR} && exitCode=$? || exitCode=$? + dehydrated --domain ${DOMAIN} --cron --accept-terms && exitCode=$? || exitCode=$? if [[ "${exitCode}" > 0 ]]; then red "Fetching certificates failed" fi @@ -113,4 +118,4 @@ RED='\033[0;31m' DEFAULT_COLOR='\033[0m' -main "$@" \ No newline at end of file +main "$@"