If you need a good way to secure your Django admin site (e.g., http://example.com/admin/), this is it.
Reference: https://gist.github.com/mtigas/952344
Find a directory to put your certificates, e.g., /etc/nginx/certs/.
Generate server certificate:
openssl genrsa -out ca.key 4096
openssl req -new -x509 -days 365 -key ca.key -out ca.crt
Generate client certificate:
openssl genrsa -out client.key 4096
openssl req -new -key client.key -out client.csr
# self-signed
openssl x509 -req -days 365 -in client.csr -CA ca.crt -CAkey ca.key -set_serial 01 -out client.crt
Convert client key to PKCS (for browsers):
openssl pkcs12 -export -clcerts -in client.crt -inkey client.key -out client.p12
Make sure you enter an export password. Otherwise, you may be unable to import it to your browser.
/etc/nginx/sites-available/yoursite:
# the upstream component nginx needs to connect to
upstream django {
#server 127.0.0.1:8000; # for a web port socket
server unix:///tmp/uwsgi_yoursite.sock;
}
# configuration of the server
server {
# the port your site will be served on
listen 80;
# the domain name it will serve for
server_name .example.com; # substitute your machine's IP address or FQDN
charset utf-8;
# max upload size
client_max_body_size 75M; # adjust to taste
location /media {
alias /path/to/your/site/media;
}
location /static {
alias /path/to/your/site/static;
}
location /favicon.ico {
alias /path/to/your/site/static/img/favicon.ico;
}
# admin is served at port 443, return 404 on port 80
location /admin {
return 404;
}
# send all other requests to the Django server
location / {
include /etc/nginx/uwsgi_params;
uwsgi_pass django;
}
# redirect error pages to Django, should provide Django views for these
error_page 404 = /_error/404/;
error_page 403 = /_error/403/;
error_page 500 = /_error/500/;
error_page 502 503 = /static/_503.html;
}
server {
listen 443;
ssl on;
ssl_certificate /etc/nginx/certs/ca.crt;
ssl_certificate_key /etc/nginx/certs/ca.key;
ssl_client_certificate /etc/nginx/certs/ca.crt;
ssl_verify_client on;
location /media {
alias /path/to/your/site/media;
}
location /static {
alias /path/to/your/site/static;
}
location /admin {
include /etc/nginx/uwsgi_params;
uwsgi_param HTTP_X_FORWARDED_PROTO $scheme;
uwsgi_pass django;
}
# redirect other requests to http
location / {
return 301 http://$host$request_uri;
}
}
Download (with scp command) the .p12 file to your client computer.
Take Chrome browser on Mac OS for example, go to [Settings] -> [Show advanced settings]. Click [Manage certificate] button in HTTPS/SSL section. In the menu bar of Keychain Access, click [File] -> [Import Items]. Then select the .p12 file.
Restart the browser, access https://example.com/admin/, it should prompt you to choose a certificate. Select the one you just imported and you should be able to see the Django admin page successfully.
@pete-experimenter corrected it. Thanks!