switch to caddy (#1282)

This commit is contained in:
Jannis Gebauer 2017-08-11 11:16:15 +02:00 committed by GitHub
parent 035dc4d7ab
commit 8801c50867
13 changed files with 34 additions and 301 deletions

View File

@ -171,7 +171,6 @@ Answer the prompts with your own desired options_. For example::
2 - Grunt 2 - Grunt
3 - None 3 - None
Choose from 1, 2, 3, 4 [1]: 1 Choose from 1, 2, 3, 4 [1]: 1
use_lets_encrypt [n]: n
Select open_source_license: Select open_source_license:
1 - MIT 1 - MIT
2 - BSD 2 - BSD

View File

@ -20,7 +20,6 @@
"use_compressor": "n", "use_compressor": "n",
"postgresql_version": ["9.6", "9.5", "9.4", "9.3", "9.2"], "postgresql_version": ["9.6", "9.5", "9.4", "9.3", "9.2"],
"js_task_runner": ["Gulp", "Grunt", "None"], "js_task_runner": ["Gulp", "Grunt", "None"],
"use_lets_encrypt": "n",
"custom_bootstrap_compilation": "n", "custom_bootstrap_compilation": "n",
"open_source_license": ["MIT", "BSD", "GPLv3", "Apache Software License 2.0", "Not open source"] "open_source_license": ["MIT", "BSD", "GPLv3", "Apache Software License 2.0", "Not open source"]
} }

View File

@ -72,9 +72,6 @@ js_task_runner [1]
2. Grunt_ 2. Grunt_
3. None 3. None
use_lets_encrypt [n]
Use `Let's Encrypt`_ as the certificate authority for this project.
custom_bootstrap_compilation [n] custom_bootstrap_compilation [n]
If you use Grunt, scaffold out recompiling Bootstrap as as task. (Useful for letting you change Bootstrap variables in real time.) Consult project README for more details. If you use Grunt, scaffold out recompiling Bootstrap as as task. (Useful for letting you change Bootstrap variables in real time.) Consult project README for more details.

View File

