Skip to content

Commit

Permalink
feat: add example nginx, uwsgi and celery production configs
Browse files Browse the repository at this point in the history
also retain `*.env.sample` files in version control
  • Loading branch information
engineervix committed Jul 21, 2021
1 parent 6537d58 commit 42465a2
Show file tree
Hide file tree
Showing 8 changed files with 308 additions and 0 deletions.
8 changes: 8 additions & 0 deletions hooks/post_gen_project.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,14 +68,22 @@ def make_secret_key(project_directory):
example_dev_env_file = os.path.join(project_directory, "#envs/env_dev.example")

dev_env_file = os.path.join(project_directory, "#envs/.dev.env")
dev_env_sample = os.path.join(project_directory, "#envs/.dev.env.sample")

example_prod_env_file = os.path.join(project_directory, "#envs/env_prod.example")

prod_env_file = os.path.join(project_directory, "#envs/.prod.env")
prod_env_sample = os.path.join(project_directory, "#envs/.prod.env.sample")

example_test_env_file = os.path.join(project_directory, "#envs/env_test.example")

test_env_file = os.path.join(project_directory, "#envs/.test.env")
test_env_sample = os.path.join(project_directory, "#envs/.test.env.sample")

# create *.env.sample files which should be part of version control
shutil.copy(example_dev_env_file, dev_env_sample)
shutil.copy(example_prod_env_file, prod_env_sample)
shutil.copy(example_test_env_file, test_env_sample)

shutil.move(example_dev_env_file, dev_env_file)
shutil.move(example_prod_env_file, prod_env_file)
Expand Down
27 changes: 27 additions & 0 deletions {{cookiecutter.project_slug}}/#envs/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Ignore everything in this directory
*

## Except the following files:

### 0. this .gitignore file
!.gitignore

### 1. sample .env files
!.dev.env.sample
!.test.env.sample
!.prod.env.sample

### 2. sample nginx configs
!nginx
!nginx/example_nginx_https.conf
!nginx/example_nginx_no-https.conf

### 3. sample uwsgi config
!uwsgi
!uwsgi/example.ini

### 4. sample celery configs
!celery
!celery/example_celery-project
!celery/example_celery-project.service
!celery/example_celerybeat-project.service
38 changes: 38 additions & 0 deletions {{cookiecutter.project_slug}}/#envs/celery/example_celery-project
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# /etc/conf.d/celery-project

# See
# http://docs.celeryproject.org/en/latest/userguide/daemonizing.html#usage-systemd
# and https://www.willandskill.se/en/celery-4-with-django-on-ubuntu-18-04/

# App instance to use
# comment out this line if you don't use an app
CELERY_APP="config"

# Name of nodes to start
# here we have a single node
CELERYD_NODES="celeryproject"
# or we could have three nodes:
#CELERYD_NODES="celeryproject1 celeryproject2 celeryproject3"

# Extra command-line arguments to the worker
CELERYD_OPTS="--time-limit=300 --concurrency=8"

# Absolute or relative path to the 'celery' command:
# I'm using virtualenvwrapper, and celery is installed in the 'celery_project' virtual environment
CELERY_BIN="/home/username/Env/celery_project/bin/celery"

# How to call manage.py
# CELERYD_MULTI="multi"

# - %n will be replaced with the first part of the nodename.
# - %I will be replaced with the current child process index
# and is important when using the prefork pool to avoid race conditions.
CELERYD_PID_FILE="/var/run/celery/%n.pid"
CELERYD_LOG_FILE="/var/log/celery/%n%I.log"
CELERYD_LOG_LEVEL="INFO"

# The below lines should be uncommented if using the celerybeat-project.service
# unit file, but are unnecessary otherwise

CELERYBEAT_PID_FILE="/var/run/celery/celeryproject_beat.pid"
CELERYBEAT_LOG_FILE="/var/log/celery/celeryproject_beat.log"
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
[Unit]
Description=Celery Service for celeryproject.example.com
After=network.target

