Merge e95be19950
into f42bf9175d
This commit is contained in:
commit
ef07a415a9
20 changed files with 241 additions and 82 deletions
|
@ -1,6 +1,8 @@
|
||||||
.git
|
.git
|
||||||
.dockerignore
|
.dockerignore
|
||||||
circle.yml
|
circle.yml
|
||||||
|
Dockerfile
|
||||||
|
LICENSE
|
||||||
Makefile
|
Makefile
|
||||||
README.md
|
README.md
|
||||||
test
|
test
|
||||||
|
|
39
Dockerfile
39
Dockerfile
|
@ -1,34 +1,11 @@
|
||||||
FROM nginx:1.9.6
|
FROM jwilder/nginx-proxy
|
||||||
MAINTAINER Jason Wilder mail@jasonwilder.com
|
|
||||||
|
|
||||||
# Install wget and install/updates certificates
|
MAINTAINER David Parrish <daveparrish@tutanota.com>
|
||||||
RUN apt-get update \
|
MAINTAINER Yves Blusseau <90z7oey02@sneakemail.com>
|
||||||
&& apt-get install -y -q --no-install-recommends \
|
MAINTAINER Hadrien Mary <hadrien.mary@gmail.com>
|
||||||
ca-certificates \
|
|
||||||
wget \
|
|
||||||
&& apt-get clean \
|
|
||||||
&& rm -r /var/lib/apt/lists/*
|
|
||||||
|
|
||||||
# Configure Nginx and apply fix for very long server names
|
# Install simp_le program
|
||||||
RUN echo "daemon off;" >> /etc/nginx/nginx.conf \
|
COPY /install_simp_le.sh /app/install_simp_le.sh
|
||||||
&& sed -i 's/^http {/&\n server_names_hash_bucket_size 128;/g' /etc/nginx/nginx.conf
|
RUN chmod +rx /app/install_simp_le.sh && sync && /app/install_simp_le.sh && rm -f /app/install_simp_le.sh
|
||||||
|
|
||||||
# Install Forego
|
COPY letsencrypt_service letsencrypt_service_data.tmpl nginx.tmpl Procfile update_certs update_nginx /app/
|
||||||
RUN wget -P /usr/local/bin https://godist.herokuapp.com/projects/ddollar/forego/releases/current/linux-amd64/forego \
|
|
||||||
&& chmod u+x /usr/local/bin/forego
|
|
||||||
|
|
||||||
ENV DOCKER_GEN_VERSION 0.4.2
|
|
||||||
|
|
||||||
RUN wget https://github.com/jwilder/docker-gen/releases/download/$DOCKER_GEN_VERSION/docker-gen-linux-amd64-$DOCKER_GEN_VERSION.tar.gz \
|
|
||||||
&& tar -C /usr/local/bin -xvzf docker-gen-linux-amd64-$DOCKER_GEN_VERSION.tar.gz \
|
|
||||||
&& rm /docker-gen-linux-amd64-$DOCKER_GEN_VERSION.tar.gz
|
|
||||||
|
|
||||||
COPY . /app/
|
|
||||||
WORKDIR /app/
|
|
||||||
|
|
||||||
ENV DOCKER_HOST unix:///tmp/docker.sock
|
|
||||||
|
|
||||||
VOLUME ["/etc/nginx/certs"]
|
|
||||||
|
|
||||||
ENTRYPOINT ["/app/docker-entrypoint.sh"]
|
|
||||||
CMD ["forego", "start", "-r"]
|
|
||||||
|
|
7
Makefile
7
Makefile
|
@ -7,8 +7,11 @@ update-dependencies:
|
||||||
docker pull python:3
|
docker pull python:3
|
||||||
docker pull rancher/socat-docker:latest
|
docker pull rancher/socat-docker:latest
|
||||||
docker pull appropriate/curl:latest
|
docker pull appropriate/curl:latest
|
||||||
docker pull docker:1.9
|
docker pull docker:1.9.1
|
||||||
|
|
||||||
test:
|
test:
|
||||||
docker build -t jwilder/nginx-proxy:bats .
|
docker build -t dmp1ce/nginx-proxy-letsencrypt:bats .
|
||||||
bats test
|
bats test
|
||||||
|
|
||||||
|
test-clean:
|
||||||
|
./test/cleanup_test_containers.sh
|
||||||
|
|
5
Procfile
5
Procfile
|
@ -1,2 +1,3 @@
|
||||||
nginx: nginx
|
nginx: /usr/sbin/nginx
|
||||||
dockergen: docker-gen -watch -only-exposed -notify "nginx -s reload" /app/nginx.tmpl /etc/nginx/conf.d/default.conf
|
dockergen: /usr/local/bin/docker-gen -watch -only-exposed -notify "/app/update_nginx" /app/nginx.tmpl /etc/nginx/conf.d/default.conf
|
||||||
|
letsencrypt: /app/letsencrypt_service
|
||||||
|
|
60
README.md
60
README.md
|
@ -1,14 +1,18 @@
|
||||||
  [](https://circleci.com/gh/jwilder/nginx-proxy)
|
**Development efforts have moved to the [docker-letsencrypt-nginx-proxy-companion](https://github.com/JrCs/docker-letsencrypt-nginx-proxy-companion) project. docker-letsencrypt-nginx-proxy-companion doesn't require a fork of nginx-proxy in order to register Let's Encrypt certificates.**
|
||||||
|
|
||||||
|
  [](https://circleci.com/gh/dmp1ce/nginx-proxy-letsencrypt) [](https://imagelayers.io/?images=dmp1ce/nginx-proxy-letsencrypt:latest 'Get your own badge on imagelayers.io')
|
||||||
|
|
||||||
nginx-proxy sets up a container running nginx and [docker-gen][1]. docker-gen generates reverse proxy configs for nginx and reloads nginx when containers are started and stopped.
|
nginx-proxy sets up a container running nginx and [docker-gen][1]. docker-gen generates reverse proxy configs for nginx and reloads nginx when containers are started and stopped.
|
||||||
|
|
||||||
See [Automated Nginx Reverse Proxy for Docker][2] for why you might want to use this.
|
See [Automated Nginx Reverse Proxy for Docker][2] for why you might want to use this.
|
||||||
|
|
||||||
|
nginx-proxy-letsencrypt is a fork of nginx-proxy which adds Let's Encrypt support. Let's Encrypt allows multiple virtual hosts to have TLS certificates automatically created and renewed! The reason the jwilder/nginx-proxy was forked is because it seemed unlikely that the specific Let's Encrypt use case world be added to the more generic nginx-proxy project and the Let's Encrypt client does add some storage overhead. See [pull request](https://github.com/jwilder/nginx-proxy/pull/300) for details about fork. See [Let's Encrypt section](#lets-encrypt) for configuration details.
|
||||||
|
|
||||||
### Usage
|
### Usage
|
||||||
|
|
||||||
To run it:
|
To run it:
|
||||||
|
|
||||||
$ docker run -d -p 80:80 -v /var/run/docker.sock:/tmp/docker.sock:ro jwilder/nginx-proxy
|
$ docker run -d -p 80:80 -v /var/run/docker.sock:/tmp/docker.sock:ro dmp1ce/nginx-proxy-letsencrypt
|
||||||
|
|
||||||
Then start any containers you want proxied with an env var `VIRTUAL_HOST=subdomain.youdomain.com`
|
Then start any containers you want proxied with an env var `VIRTUAL_HOST=subdomain.youdomain.com`
|
||||||
|
|
||||||
|
@ -41,7 +45,7 @@ If you would like to connect to your backend using HTTPS instead of HTTP, set `V
|
||||||
|
|
||||||
To set the default host for nginx use the env var `DEFAULT_HOST=foo.bar.com` for example
|
To set the default host for nginx use the env var `DEFAULT_HOST=foo.bar.com` for example
|
||||||
|
|
||||||
$ docker run -d -p 80:80 -e DEFAULT_HOST=foo.bar.com -v /var/run/docker.sock:/tmp/docker.sock:ro jwilder/nginx-proxy
|
$ docker run -d -p 80:80 -e DEFAULT_HOST=foo.bar.com -v /var/run/docker.sock:/tmp/docker.sock:ro dmp1ce/nginx-proxy-letsencrypt
|
||||||
|
|
||||||
|
|
||||||
### Separate Containers
|
### Separate Containers
|
||||||
|
@ -51,7 +55,7 @@ image and the official [nginx](https://registry.hub.docker.com/_/nginx/) image.
|
||||||
|
|
||||||
You may want to do this to prevent having the docker socket bound to a publicly exposed container service.
|
You may want to do this to prevent having the docker socket bound to a publicly exposed container service.
|
||||||
|
|
||||||
To run nginx proxy as a separate container you'll need to have [nginx.tmpl](https://github.com/jwilder/nginx-proxy/blob/master/nginx.tmpl) on your host system.
|
To run nginx proxy as a separate container you'll need to have [nginx.tmpl](https://github.com/dmp1ce/nginx-proxy-letsencrypt/blob/master/nginx.tmpl) on your host system.
|
||||||
|
|
||||||
First start nginx with a volume:
|
First start nginx with a volume:
|
||||||
|
|
||||||
|
@ -78,7 +82,7 @@ certificates or optionally specifying a cert name (for SNI) as an environment va
|
||||||
|
|
||||||
To enable SSL:
|
To enable SSL:
|
||||||
|
|
||||||
$ docker run -d -p 80:80 -p 443:443 -v /path/to/certs:/etc/nginx/certs -v /var/run/docker.sock:/tmp/docker.sock:ro jwilder/nginx-proxy
|
$ docker run -d -p 80:80 -p 443:443 -v /path/to/certs:/etc/nginx/certs -v /var/run/docker.sock:/tmp/docker.sock:ro dmp1ce/nginx-proxy-letsencrypt
|
||||||
|
|
||||||
The contents of `/path/to/certs` should contain the certificates and private keys for any virtual
|
The contents of `/path/to/certs` should contain the certificates and private keys for any virtual
|
||||||
hosts in use. The certificate and keys should be named after the virtual host with a `.crt` and
|
hosts in use. The certificate and keys should be named after the virtual host with a `.crt` and
|
||||||
|
@ -121,6 +125,42 @@ to establish a connection. A self-signed or generic cert named `default.crt` an
|
||||||
will allow a client browser to make a SSL connection (likely w/ a warning) and subsequently receive
|
will allow a client browser to make a SSL connection (likely w/ a warning) and subsequently receive
|
||||||
a 503.
|
a 503.
|
||||||
|
|
||||||
|
#### Let's Encrypt
|
||||||
|
|
||||||
|
Use the Let's Encrypt service to automatically create a valid certificate for a virtual host.
|
||||||
|
|
||||||
|
Set the following environment variables to enable Let's Encrypt support for a container being proxied.
|
||||||
|
|
||||||
|
- `LETSENCRYPT_HOST`
|
||||||
|
- `LETSENCRYPT_EMAIL`
|
||||||
|
|
||||||
|
The `LETSENCRYPT_HOST` variable most likely needs to be the same as the `VIRTUAL_HOST` variable and must be publicly reachable domains. Specify multiple hosts with a comma delimiter.
|
||||||
|
|
||||||
|
For example
|
||||||
|
|
||||||
|
```
|
||||||
|
$ docker run -d -p 80:80 \
|
||||||
|
-e VIRTUAL_HOST="foo.bar.com,bar.com" \
|
||||||
|
-e LETSENCRYPT_HOST="foo.bar.com,bar.com" \
|
||||||
|
-e LETSENCRYPT_EMAIL="foo@bar.com" ...
|
||||||
|
```
|
||||||
|
|
||||||
|
##### Optional container environment variables
|
||||||
|
|
||||||
|
Optional nginx-proxy-letsencrypt container environment variables for custom configuration.
|
||||||
|
|
||||||
|
- `ACME_CA_URI` - Directory URI for the CA ACME API endpoint (default: ``https://acme-v01.api.letsencrypt.org/directory``)
|
||||||
|
|
||||||
|
For example
|
||||||
|
|
||||||
|
```
|
||||||
|
$ docker run -d -p 80:80 -p 443:443 \
|
||||||
|
-e ACME_CA_URI="https://acme-staging.api.letsencrypt.org/directory" \
|
||||||
|
-v /path/to/certs:/etc/nginx/certs \
|
||||||
|
-v /var/run/docker.sock:/tmp/docker.sock:ro \
|
||||||
|
dmp1ce/nginx-proxy-letsencrypt
|
||||||
|
```
|
||||||
|
|
||||||
### Basic Authentication Support
|
### Basic Authentication Support
|
||||||
|
|
||||||
In order to be able to secure your virtual host, you have to create a file named as its equivalent VIRTUAL_HOST variable on directory
|
In order to be able to secure your virtual host, you have to create a file named as its equivalent VIRTUAL_HOST variable on directory
|
||||||
|
@ -131,7 +171,7 @@ $ docker run -d -p 80:80 -p 443:443 \
|
||||||
-v /path/to/htpasswd:/etc/nginx/htpasswd \
|
-v /path/to/htpasswd:/etc/nginx/htpasswd \
|
||||||
-v /path/to/certs:/etc/nginx/certs \
|
-v /path/to/certs:/etc/nginx/certs \
|
||||||
-v /var/run/docker.sock:/tmp/docker.sock:ro \
|
-v /var/run/docker.sock:/tmp/docker.sock:ro \
|
||||||
jwilder/nginx-proxy
|
dmp1ce/nginx-proxy-letsencrypt
|
||||||
```
|
```
|
||||||
|
|
||||||
You'll need apache2-utils on the machine where you plan to create the htpasswd file. Follow these [instructions](http://httpd.apache.org/docs/2.2/programs/htpasswd.html)
|
You'll need apache2-utils on the machine where you plan to create the htpasswd file. Follow these [instructions](http://httpd.apache.org/docs/2.2/programs/htpasswd.html)
|
||||||
|
@ -166,7 +206,7 @@ To add settings on a proxy-wide basis, add your configuration file under `/etc/n
|
||||||
This can be done in a derived image by creating the file in a `RUN` command or by `COPY`ing the file into `conf.d`:
|
This can be done in a derived image by creating the file in a `RUN` command or by `COPY`ing the file into `conf.d`:
|
||||||
|
|
||||||
```Dockerfile
|
```Dockerfile
|
||||||
FROM jwilder/nginx-proxy
|
FROM dmp1ce/nginx-proxy-letsencrypt
|
||||||
RUN { \
|
RUN { \
|
||||||
echo 'server_tokens off;'; \
|
echo 'server_tokens off;'; \
|
||||||
echo 'client_max_body_size 100m;'; \
|
echo 'client_max_body_size 100m;'; \
|
||||||
|
@ -175,7 +215,7 @@ RUN { \
|
||||||
|
|
||||||
Or it can be done by mounting in your custom configuration in your `docker run` command:
|
Or it can be done by mounting in your custom configuration in your `docker run` command:
|
||||||
|
|
||||||
$ docker run -d -p 80:80 -p 443:443 -v /path/to/my_proxy.conf:/etc/nginx/conf.d/my_proxy.conf:ro -v /var/run/docker.sock:/tmp/docker.sock:ro jwilder/nginx-proxy
|
$ docker run -d -p 80:80 -p 443:443 -v /path/to/my_proxy.conf:/etc/nginx/conf.d/my_proxy.conf:ro -v /var/run/docker.sock:/tmp/docker.sock:ro dmp1ce/nginx-proxy-letsencrypt
|
||||||
|
|
||||||
#### Per-VIRTUAL_HOST
|
#### Per-VIRTUAL_HOST
|
||||||
|
|
||||||
|
@ -185,7 +225,7 @@ In order to allow virtual hosts to be dynamically configured as backends are add
|
||||||
|
|
||||||
For example, if you have a virtual host named `app.example.com`, you could provide a custom configuration for that host as follows:
|
For example, if you have a virtual host named `app.example.com`, you could provide a custom configuration for that host as follows:
|
||||||
|
|
||||||
$ docker run -d -p 80:80 -p 443:443 -v /path/to/vhost.d:/etc/nginx/vhost.d:ro -v /var/run/docker.sock:/tmp/docker.sock:ro jwilder/nginx-proxy
|
$ docker run -d -p 80:80 -p 443:443 -v /path/to/vhost.d:/etc/nginx/vhost.d:ro -v /var/run/docker.sock:/tmp/docker.sock:ro dmp1ce/nginx-proxy-letsencrypt
|
||||||
$ { echo 'server_tokens off;'; echo 'client_max_body_size 100m;'; } > /path/to/vhost.d/app.example.com
|
$ { echo 'server_tokens off;'; echo 'client_max_body_size 100m;'; } > /path/to/vhost.d/app.example.com
|
||||||
|
|
||||||
If you are using multiple hostnames for a single container (e.g. `VIRTUAL_HOST=example.com,www.example.com`), the virtual host configuration file must exist for each hostname. If you would like to use the same configuration for multiple virtual host names, you can use a symlink:
|
If you are using multiple hostnames for a single container (e.g. `VIRTUAL_HOST=example.com,www.example.com`), the virtual host configuration file must exist for each hostname. If you would like to use the same configuration for multiple virtual host names, you can use a symlink:
|
||||||
|
@ -205,7 +245,7 @@ just like the previous section except with the suffix `_location`.
|
||||||
|
|
||||||
For example, if you have a virtual host named `app.example.com` and you have configured a proxy_cache `my-cache` in another custom file, you could tell it to use a proxy cache as follows:
|
For example, if you have a virtual host named `app.example.com` and you have configured a proxy_cache `my-cache` in another custom file, you could tell it to use a proxy cache as follows:
|
||||||
|
|
||||||
$ docker run -d -p 80:80 -p 443:443 -v /path/to/vhost.d:/etc/nginx/vhost.d:ro -v /var/run/docker.sock:/tmp/docker.sock:ro jwilder/nginx-proxy
|
$ docker run -d -p 80:80 -p 443:443 -v /path/to/vhost.d:/etc/nginx/vhost.d:ro -v /var/run/docker.sock:/tmp/docker.sock:ro dmp1ce/nginx-proxy-letsencrypt
|
||||||
$ { echo 'proxy_cache my-cache;'; echo 'proxy_cache_valid 200 302 60m;'; echo 'proxy_cache_valid 404 1m;' } > /path/to/vhost.d/app.example.com_location
|
$ { echo 'proxy_cache my-cache;'; echo 'proxy_cache_valid 200 302 60m;'; echo 'proxy_cache_valid 404 1m;' } > /path/to/vhost.d/app.example.com_location
|
||||||
|
|
||||||
If you are using multiple hostnames for a single container (e.g. `VIRTUAL_HOST=example.com,www.example.com`), the virtual host configuration file must exist for each hostname. If you would like to use the same configuration for multiple virtual host names, you can use a symlink:
|
If you are using multiple hostnames for a single container (e.g. `VIRTUAL_HOST=example.com,www.example.com`), the virtual host configuration file must exist for each hostname. If you would like to use the same configuration for multiple virtual host names, you can use a symlink:
|
||||||
|
|
|
@ -1,7 +1,10 @@
|
||||||
machine:
|
machine:
|
||||||
pre:
|
pre:
|
||||||
|
# install docker 1.9.1 with some CircleCI suggestions:
|
||||||
|
# https://discuss.circleci.com/t/how-use-a-different-docker-version/298/8
|
||||||
- sudo curl -L -o /usr/bin/docker 'https://s3-external-1.amazonaws.com/circle-downloads/docker-1.9.1-circleci'
|
- sudo curl -L -o /usr/bin/docker 'https://s3-external-1.amazonaws.com/circle-downloads/docker-1.9.1-circleci'
|
||||||
- sudo chmod 0755 /usr/bin/docker
|
- sudo chmod 0755 /usr/bin/docker
|
||||||
|
- sudo sed -i -e 's/ --userland-proxy=false//' /etc/default/docker
|
||||||
services:
|
services:
|
||||||
- docker
|
- docker
|
||||||
|
|
||||||
|
|
|
@ -1,22 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
set -e
|
|
||||||
|
|
||||||
# Warn if the DOCKER_HOST socket does not exist
|
|
||||||
if [[ $DOCKER_HOST == unix://* ]]; then
|
|
||||||
socket_file=${DOCKER_HOST#unix://}
|
|
||||||
if ! [ -S $socket_file ]; then
|
|
||||||
cat >&2 <<-EOT
|
|
||||||
ERROR: you need to share your Docker host socket with a volume at $socket_file
|
|
||||||
Typically you should run your jwilder/nginx-proxy with: \`-v /var/run/docker.sock:$socket_file:ro\`
|
|
||||||
See the documentation at http://git.io/vZaGJ
|
|
||||||
EOT
|
|
||||||
socketMissing=1
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
# If the user has run the default command and the socket doesn't exist, fail
|
|
||||||
if [ "$socketMissing" = 1 -a "$1" = forego -a "$2" = start -a "$3" = '-r' ]; then
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
exec "$@"
|
|
28
install_simp_le.sh
Executable file
28
install_simp_le.sh
Executable file
|
@ -0,0 +1,28 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
apt-get update
|
||||||
|
|
||||||
|
# Install python packages needed by simp_le
|
||||||
|
apt-get install -y -q --no-install-recommends python python-requests
|
||||||
|
|
||||||
|
# Install python packages needed to build simp_le
|
||||||
|
apt-get install -y -q --no-install-recommends git gcc libssl-dev libffi-dev python-dev python-pip
|
||||||
|
|
||||||
|
# Get Let's Encrypt simp_le client source
|
||||||
|
git -C /opt clone https://github.com/kuba/simp_le.git
|
||||||
|
|
||||||
|
cd /opt/simp_le
|
||||||
|
# Upgrade setuptools
|
||||||
|
pip install -U setuptools
|
||||||
|
# Install simp_le in /usr/local/bin
|
||||||
|
python ./setup.py install
|
||||||
|
|
||||||
|
# Make house cleaning
|
||||||
|
rm -rf /opt/simp_le
|
||||||
|
|
||||||
|
apt-get autoremove -y git gcc libssl-dev libffi-dev python-dev python-pip
|
||||||
|
|
||||||
|
apt-get clean all
|
||||||
|
rm -r /var/lib/apt/lists/*
|
74
letsencrypt_service
Executable file
74
letsencrypt_service
Executable file
|
@ -0,0 +1,74 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||||
|
|
||||||
|
seconds_to_wait=3600
|
||||||
|
acme_ca_uri="${ACME_CA_URI:-https://acme-v01.api.letsencrypt.org/directory}"
|
||||||
|
|
||||||
|
update_certs() {
|
||||||
|
[[ ! -f "$DIR"/letsencrypt_service_data ]] && return
|
||||||
|
|
||||||
|
# Load relevant container settings
|
||||||
|
source "$DIR"/letsencrypt_service_data
|
||||||
|
|
||||||
|
reload_nginx='false'
|
||||||
|
for cid in "${LETSENCRYPT_CONTAINERS[@]}"; do
|
||||||
|
# Derive host and email variable names
|
||||||
|
host_varname="LETSENCRYPT_${cid}_HOST"
|
||||||
|
# Array variable indirection hack: http://stackoverflow.com/a/25880676/350221
|
||||||
|
hosts_array=$host_varname[@]
|
||||||
|
email_varname="LETSENCRYPT_${cid}_EMAIL"
|
||||||
|
|
||||||
|
params_d_str=""
|
||||||
|
hosts_array_expanded=("${!hosts_array}")
|
||||||
|
# First domain will be our base domain
|
||||||
|
base_domain="${hosts_array_expanded[0]}"
|
||||||
|
|
||||||
|
# Create directorty for the first domain
|
||||||
|
mkdir -p /etc/nginx/certs/$base_domain
|
||||||
|
cd /etc/nginx/certs/$base_domain
|
||||||
|
|
||||||
|
for domain in "${!hosts_array}"; do
|
||||||
|
# Add all the domains to certificate
|
||||||
|
params_d_str+=" -d $domain"
|
||||||
|
done
|
||||||
|
echo "Creating/renewal $base_domain certificates... (${hosts_array_expanded[*]})"
|
||||||
|
/usr/local/bin/simp_le \
|
||||||
|
-f account_key.json -f key.pem -f fullchain.pem \
|
||||||
|
$params_d_str \
|
||||||
|
--email "${!email_varname}" \
|
||||||
|
--server=$acme_ca_uri \
|
||||||
|
--default_root /usr/share/nginx/html/
|
||||||
|
|
||||||
|
simp_le_return=$?
|
||||||
|
|
||||||
|
if [[ $simp_le_return -eq 0 ]]; then
|
||||||
|
for domain in "${!hosts_array}"; do
|
||||||
|
# Symlink all alternative names to base domain certificate
|
||||||
|
ln -sf ./$base_domain/fullchain.pem /etc/nginx/certs/$domain".crt"
|
||||||
|
ln -sf ./$base_domain/key.pem /etc/nginx/certs/$domain".key"
|
||||||
|
done
|
||||||
|
reload_nginx='true'
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
unset LETSENCRYPT_CONTAINERS
|
||||||
|
if [[ "$reload_nginx" == 'true' ]]; then
|
||||||
|
/usr/local/bin/docker-gen -only-exposed /app/nginx.tmpl /etc/nginx/conf.d/default.conf
|
||||||
|
nginx -s reload
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
pid=
|
||||||
|
trap '[[ $pid ]] && kill $pid; exec $0' EXIT
|
||||||
|
trap 'trap - EXIT' INT TERM
|
||||||
|
|
||||||
|
echo 'Waiting 10s before updating certs...'
|
||||||
|
sleep 10s
|
||||||
|
|
||||||
|
update_certs
|
||||||
|
|
||||||
|
# Wait some amount of time
|
||||||
|
echo "Sleep for ${seconds_to_wait}s"
|
||||||
|
sleep $seconds_to_wait & pid=$!
|
||||||
|
wait
|
||||||
|
pid=
|
10
letsencrypt_service_data.tmpl
Normal file
10
letsencrypt_service_data.tmpl
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
LETSENCRYPT_CONTAINERS=({{ range $host, $containers := groupBy $ "Env.LETSENCRYPT_HOST" }}{{ range $container := $containers }} '{{ $container.ID }}' {{ end }}{{ end }})
|
||||||
|
|
||||||
|
{{ range $hosts, $containers := groupBy $ "Env.LETSENCRYPT_HOST" }}
|
||||||
|
|
||||||
|
{{ range $container := $containers }}
|
||||||
|
LETSENCRYPT_{{ $container.ID }}_HOST=( {{ range $host := split $hosts "," }}'{{ $host }}' {{ end }})
|
||||||
|
LETSENCRYPT_{{ $container.ID }}_EMAIL="{{ $container.Env.LETSENCRYPT_EMAIL }}"
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
{{ end }}
|
20
nginx.tmpl
20
nginx.tmpl
|
@ -143,7 +143,17 @@ server {
|
||||||
include /etc/nginx/vhost.d/default;
|
include /etc/nginx/vhost.d/default;
|
||||||
{{ end }}
|
{{ end }}
|
||||||
|
|
||||||
|
location /.well-known/ {
|
||||||
|
root /usr/share/nginx/html;
|
||||||
|
try_files $uri @proxy_pass;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Redirect hack. See: http://stackoverflow.com/a/20694873/350221
|
||||||
location / {
|
location / {
|
||||||
|
error_page 418 = @proxy_pass; return 418;
|
||||||
|
}
|
||||||
|
|
||||||
|
location @proxy_pass {
|
||||||
proxy_pass {{ trim $proto }}://{{ trim $host }};
|
proxy_pass {{ trim $proto }}://{{ trim $host }};
|
||||||
{{ if (exists (printf "/etc/nginx/htpasswd/%s" $host)) }}
|
{{ if (exists (printf "/etc/nginx/htpasswd/%s" $host)) }}
|
||||||
auth_basic "Restricted {{ $host }}";
|
auth_basic "Restricted {{ $host }}";
|
||||||
|
@ -169,7 +179,17 @@ server {
|
||||||
include /etc/nginx/vhost.d/default;
|
include /etc/nginx/vhost.d/default;
|
||||||
{{ end }}
|
{{ end }}
|
||||||
|
|
||||||
|
location /.well-known/ {
|
||||||
|
root /usr/share/nginx/html;
|
||||||
|
try_files $uri @proxy_pass;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Redirect hack. See: http://stackoverflow.com/a/20694873/350221
|
||||||
location / {
|
location / {
|
||||||
|
error_page 418 = @proxy_pass; return 418;
|
||||||
|
}
|
||||||
|
|
||||||
|
location @proxy_pass {
|
||||||
proxy_pass {{ trim $proto }}://{{ trim $host }};
|
proxy_pass {{ trim $proto }}://{{ trim $host }};
|
||||||
{{ if (exists (printf "/etc/nginx/htpasswd/%s" $host)) }}
|
{{ if (exists (printf "/etc/nginx/htpasswd/%s" $host)) }}
|
||||||
auth_basic "Restricted {{ $host }}";
|
auth_basic "Restricted {{ $host }}";
|
||||||
|
|
|
@ -3,12 +3,12 @@ Test suite
|
||||||
|
|
||||||
This test suite is implemented on top of the [Bats](https://github.com/sstephenson/bats/blob/master/README.md) test framework.
|
This test suite is implemented on top of the [Bats](https://github.com/sstephenson/bats/blob/master/README.md) test framework.
|
||||||
|
|
||||||
It is intended to verify the correct behavior of the Docker image `jwilder/nginx-proxy:bats`.
|
It is intended to verify the correct behavior of the Docker image `dmp1ce/nginx-proxy-letsencrypt:bats`.
|
||||||
|
|
||||||
Running the test suite
|
Running the test suite
|
||||||
----------------------
|
----------------------
|
||||||
|
|
||||||
Make sure you have Bats installed, then run:
|
Make sure you have Bats installed, then run:
|
||||||
|
|
||||||
docker build -t jwilder/nginx-proxy:bats .
|
docker build -t jwilder/nginx-proxy-letsencrypt:bats .
|
||||||
bats test/
|
bats test/
|
||||||
|
|
8
test/cleanup_test_containers.sh
Executable file
8
test/cleanup_test_containers.sh
Executable file
|
@ -0,0 +1,8 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Remove "bats-*" containers
|
||||||
|
function teardown {
|
||||||
|
docker rm -f $(docker ps -aq -f name=bats-*)
|
||||||
|
}
|
||||||
|
|
||||||
|
teardown
|
|
@ -62,7 +62,7 @@ load test_helpers
|
||||||
-v /etc/nginx/certs/ \
|
-v /etc/nginx/certs/ \
|
||||||
nginx:latest
|
nginx:latest
|
||||||
assert_success
|
assert_success
|
||||||
run retry 5 1s docker run appropriate/curl --silent --fail --head http://$(docker_ip bats-nginx)/
|
run retry 5 1s docker run --rm appropriate/curl --silent --fail --head http://$(docker_ip bats-nginx)/
|
||||||
assert_output -l 0 $'HTTP/1.1 200 OK\r'
|
assert_output -l 0 $'HTTP/1.1 200 OK\r'
|
||||||
|
|
||||||
# WHEN docker-gen runs on our docker host
|
# WHEN docker-gen runs on our docker host
|
||||||
|
@ -105,13 +105,12 @@ function assert_nginxproxy_behaves {
|
||||||
|
|
||||||
# Querying the proxy with Host header → 200
|
# Querying the proxy with Host header → 200
|
||||||
run curl_container $container /data --header "Host: web1.bats"
|
run curl_container $container /data --header "Host: web1.bats"
|
||||||
assert_output "answer from port 81"
|
assert_output -l 0 "answer from port 81"
|
||||||
|
|
||||||
run curl_container $container /data --header "Host: web2.bats"
|
run curl_container $container /data --header "Host: web2.bats"
|
||||||
assert_output "answer from port 82"
|
assert_output -l 0 "answer from port 82"
|
||||||
|
|
||||||
# Querying the proxy with unknown Host header → 503
|
# Querying the proxy with unknown Host header → 503
|
||||||
run curl_container $container /data --header "Host: webFOO.bats" --head
|
run curl_container $container /data --header "Host: webFOO.bats" --head
|
||||||
assert_output -l 0 $'HTTP/1.1 503 Service Temporarily Unavailable\r'
|
assert_output -l 0 $'HTTP/1.1 503 Service Temporarily Unavailable\r'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -56,5 +56,10 @@ function docker_tcp {
|
||||||
--expose 2375 \
|
--expose 2375 \
|
||||||
-v /var/run/docker.sock:/var/run/docker.sock \
|
-v /var/run/docker.sock:/var/run/docker.sock \
|
||||||
rancher/socat-docker
|
rancher/socat-docker
|
||||||
docker run --link "$container_name:docker" docker:1.9 version
|
docker run --rm --link "$container_name:docker" docker:1.9.1 version
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Remove "bats-*" containers after each test
|
||||||
|
#function teardown {
|
||||||
|
#docker rm -f $(docker ps -aq -f name=bats-*)
|
||||||
|
#}
|
||||||
|
|
|
@ -32,9 +32,9 @@ function setup {
|
||||||
|
|
||||||
# THEN
|
# THEN
|
||||||
run curl_container $SUT_CONTAINER /data --header 'Host: multiple-hosts-1-A.bats'
|
run curl_container $SUT_CONTAINER /data --header 'Host: multiple-hosts-1-A.bats'
|
||||||
assert_output "answer from port 80"
|
assert_output -l 0 "answer from port 80"
|
||||||
|
|
||||||
# THEN
|
# THEN
|
||||||
run curl_container $SUT_CONTAINER /data --header 'Host: multiple-hosts-1-B.bats'
|
run curl_container $SUT_CONTAINER /data --header 'Host: multiple-hosts-1-B.bats'
|
||||||
assert_output "answer from port 80"
|
assert_output -l 0 "answer from port 80"
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,6 +52,6 @@ function setup {
|
||||||
function assert_response_is_from_port {
|
function assert_response_is_from_port {
|
||||||
local -r port=$1
|
local -r port=$1
|
||||||
run curl_container $SUT_CONTAINER /data --header "Host: web.bats"
|
run curl_container $SUT_CONTAINER /data --header "Host: web.bats"
|
||||||
assert_output "answer from port $port"
|
assert_output -l 0 "answer from port $port"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
|
|
||||||
|
|
||||||
# set a few global variables
|
# set a few global variables
|
||||||
SUT_IMAGE=jwilder/nginx-proxy:bats
|
SUT_IMAGE=dmp1ce/nginx-proxy-letsencrypt:bats
|
||||||
TEST_FILE=$(basename $BATS_TEST_FILENAME .bats)
|
TEST_FILE=$(basename $BATS_TEST_FILENAME .bats)
|
||||||
|
|
||||||
|
|
||||||
|
@ -66,7 +66,7 @@ function curl_container {
|
||||||
local -r container=$1
|
local -r container=$1
|
||||||
local -r path=$2
|
local -r path=$2
|
||||||
shift 2
|
shift 2
|
||||||
docker run appropriate/curl --silent \
|
docker run --rm appropriate/curl --silent \
|
||||||
--connect-timeout 5 \
|
--connect-timeout 5 \
|
||||||
--max-time 20 \
|
--max-time 20 \
|
||||||
"$@" \
|
"$@" \
|
||||||
|
@ -128,7 +128,7 @@ function prepare_web_container {
|
||||||
# THEN querying directly port works
|
# THEN querying directly port works
|
||||||
IFS=$' \t\n' # See https://github.com/sstephenson/bats/issues/89
|
IFS=$' \t\n' # See https://github.com/sstephenson/bats/issues/89
|
||||||
for port in $ports; do
|
for port in $ports; do
|
||||||
run retry 5 1s docker run appropriate/curl --silent --fail http://$(docker_ip $container_name):$port/data
|
run retry 5 1s docker run --rm appropriate/curl --silent --fail http://$(docker_ip $container_name):$port/data
|
||||||
assert_output "answer from port $port"
|
assert_output -l 0 "answer from port $port"
|
||||||
done
|
done
|
||||||
}
|
}
|
||||||
|
|
3
update_certs
Executable file
3
update_certs
Executable file
|
@ -0,0 +1,3 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
pkill -f -SIGUSR1 /app/letsencrypt_service
|
8
update_nginx
Executable file
8
update_nginx
Executable file
|
@ -0,0 +1,8 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
nginx -s reload
|
||||||
|
|
||||||
|
docker-gen \
|
||||||
|
-only-exposed \
|
||||||
|
-notify '/app/update_certs' \
|
||||||
|
/app/letsencrypt_service_data.tmpl /app/letsencrypt_service_data
|
Loading…
Reference in a new issue