@ -167,14 +167,6 @@ def remove_packageJSON_file():
PROJECT_DIRECTORY, filename PROJECT_DIRECTORY, filename
)) ))
def remove_certbot_files():
"""
Removes files needed for certbot if it isn't going to be used
"""
nginx_dir_location = os.path.join(PROJECT_DIRECTORY, 'compose/nginx')
for filename in ["nginx-secure.conf", "start.sh", "dhparams.example.pem"]:
file_name = os.path.join(nginx_dir_location, filename)
remove_file(file_name)
def remove_copying_files(): def remove_copying_files():
""" """
@ -229,26 +221,26 @@ def remove_open_source_files():
# dst = os.path.join(target_dir, name) # dst = os.path.join(target_dir, name)
# shutil.copyfile(src, dst) # shutil.copyfile(src, dst)
# 1. Generates and saves random secret key # Generates and saves random secret key
make_secret_key(PROJECT_DIRECTORY) make_secret_key(PROJECT_DIRECTORY)
# 2. Removes the taskapp if celery isn't going to be used # Removes the taskapp if celery isn't going to be used
if '{{ cookiecutter.use_celery }}'.lower() == 'n': if '{{ cookiecutter.use_celery }}'.lower() == 'n':
remove_task_app(PROJECT_DIRECTORY) remove_task_app(PROJECT_DIRECTORY)
# 3. Removes the .idea directory if PyCharm isn't going to be used # Removes the .idea directory if PyCharm isn't going to be used
if '{{ cookiecutter.use_pycharm }}'.lower() != 'y': if '{{ cookiecutter.use_pycharm }}'.lower() != 'y':
remove_pycharm_dir(PROJECT_DIRECTORY) remove_pycharm_dir(PROJECT_DIRECTORY)
# 4. Removes all heroku files if it isn't going to be used # Removes all heroku files if it isn't going to be used
if '{{ cookiecutter.use_heroku }}'.lower() != 'y': if '{{ cookiecutter.use_heroku }}'.lower() != 'y':
remove_heroku_files() remove_heroku_files()
# 5. Removes all docker files if it isn't going to be used # Removes all docker files if it isn't going to be used
if '{{ cookiecutter.use_docker }}'.lower() != 'y': if '{{ cookiecutter.use_docker }}'.lower() != 'y':
remove_docker_files() remove_docker_files()
# 6. Removes all JS task manager files if it isn't going to be used # Removes all JS task manager files if it isn't going to be used
if '{{ cookiecutter.js_task_runner}}'.lower() == 'gulp': if '{{ cookiecutter.js_task_runner}}'.lower() == 'gulp':
remove_grunt_files() remove_grunt_files()
elif '{{ cookiecutter.js_task_runner}}'.lower() == 'grunt': elif '{{ cookiecutter.js_task_runner}}'.lower() == 'grunt':
@ -258,11 +250,7 @@ else:
remove_grunt_files() remove_grunt_files()
remove_packageJSON_file() remove_packageJSON_file()
# 7. Removes all certbot/letsencrypt files if it isn't going to be used # Display a warning if use_docker and use_grunt are selected. Grunt isn't
if '{{ cookiecutter.use_lets_encrypt }}'.lower() != 'y':
remove_certbot_files()
# 8. Display a warning if use_docker and use_grunt are selected. Grunt isn't
# supported by our docker config atm. # supported by our docker config atm.
if '{{ cookiecutter.js_task_runner }}'.lower() in ['grunt', 'gulp'] and '{{ cookiecutter.use_docker }}'.lower() == 'y': if '{{ cookiecutter.js_task_runner }}'.lower() in ['grunt', 'gulp'] and '{{ cookiecutter.use_docker }}'.lower() == 'y':
print( print(
@ -271,29 +259,15 @@ if '{{ cookiecutter.js_task_runner }}'.lower() in ['grunt', 'gulp'] and '{{ cook
"js task runner service to your docker configuration manually." "js task runner service to your docker configuration manually."
) )
# 9. Removes the certbot/letsencrypt files and display a warning if use_lets_encrypt is selected and use_docker isn't.
if '{{ cookiecutter.use_lets_encrypt }}'.lower() == 'y' and '{{ cookiecutter.use_docker }}'.lower() != 'y':
remove_certbot_files()
print(
"You selected to use Let's Encrypt and didn't select to use docker. This is NOT supported out of the box for now. You "
"can continue to use the project like you normally would, but Let's Encrypt files have been included."
)
# 10. Directs the user to the documentation if certbot and docker are selected. # Removes files needed for the GPLv3 licence if it isn't going to be used.
if '{{ cookiecutter.use_lets_encrypt }}'.lower() == 'y' and '{{ cookiecutter.use_docker }}'.lower() == 'y':
print(
"You selected to use Let's Encrypt, please see the documentation for instructions on how to use this in production. "
"You must generate a dhparams.pem file before running docker-compose in a production environment."
)
# 11. Removes files needed for the GPLv3 licence if it isn't going to be used.
if '{{ cookiecutter.open_source_license}}' != 'GPLv3': if '{{ cookiecutter.open_source_license}}' != 'GPLv3':
remove_copying_files() remove_copying_files()
# 12. Remove Elastic Beanstalk files # Remove Elastic Beanstalk files
if '{{ cookiecutter.use_elasticbeanstalk_experimental }}'.lower() != 'y': if '{{ cookiecutter.use_elasticbeanstalk_experimental }}'.lower() != 'y':
remove_elasticbeanstalk() remove_elasticbeanstalk()
# 13. Remove files conventional to opensource projects only. # Remove files conventional to opensource projects only.
if '{{ cookiecutter.open_source_license }}' == 'Not open source': if '{{ cookiecutter.open_source_license }}' == 'Not open source':
remove_open_source_files() remove_open_source_files()

View File

