Skip to content

Commit 42465a2

Browse files
committed
feat: add example nginx, uwsgi and celery production configs
also retain `*.env.sample` files in version control
1 parent 6537d58 commit 42465a2

File tree

8 files changed

+308
-0
lines changed

8 files changed

+308
-0
lines changed

hooks/post_gen_project.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,14 +68,22 @@ def make_secret_key(project_directory):
6868
example_dev_env_file = os.path.join(project_directory, "#envs/env_dev.example")
6969

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

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

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

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

7880
test_env_file = os.path.join(project_directory, "#envs/.test.env")
81+
test_env_sample = os.path.join(project_directory, "#envs/.test.env.sample")
82+
83+
# create *.env.sample files which should be part of version control
84+
shutil.copy(example_dev_env_file, dev_env_sample)
85+
shutil.copy(example_prod_env_file, prod_env_sample)
86+
shutil.copy(example_test_env_file, test_env_sample)
7987

8088
shutil.move(example_dev_env_file, dev_env_file)
8189
shutil.move(example_prod_env_file, prod_env_file)
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# Ignore everything in this directory
2+
*
3+
4+
## Except the following files:
5+
6+
### 0. this .gitignore file
7+
!.gitignore
8+
9+
### 1. sample .env files
10+
!.dev.env.sample
11+
!.test.env.sample
12+
!.prod.env.sample
13+
14+
### 2. sample nginx configs
15+
!nginx
16+
!nginx/example_nginx_https.conf
17+
!nginx/example_nginx_no-https.conf
18+
19+
### 3. sample uwsgi config
20+
!uwsgi
21+
!uwsgi/example.ini
22+
23+
### 4. sample celery configs
24+
!celery
25+
!celery/example_celery-project
26+
!celery/example_celery-project.service
27+
!celery/example_celerybeat-project.service
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
# /etc/conf.d/celery-project
2+
3+
# See
4+
# http://docs.celeryproject.org/en/latest/userguide/daemonizing.html#usage-systemd
5+
# and https://www.willandskill.se/en/celery-4-with-django-on-ubuntu-18-04/
6+
7+
# App instance to use
8+
# comment out this line if you don't use an app
9+
CELERY_APP="config"
10+
11+
# Name of nodes to start
12+
# here we have a single node
13+
CELERYD_NODES="celeryproject"
14+
# or we could have three nodes:
15+
#CELERYD_NODES="celeryproject1 celeryproject2 celeryproject3"
16+
17+
# Extra command-line arguments to the worker
18+
CELERYD_OPTS="--time-limit=300 --concurrency=8"
19+
20+
# Absolute or relative path to the 'celery' command:
21+
# I'm using virtualenvwrapper, and celery is installed in the 'celery_project' virtual environment
22+
CELERY_BIN="/home/username/Env/celery_project/bin/celery"
23+
24+
# How to call manage.py
25+
# CELERYD_MULTI="multi"
26+
27+
# - %n will be replaced with the first part of the nodename.
28+
# - %I will be replaced with the current child process index
29+
# and is important when using the prefork pool to avoid race conditions.
30+
CELERYD_PID_FILE="/var/run/celery/%n.pid"
31+
CELERYD_LOG_FILE="/var/log/celery/%n%I.log"
32+
CELERYD_LOG_LEVEL="INFO"
33+
34+
# The below lines should be uncommented if using the celerybeat-project.service
35+
# unit file, but are unnecessary otherwise
36+
37+
CELERYBEAT_PID_FILE="/var/run/celery/celeryproject_beat.pid"
38+
CELERYBEAT_LOG_FILE="/var/log/celery/celeryproject_beat.log"
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
[Unit]
2+
Description=Celery Service for celeryproject.example.com
3+
After=network.target
4+
5+
[Service]
6+
Type=forking
7+
User=celery
8+
Group=celery
9+
Environment="ENV_PATH=.envs/.prod.env"
10+
EnvironmentFile=/etc/conf.d/celery-project
11+
WorkingDirectory=/path/to/your/django-project
12+
ExecStart=/bin/sh -c '${CELERY_BIN} multi start ${CELERYD_NODES} \
13+
-A ${CELERY_APP} --pidfile=${CELERYD_PID_FILE} \
14+
--logfile=${CELERYD_LOG_FILE} --loglevel=${CELERYD_LOG_LEVEL} ${CELERYD_OPTS}'
15+
ExecStop=/bin/sh -c '${CELERY_BIN} multi stopwait ${CELERYD_NODES} \
16+
--pidfile=${CELERYD_PID_FILE}'
17+
ExecReload=/bin/sh -c '${CELERY_BIN} multi restart ${CELERYD_NODES} \
18+
-A ${CELERY_APP} --pidfile=${CELERYD_PID_FILE} \
19+
--logfile=${CELERYD_LOG_FILE} --loglevel=${CELERYD_LOG_LEVEL} ${CELERYD_OPTS}'
20+
Restart=always
21+
22+
[Install]
23+
WantedBy=multi-user.target
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
[Unit]
2+
Description=Celery Beat Service for celeryproject.example.com
3+
After=network.target
4+
5+
[Service]
6+
Type=simple
7+
User=celery
8+
Group=celery
9+
Environment="ENV_PATH=.envs/.prod.env"
10+
EnvironmentFile=/etc/conf.d/celery-project
11+
WorkingDirectory=/path/to/your/django-project
12+
ExecStart=/bin/sh -c '${CELERY_BIN} -A ${CELERY_APP} beat \
13+
--pidfile=${CELERYBEAT_PID_FILE} \
14+
--logfile=${CELERYBEAT_LOG_FILE} \
15+
--loglevel=${CELERYD_LOG_LEVEL} \
16+
--schedule=/home/celery/celerybeat-schedule'
17+
Restart=always
18+
19+
[Install]
20+
WantedBy=multi-user.target
Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
## http://subdomain.example.org redirects to https://subdomain.example.org
2+
server {
3+
listen 80;
4+
listen [::]:80;
5+
server_name subdomain.example.org;
6+
7+
# include /etc/nginx/snippets/letsencrypt.conf;
8+
9+
location / {
10+
return 301 https://subdomain.example.org$request_uri;
11+
}
12+
}
13+
14+
15+
## Serves https://subdomain.example.org
16+
server {
17+
server_name subdomain.example.org;
18+
listen 443 ssl http2;
19+
listen [::]:443 ssl http2;
20+
# gzip off;
21+
gzip on;
22+
gzip_disable "msie6";
23+
24+
gzip_comp_level 6;
25+
gzip_min_length 1100;
26+
gzip_buffers 16 8k;
27+
gzip_proxied any;
28+
gzip_types
29+
# text/plain
30+
text/css
31+
text/js
32+
# text/xml
33+
text/javascript
34+
application/javascript
35+
application/x-javascript;
36+
# application/json
37+
# application/xml
38+
# application/rss+xml
39+
# image/svg+xml;
40+
41+
ssl_certificate /etc/letsencrypt/live/subdomain.example.org/fullchain.pem;
42+
ssl_certificate_key /etc/letsencrypt/live/subdomain.example.org/privkey.pem;
43+
ssl_trusted_certificate /etc/letsencrypt/live/subdomain.example.org/fullchain.pem;
44+
45+
ssl_client_certificate /etc/letsencrypt/cloudflare/origin-pull-ca.pem;
46+
ssl_verify_client on;
47+
48+
include /etc/nginx/snippets/ssl.conf;
49+
# ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # recommended by Certbot
50+
ssl_dhparam /etc/letsencrypt/dhparam.pem;
51+
52+
## server_tokens off; # already in /etc/nginx/snippets/ssl.conf
53+
54+
## add_header X-Frame-Options DENY; # already in /etc/nginx/snippets/ssl.conf
55+
## add_header X-Content-Type-Options nosniff always; # already in /etc/nginx/snippets/ssl.conf
56+
# add_header X-Xss-Protection "1";
57+
## add_header X-Xss-Protection "1; mode=block" always; # already in /etc/nginx/snippets/ssl.conf
58+
59+
# WARNING! This header must be carefully planned before deploying it on production website
60+
# as it could easily break stuff and prevent a website to load it’s content!
61+
# for more info, read https://letsecure.me/secure-web-deployment-with-lets-encrypt-and-nginx/
62+
# https://content-security-policy.com/
63+
# https://scotthelme.co.uk/content-security-policy-an-introduction/
64+
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'";
65+
# add_header Content-Security-Policy "default-src 'self'";
66+
# add_header Content-Security-Policy "default-src 'self'; script-src 'self' *.google-analytics.com";
67+
add_header Referrer-Policy strict-origin-when-cross-origin;
68+
69+
## ssl_stapling on; # already in /etc/nginx/snippets/ssl.conf
70+
## ssl_stapling_verify on; # already in /etc/nginx/snippets/ssl.conf
71+
72+
sendfile on;
73+
client_max_body_size 50M;
74+
keepalive_timeout 0;
75+
76+
location = /favicon.ico { access_log off; log_not_found off; }
77+
78+
# location /ico {
79+
# alias /path/to/your/subdomain.example.org/{{cookiecutter.project_slug}}/static/ico;
80+
# }
81+
82+
location /static {
83+
etag on;
84+
expires 7d;
85+
access_log off;
86+
add_header Cache-Control "no-cache, public";
87+
alias /path/to/your/subdomain.example.org/{{cookiecutter.project_slug}}/staticfiles;
88+
}
89+
90+
location /files/ {
91+
etag on;
92+
expires 7d;
93+
access_log off;
94+
add_header Cache-Control "no-cache, public";
95+
alias /path/to/your/subdomain.example.org/{{cookiecutter.project_slug}}/files/;
96+
}
97+
98+
location / {
99+
include uwsgi_params;
100+
uwsgi_pass unix:/run/uwsgi/subdomain.example.org_production_app.sock;
101+
102+
proxy_set_header Host $http_host;
103+
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
104+
# proxy_set_header X-Forwarded-Proto https; # <-
105+
proxy_set_header X-Forwarded-Proto $scheme;
106+
proxy_redirect off;
107+
108+
}
109+
110+
#browser caching of static assets
111+
# location ~* \.(jpg|jpeg|svg|png|gif|ico)$ {
112+
# etag on;
113+
# expires 7d;
114+
# access_log off;
115+
# add_header Cache-Control "no-cache, public";
116+
# }
117+
118+
#browser caching of css and js
119+
# location ~* \.(css|js|gz)$ {
120+
# etag on;
121+
# expires 2d;
122+
# access_log off;
123+
# add_header Cache-Control "no-cache, public";
124+
# }
125+
126+
# add one directive for each http status code
127+
error_page 400 /ErrorPages/custom_400.html;
128+
error_page 401 /ErrorPages/custom_401.html;
129+
error_page 403 /ErrorPages/custom_403.html;
130+
error_page 404 /ErrorPages/custom_404.html;
131+
error_page 500 /ErrorPages/custom_500.html;
132+
error_page 501 /ErrorPages/custom_501.html;
133+
error_page 502 /ErrorPages/custom_502.html;
134+
error_page 503 /ErrorPages/custom_503.html;
135+
error_page 504 /ErrorPages/custom_504.html;
136+
137+
# redirect the virtual ErrorPages path the real path
138+
location /ErrorPages/ {
139+
alias /path/to/your/subdomain.example.org/{{cookiecutter.project_slug}}/templates/nginx/;
140+
internal;
141+
}
142+
143+
access_log /path/to/your/subdomain.example.org/.logs/subdomain.example.org_production_access_log;
144+
error_log /path/to/your/subdomain.example.org/.logs/subdomain.example.org_production_error_log;
145+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
server {
2+
3+
listen 80;
4+
listen [::]:80;
5+
6+
root /the/path/to/your/project/;
7+
index index.html;
8+
9+
server_name example.org;
10+
11+
include /etc/nginx/snippets/letsencrypt.conf;
12+
13+
access_log /the/path/to/your/project/.logs/test_access_log;
14+
error_log /the/path/to/your/project/.logs/test_error_log;
15+
16+
location / {
17+
try_files $uri $uri/ /index.html;
18+
}
19+
20+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
[uwsgi]
2+
project = example.org
3+
uid = username
4+
base = /home/%(uid)
5+
6+
chdir = %(base)/path/to/the/%(project)/
7+
home = %(base)/Env/virtualenv_name
8+
module = config.wsgi_production:application
9+
10+
master = true
11+
processes = 3
12+
13+
socket = /run/uwsgi/%(project)_production_app.sock
14+
chown-socket = %(uid):www-data
15+
chmod-socket = 660
16+
vacuum = true
17+
18+
logto = /var/log/uwsgi_%(project)_app.log
19+
20+
die-on-term = true
21+
22+
enable-threads = true
23+
single-interpreter = true
24+
25+
for-readline = %(home)/env_var
26+
env = %(_)
27+
end-for =

0 commit comments

Comments
 (0)