Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
96 commits
Select commit Hold shift + click to select a range
d77ba8c
Customizations
staticfloat Jan 1, 2017
10f222b
Just mess it all up
staticfloat Jan 2, 2017
afd4b57
What was this `--renew-by-default` nonsense? :P
staticfloat Jan 2, 2017
9fca4ca
Slight wording change
staticfloat Jan 2, 2017
a5e9215
Version 0.5: Less features makes for better software
staticfloat Jan 20, 2017
e8f4c77
More better error handling!
staticfloat Jan 20, 2017
9f4becc
Big rewrite so that we can enable sites as we get HTTPS certs
staticfloat Jan 23, 2017
90e3be4
Yet another rename
staticfloat Jan 23, 2017
07ad674
Multitudinous fixes
staticfloat Jan 25, 2017
2520445
Cleanup fixes
staticfloat Jan 25, 2017
41f6416
Let's wait for the NGINX pid only, so we don't wait on cron
staticfloat Jan 30, 2017
0a23913
Cleanup `Dockerfile` a bit
staticfloat Apr 29, 2017
3d3a0be
Add startup script support
staticfloat Jun 20, 2017
bd46b36
Better scripting support
staticfloat Jul 24, 2017
844d521
Get rid of useless `crontab` command
staticfloat May 2, 2018
b8b50ae
Ditch `cron` for `bash`
staticfloat May 2, 2018
87258f9
Add usage example to `README.md`
staticfloat May 2, 2018
43a2b72
add staging url for develop
Jun 27, 2018
91af6ea
update datetime
Jun 27, 2018
cf136e2
stop to reacreate keys on restart
valdergallo Jun 28, 2018
b5b887d
add old manteiner
valdergallo Jun 28, 2018
418560a
fix util sh
valdergallo Jun 28, 2018
d9ba362
add register script bash
valdergallo Jun 28, 2018
b120666
missing recreate the file for the next week
valdergallo Jun 28, 2018
87730d6
sleep for more 10 sec
Jun 28, 2018
ce79bf4
add support to subdomains
rodrigobraga Aug 8, 2018
41e0d3e
update version
rodrigobraga Aug 8, 2018
a1355e5
isolates parameter inside quotes
rodrigobraga Aug 8, 2018
ee1ca1f
fix scape
rodrigobraga Aug 9, 2018
6fa5b2b
Merge pull request #2 from rodrigobraga/master
staticfloat Aug 9, 2018
c155cde
Do not try to get certificate for wildcard domains as this is no long…
gkosciolek Aug 17, 2018
27ecefe
Fix the loop to make it sh compatible
gkosciolek Aug 17, 2018
467db4f
Merge pull request #3 from gkosciolek/master
staticfloat Aug 22, 2018
06e08af
set certbot as default server
Sep 13, 2018
c282f63
Merge pull request #4 from agairing/master
staticfloat Sep 13, 2018
f9ac240
moved all source files to src folder
BrunoZell Sep 20, 2018
80b1ba3
added baisc usage example
BrunoZell Sep 20, 2018
7a0360b
Merge pull request #5 from BrunoZell/master
staticfloat Sep 21, 2018
5aa7438
create src folder
BrunoZell Sep 28, 2018
fc1b972
merge valdergallo PR with master
BrunoZell Sep 28, 2018
00d0b9b
remove register.sh
BrunoZell Sep 28, 2018
f7668d4
call certbot only once
BrunoZell Sep 28, 2018
1aa799b
add maintainer
BrunoZell Sep 28, 2018
96897f8
move interval management to a util funcion
BrunoZell Sep 28, 2018
7385175
renaming
BrunoZell Sep 28, 2018
16e052d
comments and documentation
BrunoZell Sep 28, 2018
a89ebd1
fix function return
BrunoZell Sep 28, 2018
57c4290
move more renewal logic to util.sh
BrunoZell Oct 3, 2018
66585d9
put conditional renewal logic into certbot loop
BrunoZell Oct 3, 2018
a1104ff
comments
BrunoZell Oct 3, 2018
642614c
use domains private key file as timestamp
BrunoZell Oct 3, 2018
af4a499
Merge pull request #6 from BrunoZell/master
staticfloat Oct 3, 2018
479a108
Added IPv6 Support for the docker container
Feb 11, 2019
4bdc75a
Merge pull request #8 from greendeath/master
staticfloat Mar 30, 2019
507eac1
Update screen to use bash shell and adapt parse_keyfile output to rem…
rachedhedia May 11, 2019
caae172
allow user configs without custom image
ds17f May 17, 2019
67821fc
move link functionality into utils as a sh function
ds17f May 25, 2019
6031035
Update screen to use bash shell and adapt parse_keyfile output to… (#10)
staticfloat Jul 18, 2019
d49c7c5
address PR request comments for minor cleanup
ds17f Oct 3, 2019
e9fb0cf
Update to acme v2
chaopeng Oct 11, 2019
892cc2b
Merge pull request #13 from chaopeng/master
staticfloat Nov 19, 2019
4cedfe2
Merge pull request #12 from ds17f/easy-user-config
staticfloat Nov 19, 2019
7322e57
Update to acme v2
chaopeng Oct 11, 2019
162d240
Merge pull request #15 from yanokwa/opendatakit
staticfloat Dec 27, 2019
b176fa8
Avoid extracting comments when parsing domain names
ollien Dec 30, 2019
386d731
Merge pull request #16 from ollien/fix-comments
staticfloat Jan 9, 2020
f6d02a7
Enable templating! Eliminate unnecessary customization!
staticfloat Jan 13, 2020
452e600
Stop container if nginx stops
lispmachine Jan 29, 2020
d89eae2
indentation fix
lispmachine Feb 2, 2020
59e451c
Merge pull request #17 from lispmachine/wait-fix
staticfloat Feb 5, 2020
e39e783
Update docker-compose.yml
whatsmycoin Feb 25, 2020
e852dc6
Merge pull request #19 from whatsmycoin/patch-1
staticfloat Feb 25, 2020
4486e47
Protect against wedged `nginx` startups
staticfloat Feb 25, 2020
2de007b
(minor) precision regarding ENVSUBST_VARS
rigelk Mar 3, 2020
4fa9745
Use `ps | grep` instead of `jobs | grep`
staticfloat Mar 24, 2020
e662701
Exclude self
staticfloat Mar 24, 2020
dd581b5
Merge pull request #20 from rigelk/patch-1
staticfloat Mar 26, 2020
5fcae39
Print out user configs as we template them
staticfloat Apr 2, 2020
cccdb0a
Update README to indicate port 80 caeveat.
ollien Jun 5, 2020
1f46f18
Merge pull request #22 from ollien/patch-1
staticfloat Jun 29, 2020
1fc51c1
Switched to Python 3.7
lnobach Jun 30, 2020
238b69f
Merge pull request #23 from lnobach/master
staticfloat Jul 1, 2020
2504114
Tag v1.1
staticfloat Jul 1, 2020
e299a89
added extra domains supported.
juehai Aug 21, 2020
e4379b2
Merge pull request #27 from juehai/master
staticfloat Oct 1, 2020
66dab3c
Allow expanding certs via extra_domains_conf
jippi Oct 26, 2020
a2e95f4
Correct volume path for extra domains
earthlingdavey Dec 30, 2020
f862f37
Merge pull request #39 from EarthlingDavey/master
staticfloat Jan 3, 2021
6696466
Merge pull request #35 from jippi/patch-1
staticfloat Jan 3, 2021
4379026
Update README.md
armanjtehrani Jan 11, 2021
9e8482c
Update parse_domains parsing
jippi Feb 15, 2021
67cee92
"And a `.conf` in that directory" is misleading
ledlamp Feb 24, 2021
9d994ef
Merge pull request #43 from ledlamp/patch-1
staticfloat Mar 12, 2021
017bdb6
Merge pull request #40 from jooof/master
staticfloat Mar 12, 2021
7aa8873
Merge pull request #41 from jippi/patch-1
staticfloat Mar 12, 2021
5d2eef6
Update README.md
staticfloat Mar 12, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 0 additions & 21 deletions Dockerfile

This file was deleted.

1 change: 1 addition & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
MIT License

Copyright (c) 2016 Henri Dwyer
Copyright (c) 2017 Elliot Saba

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
148 changes: 89 additions & 59 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,90 +1,120 @@
# docker-letsencrypt-cron
Create and automatically renew website SSL certificates using the letsencrypt free certificate authority, and its client *certbot*.
# NOTE: This repository is now in maintenance-only mode

This image will renew your certificates every 2 months, and place the lastest ones in the /certs folder in the container, and in the ./certs folder on the host.
There is a [spiritual successor maintained by Jonas Alfredsson](https://github.com/JonasAlfredsson/docker-nginx-certbot/) that has some nice new features and is much more actively maintained.
I highly suggest all users migrate their docker configs to use that docker image, as it is strictly superior to this one while still maintaning the same ease of use.

# Usage

## Setup
# docker-nginx-certbot
Create and automatically renew website SSL certificates using the free [letsencrypt](https://letsencrypt.org/) certificate authority, and its client [*certbot*](https://certbot.eff.org/), built on top of the [nginx](https://www.nginx.com/) webserver.

In docker-compose.yml, change the environment variables:
- WEBROOT: set this variable to the webroot path if you want to use the webroot plugin. Leave to use the standalone webserver.
- DOMAINS: a space separated list of domains for which you want to generate certificates.
- EMAIL: where you will receive updates from letsencrypt.
- CONCAT: true or false, whether you want to concatenate the certificate's full chain with the private key (required for e.g. haproxy), or keep the two files separate (required for e.g. nginx or apache).
- SEPARATE: true or false, whether you want one certificate per domain or one certificate valid for all domains.
This repository was originally forked from `@henridwyer`, many thanks to him for the good idea. It has since been completely rewritten, and bears almost no resemblance to the original. This repository is _much_ more opinionated about the structure of your webservers/containers, however it is easier to use as long as all of your webservers follow the given pattern.

## Running
# Usage

### Using the automated image
Create a config directory for your custom configs:

```shell
docker run --name certbot -v `pwd`/certs:/certs --restart always -e "DOMAINS=domain1.com domain2.com" -e "[email protected]" -e "CONCAT=true" -e "WEBROOT=" henridwyer/docker-letsencrypt-cron
```bash
$ mkdir conf.d
```

### Building the image

The easiest way to build the image yourself is to use the provided docker-compose file.

```shell
docker-compose up -d
And a `*.conf` file in that directory (i.e. `nginx.conf`, but NOT just `.conf`):
```nginx
server {
listen 443 ssl;
server_name server.company.com;
ssl_certificate /etc/letsencrypt/live/server.company.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/server.company.com/privkey.pem;

location / {
...
}
}
```

The first time you start it up, you may want to run the certificate generation script immediately:

```shell
docker exec certbot ash -c "/scripts/run_certbot.sh"
Wrap this all up with a `docker-compose.yml` file:
```yml
version: '3'
services:
frontend:
restart: unless-stopped
image: staticfloat/nginx-certbot
ports:
- 80:80/tcp
- 443:443/tcp
environment:
CERTBOT_EMAIL: [email protected]
volumes:
- ./conf.d:/etc/nginx/user.conf.d:ro
- letsencrypt:/etc/letsencrypt
volumes:
letsencrypt:
```

At 3AM, on the 1st of every odd month, a cron job will start the script, renewing your certificates.

# ACME Validation challenge

To authenticate the certificates, the you need to pass the ACME validation challenge. This requires requests made on port 80 to your.domain.com/.well-known/ to be forwarded to this container.
Launch that docker-compose file, and you're good to go; `certbot` will automatically request an SSL certificate for any `nginx` sites that look for SSL certificates in `/etc/letsencrypt/live`, and will automatically renew them over time.

The recommended way to use this image is to set up your reverse proxy to automatically forward requests for the ACME validation challenges to this container.
Note: using a `server` block that listens on port 80 may cause issues with renewal. This container will already handle forwarding to port 443, so they are unnecessary.

## Haproxy example
## Templating

If you use a haproxy reverse proxy, you can add the following to your configuration file in order to pass the ACME challenge.
You may wish to template your configurations, e.g. passing in a hostname so as to be able to run multiple identical copies of this container; one per website. The docker container will use [`envsubst`](https://www.gnu.org/software/gettext/manual/html_node/envsubst-Invocation.html) to template all mounted user configs with a user-provided list of environment variables. Example:

``` haproxy
frontend http
bind *:80
acl letsencrypt_check path_beg /.well-known
```nginx
# In user.conf.d/nginx_template.conf
server {
listen 443 ssl;
server_name ${FQDN};
ssl_certificate /etc/letsencrypt/live/${FQDN}/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/${FQDN}/privkey.pem;

use_backend certbot if letsencrypt_check
...
}
```

backend certbot
server certbot certbot:80 maxconn 32
```yml
version: '3'
services:
frontend:
restart: unless-stopped
image: staticfloat/nginx-certbot
ports:
- 80:80/tcp
- 443:443/tcp
environment:
CERTBOT_EMAIL: [email protected]
# variable names are space-separated
ENVSUBST_VARS: FQDN
FQDN: server.company.com
volumes:
- ./conf.d:/etc/nginx/user.conf.d:ro
- letsencrypt:/etc/letsencrypt
volumes:
letsencrypt:
```

## Nginx example
# Changelog

If you use nginx as a reverse proxy, you can add the following to your configuration file in order to pass the ACME challenge.
### 1.2
- Officially putting this repository into maintenance-only mode.

``` nginx
upstream certbot_upstream{
server certbot:80;
}
### 1.1
- Upgraded to Python 3 installed within the environment, various quality of life improvements around initial setup and renewal.

server {
listen 80;
location '/.well-known/acme-challenge' {
default_type "text/plain";
proxy_pass http://certbot_upstream;
}
}
### 1.0
- Many improvements thanks to contributors from across the globe. Together, we have drastically reduced the amount of customization needed; configs can be mounted directly into a prebuilt image, and the configurations can even be templated.

```
### 0.8
- Ditch cron, it never liked me anway. Just use `sleep` and a `while` loop instead.

# More information
### 0.7
- Complete rewrite, build this image on top of the `nginx` image, and run `cron`/`certbot` alongside `nginx` so that we can have nginx configs dynamically enabled as we get SSL certificates.

Find out more about letsencrypt: https://letsencrypt.org
### 0.6
- Add `nginx_auto_enable.sh` script to `/etc/letsencrypt/` so that users can bring nginx up before SSL certs are actually available.

Certbot github: https://github.com/certbot/certbot
### 0.5
- Change the name to `docker-certbot-cron`, update documentation, strip out even more stuff I don't care about.

# Changelog
### 0.4
- Rip out a bunch of stuff because `@staticfloat` is a monster, and likes to do things his way

### 0.3
- Add support for webroot mode.
Expand Down
1 change: 0 additions & 1 deletion crontab

This file was deleted.

15 changes: 0 additions & 15 deletions docker-compose.yml

This file was deleted.

2 changes: 2 additions & 0 deletions example/certbot_extra_domains/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
1. put your letsencript primary key domain name as the filename.
2. list extra domain names each line in the file.
3 changes: 3 additions & 0 deletions example/certbot_extra_domains/example.com
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
www.example.com
sub1.example.com
sub2.example.com
9 changes: 9 additions & 0 deletions example/conf.d/nginx.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
server {
listen 443 ssl;
server_name yourhostname.com;
ssl_certificate /etc/letsencrypt/live/yourhostname.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/yourhostname.com/privkey.pem;

return 200 'Let\'s Encrypt certificate successfully installed!';
add_header Content-Type text/plain;
}
15 changes: 15 additions & 0 deletions example/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
version: '3'

services:
proxy:
image: staticfloat/nginx-certbot
restart: always
environment:
CERTBOT_EMAIL: "[email protected]"
ports:
- "80:80"
- "443:443"
volumes:
- ./conf.d:/etc/nginx/user.conf.d:ro
- ./certbot_extra_domains:/etc/certbot/extra_domains:ro

59 changes: 0 additions & 59 deletions scripts/run_certbot.sh

This file was deleted.

32 changes: 32 additions & 0 deletions src/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
FROM nginx
LABEL maintainer="Elliot Saba <[email protected]>, Valder Gallo <[email protected]>, Bruno Zell <[email protected]>"

VOLUME /etc/letsencrypt
EXPOSE 80
EXPOSE 443

# Do this apt/pip stuff all in one RUN command to avoid creating large
# intermediate layers on non-squashable docker installs
RUN apt update && \
apt install -y python3 python3-dev libffi6 libffi-dev libssl-dev curl build-essential procps && \
curl -L 'https://bootstrap.pypa.io/get-pip.py' | python3 && \
pip install -U cffi certbot && \
apt remove --purge -y python3-dev build-essential libffi-dev libssl-dev curl && \
apt-get autoremove -y && \
apt-get clean && \
rm -rf /var/lib/apt/lists/*

# Copy in scripts for certbot
COPY ./scripts/ /scripts
RUN chmod +x /scripts/*.sh

# Add /scripts/startup directory to source more startup scripts
RUN mkdir -p /scripts/startup

# Copy in default nginx configuration (which just forwards ACME requests to
# certbot, or redirects to HTTPS, but has no HTTPS configurations by default).
RUN rm -f /etc/nginx/conf.d/*
COPY nginx_conf.d/ /etc/nginx/conf.d/

ENTRYPOINT []
CMD ["/bin/bash", "/scripts/entrypoint.sh"]
22 changes: 22 additions & 0 deletions src/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@

$(warning $(shell IMAGE_NAME=$(IMAGE_NAME) printenv | grep IMAGE_NAME))
ifndef IMAGE_NAME
#$(warning IMAGE_NAME is not set)
IMAGE_NAME=nginx-certbot
endif

# If we have `--squash` support, then use it!
ifneq ($(shell docker build --help 2>/dev/null | grep squash),)
DOCKER_BUILD = docker build --squash
else
DOCKER_BUILD = docker build
endif

all: build

build: Makefile Dockerfile
$(DOCKER_BUILD) -t $(IMAGE_NAME) .
@echo "Done! Use docker run $(IMAGE_NAME) to run"

push:
docker push $(IMAGE_NAME)
16 changes: 16 additions & 0 deletions src/nginx_conf.d/certbot.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
server {
# Listen on plain old HTTP
listen 80 default_server reuseport;
listen [::]:80 default_server reuseport;

# Pass this particular URL off to certbot, to authenticate HTTPS certificates
location '/.well-known/acme-challenge' {
default_type "text/plain";
proxy_pass http://localhost:1337;
}

# Everything else gets shunted over to HTTPS
location / {
return 301 https://$http_host$request_uri;
}
}
Loading