Sign inSign up

jschnabel/nginx

By jschnabel

•Updated 8 months ago

A simple nginx container

Image
Networking
API management
1

10K+

jschnabel/nginx repository overview

⁠jschnabel/docker-nginx

A lightweight, pre-configured nginx container with HTTP 2.0, TLS1.3 and SSL Labs A rating

Current Version:

Development Version:

  • Built on the lightweight and secure Alpine Linux distribution
  • Very small Docker image size (+/- 8MB)
  • Optimized for rapid delivery of static content and proxied content from downstream web applications.
  • Secure configuration with pre-configured, optimized TLS settings
  • Pre-defined DSGVO-compliant log rotation settings with 7-day retention of access logs.

⁠What is nginx?

Nginx is a web server which can also be used as a reverse proxy, load balancer, mail proxy and HTTP cache. (Wikipedia)

⁠Why would you use this image?

With this image you get a preconfigured nginx image. This image provides support for TLS 1.3 and HTTP 2.0.

A secure TLS protected server is started without having to change the configuration. A self-signed certificate is created for this purpose. SSL Labs rates the configuration with an A.

SSL Labs rating

⁠Setup

The easiest way to start the server is the following command.

docker run -d -p 80:80 -p 443:443 jschnabel/nginx

You can also use docker-compose.

services:
   nginx:
     image: jschnabel/nginx
     container_name: nginx
     ports:
       - 80:80
       - 443:443

If now the IP address or domain is accessed with the browser, the test page should be visible.

⁠Hosting some simple static content

To be able to host your own content, just mount a directory under /media/data/webroot.

services:
   nginx:
     image: jschnabel/nginx
     container_name: nginx
     ports:
       - 80:80
       - 443:443	 
     volumes:
       - /media/docker/volumes/nginx/webroot:/media/data/webroot

In this example all data from the host directory /media/docker/volumes/nginx/webroot will be published as content.

⁠Custom SSL Certificate

The configuration shown above will cause a warning window in all browsers. This is due to the self-signed certificate. To get a free certificate from Let's Encrypt you have to do the following. First the certbot must be installed on the host. Then a certificate can be created using the command below. Please make sure that a directory is mounted by the host as webroot.

⁠ACME.sh
acme.sh --issue -d <your.domain> --cert-file /media/docker/volumes/nginx/webroot/cert.pem --key-file /media/docker/volumes/nginx/webroot/key.pem --fullchain-file /media/docker/volumes/nginx/webroot/fullchain.pem --reloadcmd "docker restart nginx"

The program will create the following files.

/media/docker/volumes/nginx/webroot/cert.pem 
/media/docker/volumes/nginx/webroot/key.pem
/media/docker/volumes/nginx/webroot/fullchain.pem

Now the certificate and the private key have to be mounted.

services:
   nginx:
     image: jschnabel/nginx
     container_name: nginx
     ports:
       - 80:80
       - 443:443	 
     volumes:
       - /media/docker/volumes/nginx/webroot:/media/data/webroot
       - /etc/letsencrypt/live/<your.domain>/fullchain.pem:/media/data/certs/default_cert.pem:ro
       - /etc/letsencrypt/live/<your.domain>/privkey.pem:/media/data/certs/default_key.pem:ro
⁠Certbot
certbot certonly --webroot --webroot-path /media/docker/volumes/nginx/webroot --rsa-key-size 4096 --renew-by-default -d <your.domain>

The program will create the following files.

/etc/letsencrypt/live/<your.domain>/fullchain.pem
/etc/letsencrypt/live/<your.domain>/privkey.pem

Now the certificate and the private key have to be mounted.

services:
   nginx:
     image: jschnabel/nginx
     container_name: nginx
     ports:
       - 80:80
       - 443:443	 
     volumes:
       - /media/docker/volumes/nginx/webroot:/media/data/webroot
       - /etc/letsencrypt/live/<your.domain>/fullchain.pem:/media/data/certs/default_cert.pem:ro
       - /etc/letsencrypt/live/<your.domain>/privkey.pem:/media/data/certs/default_key.pem:ro
⁠Custom Config

In order to provide own configurations, these must be simply mounted under the directory /media/data/sites-enabled. All configurations from this directory are activated. In this way several domains can be configured.

services:
   nginx:
     image: jschnabel/nginx
     container_name: nginx
     ports:
       - 80:80
       - 443:443	 
     volumes:
       - /media/docker/volumes/nginx/webroot:/media/data/webroot
       - /etc/letsencrypt/live/<your.domain>/fullchain.pem:/media/data/certs/default_cert.pem:ro
       - /etc/letsencrypt/live/<your.domain>/privkey.pem:/media/data/certs/default_key.pem:ro
       - /media/docker/volumes/nginx/sites:/media/data/sites-enabled
       - /media/docker/volumes/nginx/streams:/media/data/streams

