├── .hgignore ├── .dockerignore ├── bin ├── renew.sh ├── expand-certbot-ini.sh ├── certonly.sh ├── reload.sh └── update-crt-list.sh ├── conf ├── 60-backend-main.cfg ├── 50-backend-acme.cfg ├── 65-backend-odoo.cfg ├── 70-frontend-plain.cfg ├── 40-defaults.cfg ├── 80-frontend-encrypted.cfg └── 30-global.cfg ├── hooks └── build ├── cli.ini ├── prepare-entrypoint.sh ├── docker-compose.yaml ├── Dockerfile ├── README.md ├── LICENSE.txt └── certbot.txt /.hgignore: -------------------------------------------------------------------------------- 1 | syntax: glob 2 | *.pem 3 | *.key 4 | -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | .hg* 2 | LICENSE.txt 3 | README.md 4 | -------------------------------------------------------------------------------- /bin/renew.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | echo Asking for certificate renewal 4 | $RENEW 5 | -------------------------------------------------------------------------------- /conf/60-backend-main.cfg: -------------------------------------------------------------------------------- 1 | backend main 2 | # Redirect all traffic to the linked container 3 | server linked www:$PORT 4 | -------------------------------------------------------------------------------- /bin/expand-certbot-ini.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | echo Generating /etc/letsencrypt/cli.ini 4 | envsubst < /usr/src/cli.ini > /etc/letsencrypt/cli.ini 5 | -------------------------------------------------------------------------------- /conf/50-backend-acme.cfg: -------------------------------------------------------------------------------- 1 | backend certbot_standalone 2 | mode http 3 | 4 | # Redirect all traffic to the acme service 5 | server acme-client localhost:90 6 | -------------------------------------------------------------------------------- /hooks/build: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -ex 3 | 4 | docker build \ 5 | --build-arg VCS_REF="$GIT_SHA1" \ 6 | --build-arg BUILD_DATE="$(date --rfc-3339 ns)" \ 7 | --tag "$IMAGE_NAME" . 8 | -------------------------------------------------------------------------------- /bin/certonly.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | # This runs only the first time, as a standalone server 4 | echo Asking for certificates for the first time 5 | $CERTONLY || $CONTINUE_ON_CERTONLY_FAILURE 6 | -------------------------------------------------------------------------------- /cli.ini: -------------------------------------------------------------------------------- 1 | email = $EMAIL 2 | domains = $DOMAINS 3 | $STAGING_FLAG 4 | rsa-key-size = $RSA_KEY_SIZE 5 | post-hook = update-crt-list.sh 6 | agree-tos = true 7 | authenticator = standalone 8 | preferred-challenges = http-01 9 | http-01-port = 90 10 | keep = true 11 | -------------------------------------------------------------------------------- /prepare-entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | if [ "$STAGING" == true ]; then 4 | export STAGING_FLAG="staging = true" 5 | fi 6 | expand-certbot-ini.sh 7 | certonly.sh 8 | update-crt-list.sh 9 | echo Activating cron daemon 10 | crond 11 | echo Executing: $@ 12 | exec /docker-entrypoint.sh "$@" 13 | -------------------------------------------------------------------------------- /conf/65-backend-odoo.cfg: -------------------------------------------------------------------------------- 1 | backend odoo 2 | # Required acls 3 | acl longpolling_path path_dir /longpolling 4 | 5 | # Redirections for /longpolling path 6 | server longpolling www:$ODOO_LONGPOLLING_PORT weight 0 7 | use-server longpolling if longpolling_path 8 | 9 | # Default to normal Odoo port 10 | server default www:$PORT 11 | -------------------------------------------------------------------------------- /bin/reload.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | echo Reloading HAProxy 3 | set -x 4 | # SEE http://cbonte.github.io/haproxy-dconv/1.7/configuration.html#4.2-load-server-state-from-file 5 | echo show servers state | socat /var/lib/haproxy/stats - > /var/lib/haproxy/server-state 6 | # SEE https://github.com/docker-library/docs/tree/master/haproxy#reloading-config 7 | killall -s HUP haproxy-systemd-wrapper || true 8 | -------------------------------------------------------------------------------- /conf/70-frontend-plain.cfg: -------------------------------------------------------------------------------- 1 | frontend plain 2 | bind :80 3 | 4 | # Required variables from the request 5 | http-request set-var(req.path) path 6 | 7 | # Required ACLs 8 | acl acme_url var(req.path) -m beg /.well-known/acme-challenge/ 9 | 10 | # 6 months HSTS header 11 | rspadd "Strict-Transport-Security: max-age=15768000" unless acme_url 12 | 13 | # Normal requests should get secured 14 | redirect scheme https code 301 if !acme_url 15 | 16 | # Redirect ACME requests to certbot 17 | default_backend certbot_standalone 18 | -------------------------------------------------------------------------------- /bin/update-crt-list.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | changed=no 4 | list= 5 | txt=/etc/letsencrypt/crt-list.txt 6 | echo Updating $txt 7 | 8 | touch $txt 9 | mkdir -p /etc/letsencrypt/live 10 | cd /etc/letsencrypt/live 11 | for domain in "$(ls)"; do 12 | cd "$domain" 13 | if [ -f fullchain.pem -a -f privkey.pem ]; then 14 | # Check if something has changed 15 | old= 16 | [ -f combined.pem ] && old="$(cat combined.pem)" 17 | current="$(cat fullchain.pem privkey.pem)" 18 | if [ "$old" != "$current" ]; then 19 | # Store new combined cert 20 | echo "$current" > combined.pem 21 | changed=yes 22 | fi 23 | list="$list$(pwd)/combined.pem\n" 24 | fi 25 | cd .. 26 | done 27 | 28 | # Check if domains list or any cert has changed 29 | if [ "$list" != "$(cat $txt)" -o $changed == yes ]; then 30 | # Update list and reload server 31 | echo -e "$list" > $txt 32 | reload.sh 33 | fi 34 | -------------------------------------------------------------------------------- /docker-compose.yaml: -------------------------------------------------------------------------------- 1 | version: "2" 2 | services: 3 | https: 4 | # XXX Use image: tecnativa/haproxy-letsencrypt instead 5 | build: . 6 | environment: 7 | # XXX: Fill this with your real data 8 | DOMAINS: example.com,example.org 9 | EMAIL: admin@example.com 10 | # XXX: Use "false" to get real certs! 11 | STAGING: "true" 12 | # XXX: Use "true" when cert fetching should fail (i.e. in dev env) 13 | CONTINUE_ON_CERTONLY_FAILURE: "false" 14 | links: 15 | - www 16 | ports: 17 | # It's important to have real ports handled by this container 18 | - "80:80" 19 | - "443:443" 20 | restart: unless-stopped 21 | volumes: 22 | # This keeps certs and cronstamps across reloads 23 | - letsencrypt:/etc/letsencrypt 24 | - cronstamps:/var/spool/cron/cronstamps 25 | 26 | # XXX: Put your web app here; for testing, this one is very useful 27 | www: 28 | image: stackatoapps/phpinfo 29 | 30 | volumes: 31 | letsencrypt: 32 | cronstamps: 33 | -------------------------------------------------------------------------------- /conf/40-defaults.cfg: -------------------------------------------------------------------------------- 1 | defaults 2 | mode http 3 | log global 4 | option httplog 5 | option dontlognull 6 | option http-server-close 7 | option forwardfor except 127.0.0.0/8 8 | option redispatch 9 | retries 3 10 | timeout http-request 10s 11 | timeout queue 1m 12 | timeout connect 10s 13 | timeout client 10m 14 | timeout server 10m 15 | timeout http-keep-alive 10s 16 | timeout check 10s 17 | maxconn 3000 18 | 19 | # Allow seamless reloads 20 | load-server-state-from-file global 21 | 22 | # Use provided example error pages 23 | errorfile 400 /usr/local/etc/haproxy/errors/400.http 24 | errorfile 403 /usr/local/etc/haproxy/errors/403.http 25 | errorfile 408 /usr/local/etc/haproxy/errors/408.http 26 | errorfile 500 /usr/local/etc/haproxy/errors/500.http 27 | errorfile 502 /usr/local/etc/haproxy/errors/502.http 28 | errorfile 503 /usr/local/etc/haproxy/errors/503.http 29 | errorfile 504 /usr/local/etc/haproxy/errors/504.http 30 | -------------------------------------------------------------------------------- /conf/80-frontend-encrypted.cfg: -------------------------------------------------------------------------------- 1 | frontend encrypted 2 | # BEFORE BIND HOOK 3 | 4 | bind :443 ssl strict-sni crt-list /etc/letsencrypt/crt-list.txt 5 | 6 | # AFTER BIND HOOK 7 | 8 | # Required ACLs 9 | acl www_prefix hdr_beg(host) -i www. 10 | acl www_remove env(WWW_PREFIX) -m str REMOVE 11 | acl www_force env(WWW_PREFIX) -m str FORCE 12 | acl odoo_mode env(MODE) -m str ODOO 13 | 14 | # Standard headers to inform app about inverse proxy status 15 | http-request set-header X-SSL %[ssl_fc] 16 | http-request set-header X-SSL-Session_ID %[ssl_fc_session_id,hex] 17 | http-request set-header X-SSL-Client-Verify %[ssl_c_verify] 18 | http-request set-header X-SSL-Client-DN %{+Q}[ssl_c_s_dn] 19 | http-request set-header X-SSL-Client-CN %{+Q}[ssl_c_s_dn(cn)] 20 | http-request set-header X-SSL-Issuer %{+Q}[ssl_c_i_dn] 21 | http-request set-header X-SSL-Client-NotBefore %{+Q}[ssl_c_notbefore] 22 | http-request set-header X-SSL-Client-NotAfter %{+Q}[ssl_c_notafter] 23 | http-request set-header X-Forwarded-Proto https 24 | http-request set-header X-Forwarded-Host %[req.hdr(host)] 25 | http-request set-header X-Forwarded-Port %[dst_port] 26 | http-request set-header X-Forwarded-For %[src] 27 | http-request set-header X-Real-IP %[src] 28 | 29 | # 6 months HSTS header 30 | rspadd "Strict-Transport-Security: max-age=15768000" 31 | 32 | # Redirect www.example.com to example.com 33 | redirect prefix https://%[hdr(host),regsub(www\.,,i)] if www_prefix www_remove 34 | 35 | # Redirect example.com to www.example.com 36 | redirect prefix https://www.%[hdr(host)] if !www_prefix www_force 37 | 38 | # AFTER WWW HOOK 39 | 40 | # Use Odoo backend if chosen 41 | use_backend odoo if odoo_mode 42 | 43 | # Forward to the main linked container by default 44 | default_backend main 45 | -------------------------------------------------------------------------------- /conf/30-global.cfg: -------------------------------------------------------------------------------- 1 | global 2 | log /dev/log local0 3 | 4 | chroot /var/lib/haproxy 5 | pidfile /run/haproxy.pid 6 | maxconn 4000 7 | 8 | # Turn on stats unix socket 9 | stats socket /var/lib/haproxy/stats 10 | server-state-file /var/lib/haproxy/server-state 11 | 12 | # Mozilla security tips for intermediate level 13 | # https://mozilla.github.io/server-side-tls/ssl-config-generator/ 14 | tune.ssl.default-dh-param 2048 15 | 16 | ssl-default-bind-options no-sslv3 no-tls-tickets 17 | ssl-default-bind-ciphers ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA:!DSS 18 | 19 | ssl-default-server-options no-sslv3 no-tls-tickets 20 | ssl-default-server-ciphers ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA:!DSS 21 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM haproxy:1.7-alpine 2 | MAINTAINER Tecnativa 3 | 4 | ENTRYPOINT ["/prepare-entrypoint.sh"] 5 | CMD haproxy -- /etc/haproxy/*.cfg 6 | EXPOSE 80 443 7 | 8 | # The port listening in `www` container 9 | ENV PORT=80 \ 10 | MODE=NORMAL \ 11 | # Odoo mode special variables 12 | ODOO_LONGPOLLING_PORT=8072 \ 13 | # Use `FORCE` or `REMOVE` 14 | WWW_PREFIX=REMOVE \ 15 | # Use `false` to ask for real certs 16 | STAGING=true \ 17 | # Use `true` to continue on cert fetch failure 18 | CONTINUE_ON_CERTONLY_FAILURE=false \ 19 | # Fill your data here 20 | EMAIL=example@example.com \ 21 | DOMAINS=example.com,example.org \ 22 | RSA_KEY_SIZE=4096 \ 23 | # Command to fetch certs at container boot 24 | CERTONLY="certbot certonly --http-01-port 80" \ 25 | # Command to monthly renew certs 26 | RENEW="certbot certonly" 27 | 28 | # Certbot (officially supported Let's Encrypt client) 29 | # SEE https://github.com/certbot/certbot/pull/4032 30 | COPY cli.ini certbot.txt /usr/src/ 31 | RUN apk add --no-cache --virtual .certbot-deps \ 32 | py2-pip \ 33 | dialog \ 34 | augeas-libs \ 35 | libffi \ 36 | libssl1.0 \ 37 | wget \ 38 | ca-certificates \ 39 | binutils 40 | RUN apk add --no-cache --virtual .build-deps \ 41 | python-dev \ 42 | gcc \ 43 | linux-headers \ 44 | openssl-dev \ 45 | musl-dev \ 46 | libffi-dev \ 47 | && pip install --no-cache-dir --require-hashes -r /usr/src/certbot.txt \ 48 | && apk del .build-deps 49 | 50 | # Cron 51 | RUN apk add --no-cache dcron 52 | RUN ln -s /usr/local/bin/renew.sh /etc/periodic/monthly/renew 53 | 54 | # Utils 55 | RUN apk add --no-cache gettext socat 56 | RUN mkdir -p /var/lib/haproxy && touch /var/lib/haproxy/server-state 57 | COPY conf/* /etc/haproxy/ 58 | COPY prepare-entrypoint.sh / 59 | COPY bin/* /usr/local/bin/ 60 | 61 | VOLUME /var/spool/cron/cronstamps /etc/letsencrypt 62 | 63 | # Metadata 64 | ARG VCS_REF 65 | ARG BUILD_DATE 66 | LABEL org.label-schema.schema-version="1.0" \ 67 | org.label-schema.vendor=Tecnativa \ 68 | org.label-schema.build-date="$BUILD_DATE" \ 69 | org.label-schema.vcs-ref="$VCS_REF" \ 70 | org.label-schema.vcs-url="https://github.com/Tecnativa/docker-haproxy-letsencrypt" 71 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # HTTPS Proxy 2 | 3 | [![](https://images.microbadger.com/badges/image/tecnativa/haproxy-letsencrypt.svg)](https://microbadger.com/images/tecnativa/haproxy-letsencrypt "Get your own image badge on microbadger.com") 4 | [![](https://images.microbadger.com/badges/version/tecnativa/haproxy-letsencrypt.svg)](https://microbadger.com/images/tecnativa/haproxy-letsencrypt "Get your own version badge on microbadger.com") 5 | [![](https://images.microbadger.com/badges/commit/tecnativa/haproxy-letsencrypt:latest.svg)](https://microbadger.com/images/tecnativa/haproxy-letsencrypt:latest "Get your own commit badge on microbadger.com") 6 | 7 | Use [HAProxy][] to create a HTTPS proxy with for [Let's Encrypt][]. 8 | 9 | To understand settings in configuration files, see 10 | [online manual](https://cbonte.github.io/haproxy-dconv/). 11 | 12 | ## Disclaimer about load balancing 13 | 14 | This container uses HAProxy, but **it does not perform load balancing**. 15 | It's just for adding an HTTPS layer to any HTTP container. 16 | 17 | However, feel free to fork or subclass this image to do it, or just use other 18 | container for load balancing and link it to this one to add HTTPS to it. 19 | 20 | ## Disclaimer about certificates storage 21 | 22 | You should store the `/etc/letsencrypt` volume contents somewhere persistent 23 | and safe. It contains certificates and private keys, and those things **are 24 | important**. 25 | 26 | ## How does it work? 27 | 28 | It is based on the 29 | [officially-supported HAProxy Alpine image](https://hub.docker.com/_/haproxy/) 30 | with a 31 | [hash-pinned](https://github.com/Tecnativa/docker-haproxy-letsencrypt/blob/master/certbot.txt) 32 | install of the official ACME client supported by Let's Encrypt and the EFF: 33 | [Certbot][], so it tries to stick to official recommendations as close as 34 | possible. 35 | 36 | Before booting HAProxy, it uses the provided configuration to get any missing 37 | certificates from Let's Encrypt directly using 38 | [Certbot's standalone `http-01`](https://certbot.eff.org/docs/using.html#standalone) 39 | challenge implementation, directly on port 80. 40 | 41 | After that, it combines the certificate chain with the private key to satisfy 42 | [HAProxy's requirements](http://cbonte.github.io/haproxy-dconv/1.7/configuration.html#5.1-crt) 43 | and generates a 44 | [`crt-list`](http://cbonte.github.io/haproxy-dconv/1.7/configuration.html#crt-list) 45 | file ready for HAProxy's taste. 46 | 47 | Finally, it will boot up the server using with configuration from 48 | `/etc/haproxy/*.cfg`. 49 | 50 | ## Skip the boring parts 51 | 52 | If you understand the [Docker Compose file][], then all you need to do is to 53 | open [`docker-compose.yaml`][], follow any instructions labeled with `XXX`, and 54 | adapt that structure to your project. 55 | 56 | ## Usage and boring stuff 57 | 58 | Just link it to any container listening on port 80 59 | (let's call it LC for Linked Container): 60 | 61 | docker run -d -p 80:80 -p 443:443 --link LC:www tecnativa/haproxy-letsencrypt 62 | 63 | Then navigate to `https://localhost` and add security exception. 64 | 65 | ### When the LC exposes other port 66 | 67 | The proxy will use `www:$PORT` as origin, so run it as: 68 | 69 | docker run -e PORT=8080 --link LC:www yajo/https-proxy 70 | 71 | ### When you want custom error pages 72 | 73 | This is preconfigured to use error pages from the examples. Just override the 74 | corresponding error page found in `/usr/local/etc/haproxy/errors` in your 75 | subimage: 76 | 77 | FROM yajo/https-proxy 78 | MAINTAINER you@example.com 79 | ADD 400.http 503.http /usr/local/etc/haproxy/errors/ 80 | 81 | ### Automatic redirection of HTTP 82 | 83 | This image will redirect all HTTP traffic to HTTPS, but this is a job that 84 | **should** be handled by your LC in production to avoid this little overhead. 85 | 86 | To help your LC know it is proxied (because it will seem to the LC like 87 | requests come in HTTP form), all requests will have common additional headers 88 | like `X-Forwarded-Proto: https` and 89 | [other common ones](https://github.com/Tecnativa/docker-haproxy-letsencrypt/blob/master/conf/60-backend-main.cfg). 90 | 91 | You can use that to make HTTPS (`https://example.com/other-page`) 92 | redirections, or just use relative (`../other-page`) or protocol-agnostic 93 | (`//example.com/other-page`) redirections and it will always work 94 | anywhere (this is a good practice, BTW). 95 | 96 | If you don't want this forced redirection (to maintain both HTTP and HTTPS 97 | versions of your site), just expose port 80 from your LC and port 443 98 | from the proxy. 99 | 100 | ### Automatic redirection of `www.example.com` to `example.com` 101 | 102 | This container reduces redundancy by removing the `www.` prefix to any request. 103 | 104 | You can do it the other way around with `-e WWW_PREFIX=FORCE`, or disable it 105 | with `-e WWW_PREFIX=0`. 106 | 107 | ### Special modes 108 | 109 | You can use the `MODE` environment variable to switch to some special modes by 110 | setting it to any of these values: 111 | 112 | #### `NORMAL` (default) 113 | 114 | It simply adds its magic to redirect all HTTP(S) requests to the backend, as 115 | explained above. 116 | 117 | #### `ODOO` 118 | 119 | It redirects all requests for `/longpolling` and its subdirs to 120 | `www:$ODOO_LONGPOLLING_PORT` (`www:8072` by default). 121 | 122 | Normally you combine this mode with `e PORT=8069`, and you must configure 123 | correctly the workers parameter for the Odoo linked container. Check its docs 124 | for that. 125 | 126 | ### Configuring [Certbot][] 127 | 128 | You can override the template in `/usr/src/cli.ini` with the default options 129 | that are going to be used. It gets environment variable-expanded in the 130 | entrypoint. Use any 131 | [configuration](https://certbot.eff.org/docs/using.html#configuration-file) you 132 | want. 133 | 134 | By default you should use these environment variables to make it work: 135 | 136 | #### `STAGING` 137 | 138 | Set it to `false` to start using the real Let's Encrypt CA. By default (`true`) 139 | it uses the 140 | [staging environment](https://letsencrypt.org/docs/staging-environment/). 141 | 142 | #### `EMAIL` 143 | 144 | Set your real email to interact with Let's Encrypt. 145 | 146 | #### `DOMAINS` 147 | 148 | Comma-separated list of domains you are serving with this container (and for 149 | whom you want certificates). 150 | 151 | Remember that if you are going to serve both `www.example.com` and 152 | `example.com`, you have to ask for both. 153 | 154 | #### `RSA_KEY_SIZE` 155 | 156 | By default it is a bit higher than [Certbot][]'s default: `4096`. 157 | 158 | ### Using replacement hooks 159 | 160 | Some configuration files have hooks, such as `# AFTER WWW HOOK`. Those strings 161 | can be used as a replacement target in your subimage `Dockerfile` with `sed -i` 162 | to inject some extra rules in those places. 163 | 164 | ## Feedback 165 | 166 | Please send any feedback (issues, questions) to the [issue tracker][]. 167 | 168 | [HAProxy]: http://www.haproxy.org/ 169 | [Certbot]: https://certbot.eff.org/docs/using.html#renewing-certificates 170 | [Docker Compose file]: https://docs.docker.com/compose/compose-file/ 171 | [`docker-compose.yaml`]: https://github.com/Tecnativa/docker-haproxy-letsencrypt/blob/master/docker-compose.yaml 172 | [Let's Encrypt]: https://letsencrypt.org/ 173 | [issue tracker]: https://github.com/Tecnativa/docker-haproxy-letsencrypt/issues 174 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | APPENDIX: How to apply the Apache License to your work. 180 | 181 | To apply the Apache License to your work, attach the following 182 | boilerplate notice, with the fields enclosed by brackets "[]" 183 | replaced with your own identifying information. (Don't include 184 | the brackets!) The text should be enclosed in the appropriate 185 | comment syntax for the file format. We also recommend that a 186 | file or class name and description of purpose be included on the 187 | same "printed page" as the copyright notice for easier 188 | identification within third-party archives. 189 | 190 | Copyright [yyyy] [name of copyright owner] 191 | 192 | Licensed under the Apache License, Version 2.0 (the "License"); 193 | you may not use this file except in compliance with the License. 194 | You may obtain a copy of the License at 195 | 196 | http://www.apache.org/licenses/LICENSE-2.0 197 | 198 | Unless required by applicable law or agreed to in writing, software 199 | distributed under the License is distributed on an "AS IS" BASIS, 200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 201 | See the License for the specific language governing permissions and 202 | limitations under the License. 203 | -------------------------------------------------------------------------------- /certbot.txt: -------------------------------------------------------------------------------- 1 | # From https://github.com/certbot/certbot/blob/v0.10.0/letsencrypt-auto-source/letsencrypt-auto#L641-L815 2 | 3 | argparse==1.4.0 \ 4 | --hash=sha256:c31647edb69fd3d465a847ea3157d37bed1f95f19760b11a47aa91c04b666314 \ 5 | --hash=sha256:62b089a55be1d8949cd2bc7e0df0bddb9e028faefc8c32038cc84862aefdd6e4 6 | 7 | # This comes before cffi because cffi will otherwise install an unchecked 8 | # version via setup_requires. 9 | pycparser==2.14 \ 10 | --hash=sha256:7959b4a74abdc27b312fed1c21e6caf9309ce0b29ea86b591fd2e99ecdf27f73 \ 11 | --no-binary pycparser 12 | 13 | cffi==1.4.2 \ 14 | --hash=sha256:53c1c9ddb30431513eb7f3cdef0a3e06b0f1252188aaa7744af0f5a4cd45dbaf \ 15 | --hash=sha256:a568f49dfca12a8d9f370187257efc58a38109e1eee714d928561d7a018a64f8 \ 16 | --hash=sha256:809c6ca8cfbcaeebfbd432b4576001b40d38ff2463773cb57577d75e1a020bc3 \ 17 | --hash=sha256:86cdca2cd9cba41422230390df17dfeaa9f344a911e3975c8be9da57b35548e9 \ 18 | --hash=sha256:24b13db84aec385ca23c7b8ded83ef8bb4177bc181d14758f9f975be5d020d86 \ 19 | --hash=sha256:969aeffd7c0e097f6be1efd682c156ae226591a0793a94b6c2d5e4293f4c8d4e \ 20 | --hash=sha256:000f358d4b0fa249feaab9c1ce7d5b2fe7e02e7bdf6806c26418505fc685e268 \ 21 | --hash=sha256:a9d86f460bbd8358a2d513ad779e3f3fc878e3b93a00b5002faebf616ffe6b9c \ 22 | --hash=sha256:3127b3ab33eb23ccac071f9a0802748e5cf7c5cbcd02482bb063e35b41dbb0b0 \ 23 | --hash=sha256:e2b2d42236469a40224d39e7b6c60575f388b2f423f354c7ee90a5b7f58c8065 \ 24 | --hash=sha256:8c2dccafee89b1b424b0bec6ad2dd9622c949d2024e929f5da1ed801eac75f1d \ 25 | --hash=sha256:a4de7a4d11aed488bab4fb14f4988587a829bece5a20433f780d6e33b08083cb \ 26 | --hash=sha256:5ca8fe30425265a49274e4b0213a1bc98f4b13449ae5e96f984771e5d83e58c1 \ 27 | --hash=sha256:a4fd38802f59e714eba81a024f62db710b27dbe27a7ea12e911537327aa84d30 \ 28 | --hash=sha256:86cd6912bbc83e9405d4a73cd7f4b4ee8353652d2dbc7c820106ed5b4d1bab3a \ 29 | --hash=sha256:8f1d177d364ea35900415ae24ca3e471be3d5334ed0419294068c49f45913998 30 | ConfigArgParse==0.10.0 \ 31 | --hash=sha256:3b50a83dd58149dfcee98cb6565265d10b53e9c0a2bca7eeef7fb5f5524890a7 32 | configobj==5.0.6 \ 33 | --hash=sha256:a2f5650770e1c87fb335af19a9b7eb73fc05ccf22144eb68db7d00cd2bcb0902 34 | cryptography==1.5.3 \ 35 | --hash=sha256:e514d92086246b53ae9b048df652cf3036b462e50a6ce9fac6b6253502679991 \ 36 | --hash=sha256:10ee414f4b5af403a0d8f20dfa80f7dad1fc7ae5452ec5af03712d5b6e78c664 \ 37 | --hash=sha256:7234456d1f4345a144ed07af2416c7c0659d4bb599dd1a963103dc8c183b370e \ 38 | --hash=sha256:d3b9587406f94642bd70b3d666b813f446e95f84220c9e416ad94cbfb6be2eaa \ 39 | --hash=sha256:b15fc6b59f1474eef62207c85888afada8acc47fae8198ba2b0197d54538961a \ 40 | --hash=sha256:3b62d65d342704fc07ed171598db2a2775bdf587b1b6abd2cba2261bfe3ccde3 \ 41 | --hash=sha256:059343022ec904c867a13bc55d2573e36c8cfb2c250e30d8a2e9825f253b07ba \ 42 | --hash=sha256:c7897cf13bc8b4ee0215d83cbd51766d87c06b277fcca1f9108595508e5bcfb4 \ 43 | --hash=sha256:9b69e983e5bf83039ddd52e52a28c7faedb2b22bdfb5876377b95aac7d3be63e \ 44 | --hash=sha256:61e40905c426d02b3fae38088dc66ce4ef84830f7eb223dec6b3ac3ccdc676fb \ 45 | --hash=sha256:00783a32bcd91a12177230d35bfcf70a2333ade4a6b607fac94a633a7971c671 \ 46 | --hash=sha256:d11973f49b648cde1ea1a30e496d7557dbfeccd08b3cd9ba58d286a9c274ff8e \ 47 | --hash=sha256:f24bedf28b81932ba6063aec9a826669f5237ea3b755efe04d98b072faa053a5 \ 48 | --hash=sha256:3ab5725367239e3deb9b92e917aa965af3fef008f25b96a3000821869e208181 \ 49 | --hash=sha256:8a53209de822e22b5f73bf4b99e68ac4ccc91051fd6751c8252982983e86a77d \ 50 | --hash=sha256:5a07439d4b1e4197ac202b7eea45e26a6fd65757652dc50f1a63367f711df933 \ 51 | --hash=sha256:26b1c4b40aec7b0074bceabe6e06565aa28176eca7323a31df66ebf89fe916d3 \ 52 | --hash=sha256:eaa4a7b5a6682adcf8d6ebb2a08a008802657643655bb527c95c8a3860253d8e \ 53 | --hash=sha256:8156927dcf8da274ff205ad0612f75c380df45385bacf98531a5b3348c88d135 \ 54 | --hash=sha256:61ec0d792749d0e91e84b1d58b6dfd204806b10b5811f846c2ceca0de028c53a \ 55 | --hash=sha256:26330c88041569ca621cc42274d0ea2667a48b6deab41467272c3aba0b6e8f07 \ 56 | --hash=sha256:cf82ddac919b587f5e44247579b433224cc2e03332d2ea4d89aa70d7e6b64ae5 57 | enum34==1.1.2 \ 58 | --hash=sha256:2475d7fcddf5951e92ff546972758802de5260bf409319a9f1934e6bbc8b1dc7 \ 59 | --hash=sha256:35907defb0f992b75ab7788f65fedc1cf20ffa22688e0e6f6f12afc06b3ea501 60 | funcsigs==0.4 \ 61 | --hash=sha256:ff5ad9e2f8d9e5d1e8bbfbcf47722ab527cf0d51caeeed9da6d0f40799383fde \ 62 | --hash=sha256:d83ce6df0b0ea6618700fe1db353526391a8a3ada1b7aba52fed7a61da772033 63 | idna==2.0 \ 64 | --hash=sha256:9b2fc50bd3c4ba306b9651b69411ef22026d4d8335b93afc2214cef1246ce707 \ 65 | --hash=sha256:16199aad938b290f5be1057c0e1efc6546229391c23cea61ca940c115f7d3d3b 66 | ipaddress==1.0.16 \ 67 | --hash=sha256:935712800ce4760701d89ad677666cd52691fd2f6f0b340c8b4239a3c17988a5 \ 68 | --hash=sha256:5a3182b322a706525c46282ca6f064d27a02cffbd449f9f47416f1dc96aa71b0 69 | linecache2==1.0.0 \ 70 | --hash=sha256:e78be9c0a0dfcbac712fe04fbf92b96cddae80b1b842f24248214c8496f006ef \ 71 | --hash=sha256:4b26ff4e7110db76eeb6f5a7b64a82623839d595c2038eeda662f2a2db78e97c 72 | ordereddict==1.1 \ 73 | --hash=sha256:1c35b4ac206cef2d24816c89f89cf289dd3d38cf7c449bb3fab7bf6d43f01b1f 74 | parsedatetime==2.1 \ 75 | --hash=sha256:ce9d422165cf6e963905cd5f74f274ebf7cc98c941916169178ef93f0e557838 \ 76 | --hash=sha256:17c578775520c99131634e09cfca5a05ea9e1bd2a05cd06967ebece10df7af2d 77 | pbr==1.8.1 \ 78 | --hash=sha256:46c8db75ae75a056bd1cc07fa21734fe2e603d11a07833ecc1eeb74c35c72e0c \ 79 | --hash=sha256:e2127626a91e6c885db89668976db31020f0af2da728924b56480fc7ccf09649 80 | pyasn1==0.1.9 \ 81 | --hash=sha256:61f9d99e3cef65feb1bfe3a2eef7a93eb93819d345bf54bcd42f4e63d5204dae \ 82 | --hash=sha256:1802a6dd32045e472a419db1441aecab469d33e0d2749e192abdec52101724af \ 83 | --hash=sha256:35025cd9422c96504912f04e2f15fe79390a8597b430c2ca5d0534cf9309ffa0 \ 84 | --hash=sha256:2f96ed5a0c329ca16230b326ca12b7461ec8f65e0be3e4f997516f36bf82a345 \ 85 | --hash=sha256:28fee44217991cfad9e6a0b9f7e3f26041e21ebc96629e94e585ccd05d49fa65 \ 86 | --hash=sha256:326e7a854a17fab07691204747695f8f692d674588a355c441fb14f660bf4e68 \ 87 | --hash=sha256:cda5a90485709ca6795c86056c3e5fe7266028b05e53f1d527fdf93a6365a6b8 \ 88 | --hash=sha256:0cb2a14742b543fdd68f931a14ce3829186ed2b1b2267a06787388c96b2dd9be \ 89 | --hash=sha256:5191ff6b9126d2c039dd87f8ff025bed274baf07fa78afa46f556b1ad7265d6e \ 90 | --hash=sha256:8323e03637b2d072cc7041300bac6ec448c3c28950ab40376036788e9a1af629 \ 91 | --hash=sha256:853cacd96d1f701ddd67aa03ecc05f51890135b7262e922710112f12a2ed2a7f 92 | pyOpenSSL==16.2.0 \ 93 | --hash=sha256:26ca380ddf272f7556e48064bbcd5bd71f83dfc144f3583501c7ddbd9434ee17 \ 94 | --hash=sha256:7779a3bbb74e79db234af6a08775568c6769b5821faecf6e2f4143edb227516e 95 | pyparsing==2.1.8 \ 96 | --hash=sha256:2f0f5ceb14eccd5aef809d6382e87df22ca1da583c79f6db01675ce7d7f49c18 \ 97 | --hash=sha256:03a4869b9f3493807ee1f1cb405e6d576a1a2ca4d81a982677c0c1ad6177c56b \ 98 | --hash=sha256:ab09aee814c0241ff0c503cff30018219fe1fc14501d89f406f4664a0ec9fbcd \ 99 | --hash=sha256:6e9a7f052f8e26bcf749e4033e3115b6dc7e3c85aafcb794b9a88c9d9ef13c97 \ 100 | --hash=sha256:9f463a6bcc4eeb6c08f1ed84439b17818e2085937c0dee0d7674ac127c67c12b \ 101 | --hash=sha256:3626b4d81cfb300dad57f52f2f791caaf7b06c09b368c0aa7b868e53a5775424 \ 102 | --hash=sha256:367b90cc877b46af56d4580cd0ae278062903f02b8204ab631f5a2c0f50adfd0 \ 103 | --hash=sha256:9f1ea360086cd68681e7f4ca8f1f38df47bf81942a0d76a9673c2d23eff35b13 104 | pyRFC3339==1.0 \ 105 | --hash=sha256:eea31835c56e2096af4363a5745a784878a61d043e247d3a6d6a0a32a9741f56 \ 106 | --hash=sha256:8dfbc6c458b8daba1c0f3620a8c78008b323a268b27b7359e92a4ae41325f535 107 | python-augeas==0.5.0 \ 108 | --hash=sha256:67d59d66cdba8d624e0389b87b2a83a176f21f16a87553b50f5703b23f29bac2 109 | pytz==2015.7 \ 110 | --hash=sha256:3abe6a6d3fc2fbbe4c60144211f45da2edbe3182a6f6511af6bbba0598b1f992 \ 111 | --hash=sha256:939ef9c1e1224d980405689a97ffcf7828c56d1517b31d73464356c1f2b7769e \ 112 | --hash=sha256:ead4aefa7007249e05e51b01095719d5a8dd95760089f5730aac5698b1932918 \ 113 | --hash=sha256:3cca0df08bd0ed98432390494ce3ded003f5e661aa460be7a734bffe35983605 \ 114 | --hash=sha256:3ede470d3d17ba3c07638dfa0d10452bc1b6e5ad326127a65ba77e6aaeb11bec \ 115 | --hash=sha256:68c47964f7186eec306b13629627722b9079cd4447ed9e5ecaecd4eac84ca734 \ 116 | --hash=sha256:dd5d3991950aae40a6c81de1578942e73d629808cefc51d12cd157980e6cfc18 \ 117 | --hash=sha256:a77c52062c07eb7c7b30545dbc73e32995b7e117eea750317b5cb5c7a4618f14 \ 118 | --hash=sha256:81af9aec4bc960a9a0127c488f18772dae4634689233f06f65443e7b11ebeb51 \ 119 | --hash=sha256:e079b1dadc5c06246cc1bb6fe1b23a50b1d1173f2edd5104efd40bb73a28f406 \ 120 | --hash=sha256:fbd26746772c24cb93c8b97cbdad5cb9e46c86bbdb1b9d8a743ee00e2fb1fc5d \ 121 | --hash=sha256:99266ef30a37e43932deec2b7ca73e83c8dbc3b9ff703ec73eca6b1dae6befea \ 122 | --hash=sha256:8b6ce1c993909783bc96e0b4f34ea223bff7a4df2c90bdb9c4e0f1ac928689e3 123 | requests==2.12.1 \ 124 | --hash=sha256:3f3f27a9d0f9092935efc78054ef324eb9f8166718270aefe036dfa1e4f68e1e \ 125 | --hash=sha256:2109ecea94df90980be040490ff1d879971b024861539abb00054062388b612e 126 | six==1.10.0 \ 127 | --hash=sha256:0ff78c403d9bccf5a425a6d31a12aa6b47f1c21ca4dc2573a7e2f32a97335eb1 \ 128 | --hash=sha256:105f8d68616f8248e24bf0e9372ef04d3cc10104f1980f54d57b2ce73a5ad56a 129 | traceback2==1.4.0 \ 130 | --hash=sha256:8253cebec4b19094d67cc5ed5af99bf1dba1285292226e98a31929f87a5d6b23 \ 131 | --hash=sha256:05acc67a09980c2ecfedd3423f7ae0104839eccb55fc645773e1caa0951c3030 132 | unittest2==1.1.0 \ 133 | --hash=sha256:13f77d0875db6d9b435e1d4f41e74ad4cc2eb6e1d5c824996092b3430f088bb8 \ 134 | --hash=sha256:22882a0e418c284e1f718a822b3b022944d53d2d908e1690b319a9d3eb2c0579 135 | zope.component==4.2.2 \ 136 | --hash=sha256:282c112b55dd8e3c869a3571f86767c150ab1284a9ace2bdec226c592acaf81a 137 | zope.event==4.1.0 \ 138 | --hash=sha256:dc7a59a2fd91730d3793131a5d261b29e93ec4e2a97f1bc487ce8defee2fe786 139 | zope.interface==4.1.3 \ 140 | --hash=sha256:f07b631f7a601cd8cbd3332d54f43142c7088a83299f859356f08d1d4d4259b3 \ 141 | --hash=sha256:de5cca083b9439d8002fb76bbe6b4998c5a5a721fab25b84298967f002df4c94 \ 142 | --hash=sha256:6788416f7ea7f5b8a97be94825377aa25e8bdc73463e07baaf9858b29e737077 \ 143 | --hash=sha256:6f3230f7254518201e5a3708cbb2de98c848304f06e3ded8bfb39e5825cba2e1 \ 144 | --hash=sha256:5fa575a5240f04200c3088427d0d4b7b737f6e9018818a51d8d0f927a6a2517a \ 145 | --hash=sha256:522194ad6a545735edd75c8a83f48d65d1af064e432a7d320d64f56bafc12e99 \ 146 | --hash=sha256:e8c7b2d40943f71c99148c97f66caa7f5134147f57423f8db5b4825099ce9a09 \ 147 | --hash=sha256:279024f0208601c3caa907c53876e37ad88625f7eaf1cb3842dbe360b2287017 \ 148 | --hash=sha256:2e221a9eec7ccc58889a278ea13dcfed5ef939d80b07819a9a8b3cb1c681484f \ 149 | --hash=sha256:69118965410ec86d44dc6b9017ee3ddbd582e0c0abeef62b3a19dbf6c8ad132b \ 150 | --hash=sha256:d04df8686ec864d0cade8cf199f7f83aecd416109a20834d568f8310ded12dea \ 151 | --hash=sha256:e75a947e15ee97e7e71e02ea302feb2fc62d3a2bb4668bf9dfbed43a506ac7e7 \ 152 | --hash=sha256:4e45d22fb883222a5ab9f282a116fec5ee2e8d1a568ccff6a2d75bbd0eb6bcfc \ 153 | --hash=sha256:bce9339bb3c7a55e0803b63d21c5839e8e479bc85c4adf42ae415b72f94facb2 \ 154 | --hash=sha256:928138365245a0e8869a5999fbcc2a45475a0a6ed52a494d60dbdc540335fedd \ 155 | --hash=sha256:0d841ba1bb840eea0e6489dc5ecafa6125554971f53b5acb87764441e61bceba \ 156 | --hash=sha256:b09c8c1d47b3531c400e0195697f1414a63221de6ef478598a4f1460f7d9a392 157 | mock==1.0.1 \ 158 | --hash=sha256:b839dd2d9c117c701430c149956918a423a9863b48b09c90e30a6013e7d2f44f \ 159 | --hash=sha256:8f83080daa249d036cbccfb8ae5cc6ff007b88d6d937521371afabe7b19badbc 160 | letsencrypt==0.7.0 \ 161 | --hash=sha256:105a5fb107e45bcd0722eb89696986dcf5f08a86a321d6aef25a0c7c63375ade \ 162 | --hash=sha256:c36e532c486a7e92155ee09da54b436a3c420813ec1c590b98f635d924720de9 163 | 164 | # THE LINES BELOW ARE EDITED BY THE RELEASE SCRIPT; ADD ALL DEPENDENCIES ABOVE. 165 | 166 | acme==0.10.0 \ 167 | --hash=sha256:df4299a9881d94185a1578ed97334430a90f761ce815edd300860ca47d0538f1 \ 168 | --hash=sha256:ddebdf1fe139c8fedbcf633955ec867496d2f7d2d2e9879d538437a69ab47876 169 | certbot==0.10.0 \ 170 | --hash=sha256:fb1bfa3d54ce9366758e374f7ed99667ce20484224934d3e8e57839fcf784bc5 \ 171 | --hash=sha256:dd64ed8fb3cc3b053f05e779b934433445918668c49bcdbb2c816062815e1661 172 | certbot-apache==0.10.0 \ 173 | --hash=sha256:909d59c53507093f838f7336f75d7d78563a35b16afdf6c30f45c9f47bf069da \ 174 | --hash=sha256:6f110dae227dd0fea9572fa12dd60b041e391f5d2028cc2e1fedd2a9a0d2bc88 175 | certbot-nginx==0.10.0 \ 176 | --hash=sha256:4f33a230d420cbd0431e7b707fb9a1732bfd18d3c6056019591bd7c3a13abe92 \ 177 | --hash=sha256:c12ffd05207b0be3c765b3d3e2927e0b2cc2b7de20654b19d154a0d789e7c1d5 178 | --------------------------------------------------------------------------------