Skip to content

Docker Compose installation

Mathieu Rampant edited this page Jun 26, 2025 · 16 revisions

We recommend using docker compose as it greatly simplifies the management and maintenance of docker containers. Docker compose is now part of the docker package, so there is no extra installation steps after installing docker.

Configuration

Given the following directory structure:

|--- docker-compose.yml           # Docker-compose master configuration of all containers
|--- nemo/
|    |--- settings.py             # Nemo settings
|    |--- logs/                   # Nemo logs folder
|--- nginx/
|    |--- nginx.conf              # Nginx configuration
|    |--- server.crt              # Optional certificate
|    |--- server.key              # Optional private key

here is an example of docker-compose.yml:

services:
  nginx:
    container_name: "nginx"
    image: nginx:1.28.0
    ports:
      - "80:80"
    volumes:
      - ./nginx:/etc/nginx
      - ./nemo/static:/etc/nginx/nemo
    restart: always
  nemo:
    container_name: "nemo"
    image: nanofab/nemo:7.1.4
    volumes:
      - ./nemo:/nemo
    restart: unless-stopped

and an example of nginx.conf:

worker_processes auto;
worker_cpu_affinity auto;
events {}

http {
	server_tokens off; # Don't send the nginx version number in error pages and server header
	add_header X-Frame-Options DENY;
	add_header X-Content-Type-Options nosniff;
	add_header X-XSS-Protection "1; mode=block";
	add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;

	# Timeouts, do not keep connections open longer then necessary to reduce resource usage and deny Slowloris type attacks.
	client_body_timeout 4s; # Maximum time between packets the client can pause when sending nginx any data
	client_header_timeout 4s; # Maximum time the client has to send the entire header to nginx
	keepalive_timeout 75s; # Timeout which a single keep-alive client connection will stay open
	send_timeout 24s; # Maximum time between packets nginx is allowed to pause when sending the client data

	log_format meaningful '$remote_addr $request_method $request_uri "$http_user_agent" $http_referer $request_length $bytes_sent $request_time';

	# TLS
	ssl_protocols TLSv1.2 TLSv1.3;
	ssl_prefer_server_ciphers on;
	ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256';
	ssl_session_timeout 1d;
	ssl_session_cache shared:SSL:50m;
	ssl_session_tickets off;

	# HTTPS
	# Uncomment the following lines for HTTPS:
	# ssl_certificate server.crt;
	# ssl_certificate_key server.key;

	# Docker internal DNS address
	resolver 127.0.0.11 ipv6=off;

	types {
		application/javascript js;
		text/css css;
		image/x-icon ico;
		text/plain txt;
		application/json map;
		application/font-woff woff;
		application/font-woff2 woff2;
		application/vnd.ms-fontobject eot;
		application/x-font-ttf ttf;
		image/svg+xml svg;
		image/png png;
	}
	default_type application/octet-stream;

	# NEMO
	server {
		listen 80;
		#server_name ;
		set $upstream http://nemo:8000;

		location / {
			proxy_set_header Host $host;
			proxy_set_header X-Forwarded-Host $server_name;
			proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
			proxy_set_header X-Forwarded-Proto https;
			proxy_set_header X-Real-IP $remote_addr;
			proxy_set_header Connection "";
			proxy_http_version 1.1;
			proxy_pass $upstream;
		}

		# NEMO RESTful API
		location /api {
			proxy_set_header Host $host;
			proxy_set_header X-Forwarded-Host $server_name;
			proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
			proxy_set_header X-Forwarded-Proto https;
			proxy_set_header X-Real-IP $remote_addr;
			proxy_set_header Connection "";
			proxy_http_version 1.1;
			proxy_pass $upstream;
		}

		location = /favicon.ico { alias /etc/nginx/nemo/favicon.ico; }
		location /static { alias /etc/nginx/nemo; }
	}
}

an example of nemo's settings.py can be found here

Usage

run docker compose up -d in the base folder to start everything

(first time only, create a superuser) run docker exec --interactive --tty nemo django-admin createsuperuser

run docker compose down to stop and remove all containers

Remote user authentication setup

NEMO doesn't do authentication, it only deal with authorization, so you will need a way to authenticate users (using LDAP, NEMO-Allauth, or REMOTE-USER authentication).

After installing NEMO and creating a superuser, when testing, you can bypass authentication (or rather force it to authenticate a specific user) by following those steps to configure Remote user authentication:

in settings.py:

  1. make sure you have 'NEMO.middleware.HTTPHeaderAuthenticationMiddleware', in the list of middlewares.
  2. use AUTHENTICATION_BACKENDS = ['NEMO.views.authentication.RemoteUserAuthenticationBackend']
  3. use AUTHENTICATION_HEADER = "AUTHORIZATION"

in nginx.conf:

  • use "proxy_set_header Authorization <your_username>;"

This will tell NEMO that <your_username> is authenticated and log that user in automatically.

In production, you will need to setup Nginx or Apache (or whichever webserver you are using) to do proper authentication and set the Authorization header accordingly.

There are docker images for Nginx for Shibboleth and Kerberos/Spnego:

Clone this wiki locally