[Service]
Type=forking
User=celery
Group=celery
Environment="ENV_PATH=.envs/.prod.env"
EnvironmentFile=/etc/conf.d/celery-project
WorkingDirectory=/path/to/your/django-project
ExecStart=/bin/sh -c '${CELERY_BIN} multi start ${CELERYD_NODES} \
-A ${CELERY_APP} --pidfile=${CELERYD_PID_FILE} \
--logfile=${CELERYD_LOG_FILE} --loglevel=${CELERYD_LOG_LEVEL} ${CELERYD_OPTS}'
ExecStop=/bin/sh -c '${CELERY_BIN} multi stopwait ${CELERYD_NODES} \
--pidfile=${CELERYD_PID_FILE}'
ExecReload=/bin/sh -c '${CELERY_BIN} multi restart ${CELERYD_NODES} \
-A ${CELERY_APP} --pidfile=${CELERYD_PID_FILE} \
--logfile=${CELERYD_LOG_FILE} --loglevel=${CELERYD_LOG_LEVEL} ${CELERYD_OPTS}'
Restart=always

[Install]
WantedBy=multi-user.target
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
[Unit]
Description=Celery Beat Service for celeryproject.example.com
After=network.target

[Service]
Type=simple
User=celery
Group=celery
Environment="ENV_PATH=.envs/.prod.env"
EnvironmentFile=/etc/conf.d/celery-project
WorkingDirectory=/path/to/your/django-project
ExecStart=/bin/sh -c '${CELERY_BIN} -A ${CELERY_APP} beat \
--pidfile=${CELERYBEAT_PID_FILE} \
--logfile=${CELERYBEAT_LOG_FILE} \
--loglevel=${CELERYD_LOG_LEVEL} \
--schedule=/home/celery/celerybeat-schedule'
Restart=always

[Install]
WantedBy=multi-user.target
145 changes: 145 additions & 0 deletions {{cookiecutter.project_slug}}/#envs/nginx/example_nginx_https.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
## http://subdomain.example.org redirects to https://subdomain.example.org
server {
listen 80;
listen [::]:80;
server_name subdomain.example.org;

# include /etc/nginx/snippets/letsencrypt.conf;

location / {
return 301 https://subdomain.example.org$request_uri;
}
}


