diff --git a/Dockerfile b/Dockerfile index c91f408..b448d17 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,6 +1,12 @@ FROM nginx:1.21.4-alpine +RUN mkdir -p /nginx +COPY nginx-http-redir.conf /nginx/default.conf + +# For renewing the certificates +COPY renew_cert.sh /etc/periodic/daily/ + RUN apk update && apk add certbot bind-tools -COPY entrypoint.sh nginx-http-redir.conf / +COPY entrypoint.sh / CMD ["/entrypoint.sh"] diff --git a/README.md b/README.md index 357f858..4eb53d3 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,8 @@ The assumption is that you can point the DNS name to the container from outside. This is by default given for **IPv6 only kubernetes services**. +The source of this image can be found on +[code.ungleich.ch](https://code.ungleich.ch/ungleich-public/ungleich-certbot). ## Usage @@ -21,66 +23,51 @@ services**. certificates, so that non-root users can access the certificates. Set the LEAVE_PERMISSIONS_AS_IS environment variable to instruct the container not to change permissions -* If you setup the variable NGINX to any value, the container will - start nginx and reload after trying to renew the certificate -* If you set the variable NGINX_HTTP_REDIRECT, the container will - enable automatic redirect of http to https with the exception of the - path /.well-known/acme-challenge/ +* If you setup the variable NO_NGINX to any value, the container will + NOT start nginx and use certbot in standalone mode ``` docker run -e DOMAIN=example.com \ -e EMAIL=root@example.com \ - ungleich/ungleich-certbot + ungleich/ungleich-certbot:1.0.0 ``` -### Nginx support +### Production certificate -Using +Use ``` docker run -e DOMAIN=example.com \ -e EMAIL=root@example.com \ - -e NGINX=yes \ -e STAGING=no \ - ungleich/ungleich-certbot + ungleich/ungleich-certbot:1.0.0 ``` you will get a proper, real world usable nginx server. Inject the nginx configuration by meains of a volume to /etc/nginx/conf.d -### Nginx HTTP redirect support - -Using - -``` -docker run -e DOMAIN=example.com \ - -e EMAIL=root@example.com \ - -e NGINX=yes \ - -e NGINX_HTTP_REDIRECT=yes \ - -e STAGING=no \ - ungleich/ungleich-certbot -``` - -the container will listen on port 80 and redirect the traffic to port -443 (https). - ### Exiting after getting the certificate By default, the container will stay alive and try to renew the -certificate every 86400 seconds. If you set the environment variable +certificate every day. If you set the environment variable `ONLYGETCERT`, then it will only get the certificates and exit. -### Only renewing the certificate +This mode can be used +as a [kubernetes Job](https://kubernetes.io/docs/concepts/workloads/controllers/job/). + +### Only renewing the certificate once If you only want to trigger renewing existing certificates and skip getting the certificates initially, you can set the variable `RENEWCERTSONCE`, then it will only renew all certificates and exit. -* If `ONLYRENEWCERTS` is set, only the reguler renew loop will run. * If `ONLYRENEWCERTSONCE` is set, renew will be run once and then the container exits +This mode can be used +as a [kubernetes Job](https://kubernetes.io/docs/concepts/workloads/controllers/job/). + ## Volumes If you want to keep / use your certificates, you are advised to create @@ -88,9 +75,30 @@ a volume below /etc/letsencrypt. ## Changelog -* 0.1.0: usable with automatic renewal -* 0.2.0: added support for nginx webserver (based on official nginx - image) +### 0.1.0 + + +Usable with automatic renewal + +### 0.2.0 + +Added support for nginx webserver, based on official nginx image + +### 1.0.0 + +- Start nginx in foreground, if not opted out + - Nicely shows erros of nginx starting, which is what we need +- Starting nginx by default on port 80 +- Removed variable NGINX to start nginx +- Introducted variable NO_NGINX to prevent nginx from starting +- Changed the wait time for domain resolution test to every 2 seconds + - helps to startup faster +- Added directory /nginx from which configuration files are sourced + - can be used to overwrite built-in configurations +- Create file /tmp/last_renew for checking when +- Dropped support for NGINX_HTTP_REDIRECT (always enabled with nginx + now) -- can be overwritten by overriding /nginx directory +- Dropped support for ONLYRENEWCERTS - this is covered by NO_NGINX already ## Kubernetes diff --git a/entrypoint.sh b/entrypoint.sh index 99462dc..1ed0508 100755 --- a/entrypoint.sh +++ b/entrypoint.sh @@ -1,5 +1,6 @@ #!/bin/sh + if [ -z "$DOMAIN" -o -z "$EMAIL" ]; then echo Missing DOMAIN or EMAIL parameter - aborting. >&2 exit 1 @@ -18,8 +19,8 @@ while [ -z "$ipv6_addr" -a -z "$ipv4_addr" ]; do if [ "$ipv6_addr" -o "$ipv4_addr" ]; then echo "Resolved domain $DOMAIN: ipv6: $ipv6_addr ipv4: $ipv4_addr" else - echo "Resolving $DOMAIN failed, waiting 5 seconds before retrying ..." - sleep 5 + echo "Resolving $DOMAIN failed, waiting 2 seconds before retrying ..." + sleep 2 fi done @@ -55,34 +56,16 @@ if [ "$ONLYGETCERT" ]; then exit 0 fi -# Still there? Start nginx if requested +# Before starting nginx, try to renew to ensure we are up-to-date +# This is necessary for container restarts not to delay a needed renew +/usr/bin/certbot renew --standalone -if [ "$NGINX" ]; then +# If it requested to renew once only we are done here +[ "$ONLYRENEWCERTSONCE" ] && exit 0 - if [ "$NGINX_HTTP_REDIRECT" ]; then - cp /nginx-http-redir.conf /etc/nginx/conf.d - fi - nginx +if [ "$NO_NGINX" ]; then + sleep infinity +else + cp /nginx/* /etc/nginx/conf.d + nginx -g "daemon off;" fi - -# Try to renew once per day -while true; do - if [ "$NGINX_HTTP_REDIRECT" ]; then - /usr/bin/certbot renew --webroot --webroot-path /var/www/html - else - /usr/bin/certbot renew - fi - - # And again, correct permissions if not told otherwise - if [ -z "$LEAVE_PERMISSIONS_AS_IS" ]; then - find /etc/letsencrypt -type d -exec chmod 0755 {} \; - find /etc/letsencrypt -type f -exec chmod 0644 {} \; - fi - - [ "$ONLYRENEWCERTSONCE" ] && exit 0 - - # reload nginx if we are running it - [ "$NGINX" ] && pkill -1 nginx - - sleep 86400 -done diff --git a/get_cert.sh b/get_cert.sh new file mode 100755 index 0000000..1ec2a36 --- /dev/null +++ b/get_cert.sh @@ -0,0 +1,19 @@ +#!/bin/sh + +while [ ! -f "/etc/letsencrypt/live/${DOMAIN}/fullchain.pem" ]; do + certbot certonly --agree-tos --cert-name "${DOMAIN}" \ + --email "$EMAIL" --expand --non-interactive \ + --domain "$DOMAIN" --standalone $STAGING + + # If it failed, sleep before next try + if [ ! -f "/etc/letsencrypt/live/${DOMAIN}/fullchain.pem" ]; then + sleep 30 + fi + + # Correct permissions for multi user container/pod deployments + # if not indicated otherwise + if [ -z "$LEAVE_PERMISSIONS_AS_IS" ]; then + find /etc/letsencrypt -type d -exec chmod 0755 {} \; + find /etc/letsencrypt -type f -exec chmod 0644 {} \; + fi +done diff --git a/renew_cert.sh b/renew_cert.sh new file mode 100755 index 0000000..3e64ea3 --- /dev/null +++ b/renew_cert.sh @@ -0,0 +1,17 @@ +#!/bin/sh + +if [ "$NO_NGINX" ]; then + /usr/bin/certbot renew --standalone +else + /usr/bin/certbot renew --webroot --webroot-path /var/www/html + # Reload nginx + pkill -1 nginx +fi + +# Correct permissions if not told otherwise +if [ -z "$LEAVE_PERMISSIONS_AS_IS" ]; then + find /etc/letsencrypt -type d -exec chmod 0755 {} \; + find /etc/letsencrypt -type f -exec chmod 0644 {} \; +fi + +echo "Last renew: $(date)" > /tmp/last_renew