@ -0,0 +1,14 @@
www.{% raw %}{%DOMAIN_NAME%}{% endraw %} {
redir https://{{cookiecutter.domain_name}}
}
{% raw %}{%DOMAIN_NAME%}{% endraw %} {
proxy / django:5000 {
header_upstream Host {host}
header_upstream X-Real-IP {remote}
header_upstream X-Forwarded-Proto {scheme}
}
log stdout
errors stdout
gzip
}

View File

@ -0,0 +1,2 @@
FROM abiosoft/caddy:0.10.6
COPY Caddyfile /etc/Caddyfile

View File

@ -1,12 +0,0 @@
FROM nginx:latest
ADD nginx.conf /etc/nginx/nginx.conf
{% if cookiecutter.use_lets_encrypt == 'y' and cookiecutter.use_docker == 'y' %}
# installs the `ps` command in the nginx image
RUN apt-get update && apt-get install -y procps
ADD start.sh /start.sh
ADD nginx-secure.conf /etc/nginx/nginx-secure.conf
ADD dhparams.pem /etc/ssl/private/dhparams.pem
CMD /start.sh
{% endif %}

View File

@ -1,3 +0,0 @@
-----BEGIN DH PARAMETERS-----
EXAMPLE_FILE
-----END DH PARAMETERS-----

View File

@ -1,98 +0,0 @@
user nginx;
worker_processes 1;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
#tcp_nopush on;
keepalive_timeout 65;
proxy_headers_hash_bucket_size 52;
gzip on;
upstream app {
server django:5000;
}
server {
listen 80;
server_name ___my.example.com___ www.___my.example.com___;
location /.well-known/acme-challenge {
# Since the certbot container isn't up constantly, need to resolve ip dynamically using docker's dns
resolver ___NAMESERVER___;
set $certbot_addr_port certbot:80;
proxy_pass http://$certbot_addr_port;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme;
}
location / {
return 301 https://$server_name$request_uri;
}
}
server {
listen 443;
server_name ___my.example.com___ www.___my.example.com___;
ssl on;
ssl_certificate /etc/letsencrypt/live/___my.example.com___/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/___my.example.com___/privkey.pem;
ssl_session_timeout 5m;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers 'EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH';
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
ssl_dhparam /etc/ssl/private/dhparams.pem;
location /.well-known/acme-challenge {
resolver ___NAMESERVER___;
set $certbot_addr_port certbot:443;
proxy_pass http://$certbot_addr_port;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header X-Forwarded-Proto https;
}
location / {
# checks for static file, if not found proxy to app
try_files $uri @proxy_to_app;
}
# cookiecutter-django app
location @proxy_to_app {
proxy_set_header X-Forwarded-Proto https;
proxy_set_header X-Url-Scheme $scheme;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_pass http://app;
}
}
}

View File

@ -1,61 +0,0 @@
user nginx;
worker_processes 1;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
#tcp_nopush on;
keepalive_timeout 65;
#gzip on;
upstream app {
server django:5000;
}
server {
listen 80;
charset utf-8;
{% if cookiecutter.use_lets_encrypt == 'y' and cookiecutter.use_docker == 'y' %}
server_name ___my.example.com___ ;
location /.well-known/acme-challenge {
proxy_pass http://certbot:80;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header X-Forwarded-Proto https;
}
{% endif %}
location / {
# checks for static file, if not found proxy to app
try_files $uri @proxy_to_app;
}
# cookiecutter-django app
location @proxy_to_app {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_pass http://app;
}
}
}

View File