## Serves https://subdomain.example.org
server {
server_name subdomain.example.org;
listen 443 ssl http2;
listen [::]:443 ssl http2;
# gzip off;
gzip on;
gzip_disable "msie6";

gzip_comp_level 6;
gzip_min_length 1100;
gzip_buffers 16 8k;
gzip_proxied any;
gzip_types
# text/plain
text/css
text/js
# text/xml
text/javascript
application/javascript
application/x-javascript;
# application/json
# application/xml
# application/rss+xml
# image/svg+xml;

ssl_certificate /etc/letsencrypt/live/subdomain.example.org/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/subdomain.example.org/privkey.pem;
ssl_trusted_certificate /etc/letsencrypt/live/subdomain.example.org/fullchain.pem;

ssl_client_certificate /etc/letsencrypt/cloudflare/origin-pull-ca.pem;
ssl_verify_client on;

include /etc/nginx/snippets/ssl.conf;
# ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # recommended by Certbot
ssl_dhparam /etc/letsencrypt/dhparam.pem;

## server_tokens off; # already in /etc/nginx/snippets/ssl.conf

## add_header X-Frame-Options DENY; # already in /etc/nginx/snippets/ssl.conf
## add_header X-Content-Type-Options nosniff always; # already in /etc/nginx/snippets/ssl.conf
# add_header X-Xss-Protection "1";
## add_header X-Xss-Protection "1; mode=block" always; # already in /etc/nginx/snippets/ssl.conf

# WARNING! This header must be carefully planned before deploying it on production website
# as it could easily break stuff and prevent a website to load it’s content!
# for more info, read https://letsecure.me/secure-web-deployment-with-lets-encrypt-and-nginx/
# https://content-security-policy.com/
# https://scotthelme.co.uk/content-security-policy-an-introduction/
add_header Content-Security-Policy "script-src 'self' https://*.google-analytics.com https://*.googleapis.com https://*.twimg.com https://*.google.com https://www.google.com/recaptcha/api/js/recaptcha_ajax.js https://freegeoip.net https://*.ravenjs.com https://*.sentry.io https://*.disqus.com https://*.amazonaws.com https://*.time.ly https://*.googletagmanager.com https://api.reftagger.com https://reftaggercdn.global.ssl.fastly.net https://*.social9.com https://*.sermonaudio.com https://*.tockify.com https://*.addthis.com https://*.gstatic.com https://*.quotery.com https://*.openweathermap.org https://openweathermap.org https://*.mapbox.com https://*.cloudflare.com https://*.maxcdn.com https://*.bbci.co.uk https://browser-update.org https://*.bbc.co.uk https://*.facebook.com https://*.facebook.net https://*.twitter.com https://*.youtube.com https://cdn.jsdelivr.net 'unsafe-inline' 'unsafe-eval'";
# add_header Content-Security-Policy "default-src 'self'";
# add_header Content-Security-Policy "default-src 'self'; script-src 'self' *.google-analytics.com";
add_header Referrer-Policy strict-origin-when-cross-origin;

## ssl_stapling on; # already in /etc/nginx/snippets/ssl.conf
## ssl_stapling_verify on; # already in /etc/nginx/snippets/ssl.conf

sendfile on;
client_max_body_size 50M;
keepalive_timeout 0;

location = /favicon.ico { access_log off; log_not_found off; }

# location /ico {
# alias /path/to/your/subdomain.example.org/{{cookiecutter.project_slug}}/static/ico;
# }

location /static {
etag on;
expires 7d;
access_log off;
add_header Cache-Control "no-cache, public";
alias /path/to/your/subdomain.example.org/{{cookiecutter.project_slug}}/staticfiles;
}

location /files/ {
etag on;
expires 7d;
access_log off;
add_header Cache-Control "no-cache, public";
alias /path/to/your/subdomain.example.org/{{cookiecutter.project_slug}}/files/;
}

location / {
include uwsgi_params;
uwsgi_pass unix:/run/uwsgi/subdomain.example.org_production_app.sock;

proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# proxy_set_header X-Forwarded-Proto https; # <-
proxy_set_header X-Forwarded-Proto $scheme;
proxy_redirect off;

}

#browser caching of static assets
# location ~* \.(jpg|jpeg|svg|png|gif|ico)$ {
# etag on;
# expires 7d;
# access_log off;
# add_header Cache-Control "no-cache, public";
# }

#browser caching of css and js
# location ~* \.(css|js|gz)$ {
# etag on;
# expires 2d;
# access_log off;
# add_header Cache-Control "no-cache, public";
# }

# add one directive for each http status code
error_page 400 /ErrorPages/custom_400.html;
error_page 401 /ErrorPages/custom_401.html;
error_page 403 /ErrorPages/custom_403.html;
error_page 404 /ErrorPages/custom_404.html;
error_page 500 /ErrorPages/custom_500.html;
error_page 501 /ErrorPages/custom_501.html;
error_page 502 /ErrorPages/custom_502.html;
error_page 503 /ErrorPages/custom_503.html;
error_page 504 /ErrorPages/custom_504.html;

# redirect the virtual ErrorPages path the real path
location /ErrorPages/ {
alias /path/to/your/subdomain.example.org/{{cookiecutter.project_slug}}/templates/nginx/;
internal;
}

access_log /path/to/your/subdomain.example.org/.logs/subdomain.example.org_production_access_log;
error_log /path/to/your/subdomain.example.org/.logs/subdomain.example.org_production_error_log;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
server {

listen 80;
listen [::]:80;

root /the/path/to/your/project/;
index index.html;

server_name example.org;

include /etc/nginx/snippets/letsencrypt.conf;

access_log /the/path/to/your/project/.logs/test_access_log;
error_log /the/path/to/your/project/.logs/test_error_log;

location / {
try_files $uri $uri/ /index.html;
}

}
27 changes: 27 additions & 0 deletions {{cookiecutter.project_slug}}/#envs/uwsgi/example.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
[uwsgi]
project = example.org
uid = username
base = /home/%(uid)

chdir = %(base)/path/to/the/%(project)/
home = %(base)/Env/virtualenv_name
module = config.wsgi_production:application

master = true
processes = 3

socket = /run/uwsgi/%(project)_production_app.sock
chown-socket = %(uid):www-data
chmod-socket = 660
vacuum = true

logto = /var/log/uwsgi_%(project)_app.log

die-on-term = true

enable-threads = true
single-interpreter = true

for-readline = %(home)/env_var
env = %(_)
end-for =

0 comments on commit 42465a2

Please sign in to comment.