@@ -1,3 +1,41 @@ | |||
# nginx | |||
nginx container for lesspass | |||
## custom SSL certificate | |||
change domain name in `docker-compose.yml` file | |||
replace YOUR_DOMAIN_NAME | |||
..... | |||
ports: | |||
- "8080:8080" | |||
nginx: | |||
restart: always | |||
build: ./nginx | |||
ports: | |||
- "80:80" | |||
- "443:443" | |||
environment: | |||
- domain=YOUR_DOMAIN_NAME | |||
volumes: | |||
- ./nginx/ssl:/certificates | |||
volumes_from: | |||
- backend | |||
links: | |||
- backend | |||
- frontend | |||
..... | |||
copy your private key to `ssl/YOUR_DOMAIN_NAME.key` | |||
copy your certificate to `ssl/YOUR_DOMAIN_NAME.crt` | |||
if you have extra certificate authorities, copy the file to `ssl/YOUR_DOMAIN_NAME.ca.crt` | |||
if you have a DH parameter file, copy the file to `ssl/YOUR_DOMAIN_NAME.dhparam.pem` | |||
Example if your domain is `lesspass.com` | |||
ls ssl/ | |||
lesspass.com.ca.crt lesspass.com.crt lesspass.com.dhparam.pem lesspass.com.key | |||
@@ -1,6 +1,6 @@ | |||
server { | |||
listen 80; | |||
server_name {{ server_name }}; | |||
server_name localhost *.{{ domain }}; | |||
return 301 https://$server_name$request_uri; | |||
} | |||
@@ -10,7 +10,7 @@ server { | |||
listen [::]:443 ssl; | |||
listen 443 ssl; | |||
server_name {{ server_name }}; | |||
server_name localhost *.{{ domain }}; | |||
charset utf-8; | |||
@@ -23,14 +23,18 @@ server { | |||
ssl_protocols TLSv1 TLSv1.1 TLSv1.2; | |||
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:ECDHE-RSA-DES-CBC3-SHA:ECDHE-ECDSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA; | |||
ssl_prefer_server_ciphers on; | |||
ssl_stapling on; | |||
ssl_stapling_verify on; | |||
{% if dhparam %} | |||
ssl_dhparam {{ dhparam_path }}; | |||
ssl_dhparam /etc/ssl/certs/dhparam.pem; | |||
{% endif %} | |||
{% if ssl_trusted_certificate %} | |||
ssl_trusted_certificate {{ ssl_trusted_certificate_path }}; | |||
resolver 8.8.8.8 8.8.4.4 208.67.222.222 208.67.220.220 valid=300s; | |||
resolver_timeout 10s; | |||
ssl_stapling on; | |||
ssl_stapling_verify on; | |||
ssl_trusted_certificate /etc/ssl/certs/ca.crt; | |||
{% endif %} | |||
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always; | |||
@@ -1,15 +0,0 @@ | |||
############################### | |||
## self-signed certificates ## | |||
############################### | |||
domain=lesspass.com | |||
server_name=localhost | |||
############################### | |||
## use custom certificate ## | |||
############################### | |||
#domain, server_name, private_key and certificate are mandatory | |||
#domain=lesspass.com | |||
#server_name=localhost *.lesspass.com | |||
#private_key=lesspass.com.key | |||
#certificate=lesspass.com.crt | |||
#dhparam=dhparam.pem | |||
#ssl_trusted_certificate=AddTrustExternalCARoot.crt |
@@ -5,55 +5,47 @@ import subprocess | |||
from dockersible.files import copy, template | |||
def copy_certificates(): | |||
copy(source=(os.path.join('/certificates', os.environ['private_key'])), | |||
destination='/etc/ssl/private', | |||
basename='private.key', | |||
mode='0600') | |||
copy(source=os.path.join('/certificates', os.environ['certificate']), | |||
destination='/etc/ssl/certs', | |||
basename='certificate.crt', | |||
mode='0644') | |||
context = { | |||
'server_name': os.environ['server_name'], | |||
'dhparam': False, | |||
'ssl_trusted_certificate': False | |||
} | |||
cert_folder = os.path.join('/etc/ssl/certs') | |||
if 'dhparam' in os.environ: | |||
dhparam = os.environ['dhparam'] | |||
copy(source=os.path.join('/certificates', dhparam), destination=cert_folder, mode='0644') | |||
context['dhparam'] = True | |||
context['dhparam_path'] = os.path.join(cert_folder, dhparam) | |||
if 'certificate' in os.environ: | |||
certificate = os.environ['ssl_trusted_certificate'] | |||
copy(source=os.path.join('/certificates', certificate), destination=cert_folder, mode='0644') | |||
context['ssl_trusted_certificate'] = True | |||
context['ssl_trusted_certificate_path'] = os.path.join(cert_folder, certificate) | |||
return context | |||
def create_certificates(): | |||
cmd = """openssl req \ | |||
-new \ | |||
-newkey rsa:4096 \ | |||
-days 365 \ | |||
-nodes \ | |||
-x509 \ | |||
-subj "/C=US/ST=State/L=City/O=Company/CN=%s" \ | |||
-keyout /etc/ssl/private/private.key \ | |||
-out /etc/ssl/certs/certificate.crt""".format(os.environ['domain']) | |||
subprocess.call(cmd, shell=True) | |||
return { | |||
'server_name': os.environ['server_name'], | |||
def get_ssl_context(environ): | |||
domain = environ['domain'] | |||
nginx_info = { | |||
'domain': domain, | |||
'dhparam': False, | |||
'ssl_trusted_certificate': False | |||
} | |||
dhparam = os.path.join('/certificates', domain + '.dhparam.pem') | |||
if os.path.exists(dhparam): | |||
nginx_info['dhparam'] = True | |||
copy(source=dhparam, destination='/etc/ssl/certs', basename='dhparam.pem', mode='0644') | |||
trusted_certificates = os.path.join('/certificates', domain + '.ca.crt') | |||
if os.path.exists(trusted_certificates): | |||
nginx_info['ssl_trusted_certificate'] = True | |||
copy(source=trusted_certificates, destination='/etc/ssl/certs', basename='ca.crt', mode='0644') | |||
return nginx_info | |||
def get_certificates(domain): | |||
private_key = os.path.join('/certificates', domain + '.key') | |||
certificate = os.path.join('/certificates', domain + '.crt') | |||
if not os.path.exists(private_key) or not os.path.exists(certificate): | |||
cmd = """openssl req \ | |||
-new \ | |||
-newkey rsa:4096 \ | |||
-days 365 \ | |||
-nodes \ | |||
-x509 \ | |||
-subj "/C=US/ST=State/L=City/O=Company/CN={}" \ | |||
-keyout {} \ | |||
-out {}""".format(domain, private_key, certificate) | |||
subprocess.call(cmd, shell=True) | |||
return private_key, certificate | |||
if __name__ == "__main__": | |||
if 'private_key' in os.environ and 'certificate' in os.environ: | |||
context = copy_certificates() | |||
else: | |||
context = create_certificates() | |||
template('/backend.conf.j2', context, '/etc/nginx/conf.d/backend.conf') | |||
pk, crt = get_certificates(os.environ['domain']) | |||
copy(source=pk, destination='/etc/ssl/private', basename='private.key', mode='0600') | |||
copy(source=crt, destination='/etc/ssl/certs', basename='certificate.crt', mode='0644') | |||
template('/backend.conf.j2', get_ssl_context(os.environ), '/etc/nginx/conf.d/backend.conf') |