@ -1,62 +0,0 @@
echo sleep 5
sleep 5
echo build starting nginx config
echo replacing ___my.example.com___/$MY_DOMAIN_NAME
# Put your domain name into the nginx reverse proxy config.
sed -i "s/___my.example.com___/$MY_DOMAIN_NAME/g" /etc/nginx/nginx.conf
cat /etc/nginx/nginx.conf
echo .
echo Firing up nginx in the background.
nginx
# # Check user has specified domain name
if [ -z "$MY_DOMAIN_NAME" ]; then
echo "Need to set MY_DOMAIN_NAME (to a letsencrypt-registered name)."
exit 1
fi
# This bit waits until the letsencrypt container has done its thing.
# We see the changes here bceause there's a docker volume mapped.
echo Waiting for folder /etc/letsencrypt/live/$MY_DOMAIN_NAME to exist
while [ ! -d /etc/letsencrypt/live/$MY_DOMAIN_NAME ] ;
do
sleep 2
done
while [ ! -f /etc/letsencrypt/live/$MY_DOMAIN_NAME/fullchain.pem ] ;
do
echo Waiting for file fullchain.pem to exist
sleep 2
done
while [ ! -f /etc/letsencrypt/live/$MY_DOMAIN_NAME/privkey.pem ] ;
do
echo Waiting for file privkey.pem to exist
sleep 2
done
# This is added so that when the certificate is being renewed or is already in place, nginx waits for everything to be good.
sleep 15
echo replacing ___my.example.com___/$MY_DOMAIN_NAME
# Put your domain name into the nginx reverse proxy config.
sed -i "s/___my.example.com___/$MY_DOMAIN_NAME/g" /etc/nginx/nginx-secure.conf
# Add the system's nameserver (the docker network dns) so we can resolve container names in nginx
NAMESERVER=`cat /etc/resolv.conf | grep "nameserver" | awk '{print $2}' | tr '\n' ' '`
echo replacing ___NAMESERVER___/$NAMESERVER
sed -i "s/___NAMESERVER___/$NAMESERVER/g" /etc/nginx/nginx-secure.conf
#go!
kill $(ps aux | grep 'nginx' | grep -v 'grep' | awk '{print $2}')
cp /etc/nginx/nginx-secure.conf /etc/nginx/nginx.conf
nginx -g 'daemon off;'

View File

@ -3,6 +3,9 @@
POSTGRES_PASSWORD=mysecretpass POSTGRES_PASSWORD=mysecretpass
POSTGRES_USER=postgresuser POSTGRES_USER=postgresuser
# Domain name, used by caddy
DOMAIN_NAME={{ cookiecutter.domain_name }}
# General settings # General settings
# DJANGO_READ_DOT_ENV_FILE=True # DJANGO_READ_DOT_ENV_FILE=True
DJANGO_ADMIN_URL= DJANGO_ADMIN_URL=

View File

@ -3,6 +3,7 @@ version: '2'
volumes: volumes:
postgres_data: {} postgres_data: {}
postgres_backup: {} postgres_backup: {}
caddy: {}
services: services:
django: django:
@ -22,36 +23,16 @@ services:
- postgres_backup:/backups - postgres_backup:/backups
env_file: .env env_file: .env
nginx: caddy:
build: ./compose/nginx build: ./compose/caddy
depends_on: depends_on:
- django - django
{% if cookiecutter.use_lets_encrypt == 'y' %}
- certbot
environment:
- MY_DOMAIN_NAME={{ cookiecutter.domain_name }}
{% endif %}
ports: ports:
- "0.0.0.0:80:80" - "0.0.0.0:80:80"
{% if cookiecutter.use_lets_encrypt == 'y' %}
- "0.0.0.0:443:443" - "0.0.0.0:443:443"
volumes: volumes:
- /etc/letsencrypt:/etc/letsencrypt - caddy:/root/.caddy
- /var/lib/letsencrypt:/var/lib/letsencrypt env_file: .env
certbot:
image: quay.io/letsencrypt/letsencrypt
command: bash -c "sleep 6 && certbot certonly -n --standalone -d {{ cookiecutter.domain_name }} --test --agree-tos --email {{ cookiecutter.email }} --server https://acme-v01.api.letsencrypt.org/directory --rsa-key-size 4096 --verbose --keep-until-expiring --preferred-challenges http-01"
entrypoint: ""
volumes:
- /etc/letsencrypt:/etc/letsencrypt
- /var/lib/letsencrypt:/var/lib/letsencrypt
ports:
- "80"
- "443"
environment:
- TERM=xterm
{% endif %}
redis: redis:
image: redis:3.0 image: redis:3.0