├── apache_config ├── new-default.conf └── 001-default-le-ssl.conf ├── supervisord.conf ├── Dockerfile ├── example └── docker-compose.yml ├── includes ├── run.sh └── renew.sh └── README.md /apache_config/new-default.conf: -------------------------------------------------------------------------------- 1 | 2 | Redirect / https://${HOST}/ 3 | 4 | -------------------------------------------------------------------------------- /supervisord.conf: -------------------------------------------------------------------------------- 1 | [supervisord] 2 | nodaemon=true 3 | 4 | [program:apache] 5 | command=apache2ctl -DFOREGROUND 6 | stdout_logfile=/dev/fd/1 7 | stdout_logfile_maxbytes=0 8 | redirect_stderr=true 9 | 10 | [program:letsencrypt] 11 | command=/bin/bash -c "/run.sh" 12 | stdout_logfile=/dev/fd/1 13 | stdout_logfile_maxbytes=0 14 | redirect_stderr=true 15 | autorestart=false 16 | 17 | [program:letsencrypt-renew] 18 | command=/bin/bash -c "/renew.sh" 19 | stdout_logfile=/dev/fd/1 20 | stdout_logfile_maxbytes=0 21 | redirect_stderr=true 22 | autostart=false 23 | autorestart=true 24 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:15.10 2 | 3 | RUN apt-get update 4 | 5 | RUN apt-get install -y git apache2 bc supervisor 6 | 7 | RUN a2enmod proxy_http 8 | RUN a2enmod ssl 9 | 10 | RUN git clone https://github.com/letsencrypt/letsencrypt 11 | 12 | RUN letsencrypt/letsencrypt-auto --help > /dev/null 13 | 14 | COPY supervisord.conf /etc/supervisor/conf.d/supervisord.conf 15 | 16 | ADD includes/run.sh /run.sh 17 | ADD includes/renew.sh /renew.sh 18 | RUN chmod +x /run.sh 19 | RUN chmod +x /renew.sh 20 | 21 | EXPOSE 443 22 | EXPOSE 80 23 | 24 | ADD apache_config /etc/apache2/sites-available/ 25 | 26 | CMD ["/usr/bin/supervisord"] 27 | -------------------------------------------------------------------------------- /example/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '2' 2 | services: 3 | proxy: 4 | image: sashee/letsencrypt-proxy-docker 5 | ports: 6 | - "80:80" 7 | - "443:443" 8 | depends_on: 9 | - angular 10 | networks: 11 | - proxy 12 | environment: 13 | # Set your host 14 | #- HOST= 15 | - PORT=80 16 | # Set your email 17 | #- EMAIL= 18 | # Turn on production mode 19 | #- MODE=PRODUCTION 20 | links: 21 | - angular:proxied 22 | angular: 23 | image: thanhson1085/angular-admin-seed 24 | networks: 25 | - proxy 26 | networks: 27 | proxy: 28 | -------------------------------------------------------------------------------- /includes/run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | /letsencrypt/letsencrypt-auto certonly --renew-by-default --webroot -w /var/www/html `if [ -z "$EMAIL" ]; then echo "--register-unsafely-without-email"; else echo "--email $EMAIL"; fi` -d $HOST --agree-tos --text `if [ "$MODE" != "PRODUCTION" ]; then echo "--test-cert"; fi` 4 | 5 | ln -s /etc/apache2/sites-available/001-default-le-ssl.conf /etc/apache2/sites-enabled/001-default-le-ssl.conf 6 | rm /etc/apache2/sites-enabled/000-default.conf 7 | mv /etc/apache2/sites-available/new-default.conf /etc/apache2/sites-available/000-default.conf 8 | ln -s /etc/apache2/sites-available/000-default.conf /etc/apache2/sites-enabled/000-default.conf 9 | 10 | apache2ctl -k restart 11 | 12 | supervisorctl start letsencrypt-renew 13 | -------------------------------------------------------------------------------- /includes/renew.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # From https://community.letsencrypt.org/t/how-to-completely-automating-certificate-renewals-on-debian/5615 4 | DAYS_REMAINING=30; 5 | 6 | get_days_exp() { 7 | local d1=$(date -d "`openssl x509 -in $1 -text -noout|grep "Not After"|cut -c 25-`" +%s) 8 | local d2=$(date -d "now" +%s) 9 | # Return result in global variable 10 | DAYS_EXP=$(echo \( $d1 - $d2 \) / 86400 |bc) 11 | } 12 | get_days_exp "/etc/letsencrypt/live/${HOST}/cert.pem" 13 | 14 | echo "Expire in ${DAYS_EXP} days" 15 | 16 | if [ "$DAYS_EXP" -gt "$DAYS_REMAINING" ]; then 17 | echo "Renewal is not necessary." 18 | else 19 | echo "Renewing" 20 | /letsencrypt/letsencrypt-auto certonly --renew-by-default --webroot -w /var/www/html `if [ -z "$EMAIL" ]; then echo "--register-unsafely-without-email"; else echo "--email $EMAIL"; fi` -d $HOST --agree-tos --text `if [ "$MODE" != "PRODUCTION" ]; then echo "--test-cert"; fi` 21 | 22 | apache2ctl -k restart 23 | fi 24 | 25 | sleep 1d 26 | -------------------------------------------------------------------------------- /apache_config/001-default-le-ssl.conf: -------------------------------------------------------------------------------- 1 | ServerName ${HOST} 2 | 3 | 4 | 5 | # The ServerName directive sets the request scheme, hostname and port that 6 | # the server uses to identify itself. This is used when creating 7 | # redirection URLs. In the context of virtual hosts, the ServerName 8 | # specifies what hostname must appear in the request's Host: header to 9 | # match this virtual host. For the default virtual host (this file) this 10 | # value is not decisive as it is used as a last resort host regardless. 11 | # However, you must set it for any further virtual host explicitly. 12 | #ServerName www.example.com 13 | 14 | 15 | # Available loglevels: trace8, ..., trace1, debug, info, notice, warn, 16 | # error, crit, alert, emerg. 17 | # It is also possible to configure the loglevel for particular 18 | # modules, e.g. 19 | #LogLevel info ssl:warn 20 | 21 | ErrorLog ${APACHE_LOG_DIR}/error.log 22 | CustomLog ${APACHE_LOG_DIR}/access.log combined 23 | 24 | ProxyPass /.well-known ! 25 | ProxyPass / "http://proxied:${PORT}/" 26 | Alias /.well-known /var/www/html/.well-known 27 | 28 | # For most configuration files from conf-available/, which are 29 | # enabled or disabled at a global level, it is possible to 30 | # include a line for only one particular virtual host. For example the 31 | # following line enables the CGI configuration for this host only 32 | # after it has been globally disabled with "a2disconf". 33 | #Include conf-available/serve-cgi-bin.conf 34 | SSLCertificateFile /etc/letsencrypt/live/${HOST}/fullchain.pem 35 | SSLCertificateKeyFile /etc/letsencrypt/live/${HOST}/privkey.pem 36 | 37 | 38 | 39 | # vim: syntax=apache ts=4 sw=4 sts=4 sr noet 40 | 41 | 42 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Dockerized Let's Encrypt Proxy 2 | 3 | This is fully automated dockerized proxy that let's you add HTTPS termination with minimal config. 4 | It uses Let's Encrypt for valid certificates and automation. It handles certification issuance as well as renewal. 5 | It has minimal downtime every 2 months, when the Apache proxy is restarted to use the new certificate. 6 | 7 | Docker hub link: [https://hub.docker.com/r/sashee/letsencrypt-proxy-docker/](https://hub.docker.com/r/sashee/letsencrypt-proxy-docker/) 8 | 9 | ## Usage 10 | 11 | The image needs just a few configurations: 12 | 13 | * Expose ports 80 and 443 14 | * Add a network bridge to your service and call it _proxied_ 15 | * Set the hostname for the certificate 16 | * Set the port your app is using 17 | * Test it and then set production mode 18 | 19 | An example config: 20 | 21 | ``` 22 | version: '2' 23 | services: 24 | proxy: 25 | image: sashee/letsencrypt-proxy-docker 26 | ports: 27 | - "80:80" 28 | - "443:443" 29 | depends_on: 30 | - angular 31 | networks: 32 | - proxy 33 | environment: 34 | # Set your host 35 | #- HOST= 36 | - PORT=80 37 | # Set your email 38 | #- EMAIL= 39 | # Turn on production mode 40 | #- MODE=PRODUCTION 41 | links: 42 | - angular:proxied 43 | angular: 44 | image: thanhson1085/angular-admin-seed 45 | networks: 46 | - proxy 47 | networks: 48 | proxy: 49 | ``` 50 | 51 | Change the `angular` part to your app, and update the `link` above. 52 | 53 | ## Production mode 54 | 55 | Let's Encrypt limits the number of certificates issued for a given host every 7 days. 56 | You should test your setup without setting the MODE, and if everything is ok, only then set it to PRODUCTION. 57 | If you test with live certificates, then you can easily find yourself limited and then you have to wait a week to continue. 58 | 59 | ## Domain name 60 | 61 | If you don't have a domain name, you can use [nip.io](http://nip.io) to test it out. 62 | 63 | Please note that AWS domains are blacklisted and will not work. 64 | --------------------------------------------------------------------------------