A custom site configuration could look like this. It should be mounted to media/data/sites-enabled.

server {
	listen 80;
	listen [::]:80;
	server_name <your.domain>; 
	
	return 301 https://$host$request_uri;
}

server {
	listen 443 ssl http2;
	listen [::]:443 ssl http2;
	server_name <your.domain>; 
	
	ssl_certificate	 /media/data/certs/<your.domain>.pem;
	ssl_certificate_key /media/data/certs/<your.domain>.pem;

	include /media/data/snippets/gzip.conf;
	include /media/data/snippets/header.conf;
	include /media/data/snippets/tls.conf;
	
	location / {
		root   /media/data/webroot/<your.domain>;
		index  index.html index.htm;
	}

	error_page   500 502 503 504  /50x.html;
	location = /50x.html {
		root   /media/data/webroot/<your.domain>;
	}
}

A custom stream configuration could look like this. It should be mounted to media/data/streams.

stream {
    upstream mqtt {
         server mosquitto:1883;
    }

    server {
        listen                8883 ssl;
        proxy_pass            mqtt;

        ssl_certificate  /media/data/certs/default_cert.pem;
        ssl_certificate_key /media/data/certs/default_key.pem;

        include /media/data/snippets/tls_stream.conf;
    }

    server {
        listen                1883;
        proxy_pass            mqtt;
    }

}
⁠Basic Auth

This image also includes a configuration for Basic-Auth authentication. This can be added as follows.

	location / {
		include /media/data/snippets/basic_auth.conf;
		
		root   /media/data/webroot/<your.domain>;
		index  index.html index.htm;
	}

To add a user, the following command can be used.

docker exec -it nginx_proxy /media/data/scripts/addUser.sh /media/data/passwords/htpasswd
⁠Webdav

There is also a configuration for a WebDav share. It is recommended that such a share is secured by authentication.

	location / {
		include /media/data/snippets/basic_auth.conf;
		include /media/data/snippets/webdav.conf;
	}
⁠Log files

The log files (error and access log) are stored under /media/data/logs by default. This directory can be mounted for external processing of the log files.

⁠How to get a better SSL Labs Grade

If you want a better grade at SSL Labs, the following things have to be done.

⁠Key Exchange 100%

To get a 100% rating in the Key Exchange category it is necessary to use a 4096 bit RSA certificate or an ECDSA certificate with ECDSA P-384 or ECDSA P-521.

With acme.sh you can create such a certificate with 4096 bit RSA if you add the following parameter to the command.

acme.sh --issue --keylength 4096 ..."

To get an ECDSA P-384 certificate the command must be modified as follows.

acme.sh --issue --ecc --keylength ec-384 ..."

Certbot currently does not support ECDSA certificates. However a 4096 bit RSA can be created. Therefore the key length has to be provided.

certbot certonly --rsa-key-size 4096 ...

SSL Labs rating

⁠Cipher Strength 100%

To get 100% in this discipline no cipher suites with 128bit are allowed in the list of cipher suites. A snippet is provided for this purpose. This snippet must be included as shown in the configuration below.

WARNING: This will prevent very old clients from accessing your website (e.g. Java <= 7 or Android <= 6). If you expect clients that fall into this category, I advise against using them.

A custom site configuration could look like this. It should be mounted to media/data/sites-enabled.

server {
	listen 80;
	listen [::]:80;
	server_name <your.domain>; 
	
	return 301 https://$host$request_uri;
}

server {
	listen 443 ssl http2;
	listen [::]:443 ssl http2;
	server_name <your.domain>; 
	
	ssl_certificate	 /media/data/certs/<your.domain>.pem;
	ssl_certificate_key /media/data/certs/<your.domain>.pem;

	include /media/data/snippets/gzip.conf;
	include /media/data/snippets/header.conf;
	include /media/data/snippets/tls_strong.conf;
	
	location / {
		root   /media/data/webroot/<your.domain>;
		index  index.html index.htm;
	}

	error_page   500 502 503 504  /50x.html;
	location = /50x.html {
		root   /media/data/webroot/<your.domain>;
	}
}

SSL Labs rating

⁠How to disable TLS?

Simply add an environment variable named DISABLETLS to the container. The value must be true.

services:
   nginx:
     image: jschnabel/nginx
     container_name: nginx
     environment:
       - DISABLETLS="true"
     ports:
       - 80:80
     volumes:
       - /media/docker/volumes/nginx/webroot:/media/data/webroot

Tag summary

Content type

Image

Digest

sha256:2a39697be…

Size

9.1 MB

Last updated

over 3 years ago

docker pull jschnabel/nginx