Marvin Pascale

[B.Log]

10 Maggio 2023

Nginx proxy manager

Ho già parlato di Nginx proxy manager nel 2021 e, da allora, il progetto si è evoluto e sono nati anche dei fork interessanti.

Avvio

Nginx proxy manager viene distribuito come container docker e sul sito ufficiale è presente uno startup che permette di avviarlo in pochi semplici passi, utilizzando docker compose.

Su un server Linux, creiamo una cartella per contenere i dati (es: /opt/docker/nginx-pm) e posizioniamo al suo interno il file docker-compose.yml

version: '3.8'
services:
  app:
    image: 'jc21/nginx-proxy-manager:latest'
    restart: unless-stopped
    ports:
      - '80:80'
      - '81:81'
      - '443:443'
    volumes:
      - ./data:/data
      - ./letsencrypt:/etc/letsencrypt

a questo punto non ci resta che lanciare

# docker-compose up -d

In questo caso verrà lanciato un solo container e i dati di gestione verranno salvato su un db sqlite. All’avvio verranno create le cartelle di configurazione e persistenza dei dati del container.

Se tutto è andato per il meglio alla pagina

_http://[IPHOST]:81/

vedrete la pagina di login.

Nginx PM Login

Le credenziali di accesso di default

Email:    [email protected]
Password: changeme

Tutto bello e nella maggior parte dei casi sarete a posto, ma se vi serve qualcosa di più performante potete decidere di separare il db ed avviare quindi due container.

version: '3.8'
services:
  app:
    image: 'jc21/nginx-proxy-manager:latest'
    restart: unless-stopped
    ports:
      # These ports are in format <host-port>:<container-port>
      - '80:80' # Public HTTP Port
      - '443:443' # Public HTTPS Port
      - '81:81' # Admin Web Port
      # Add any other Stream port you want to expose
      # - '21:21' # FTP
    environment:
      # Mysql/Maria connection parameters:
      DB_MYSQL_HOST: "db"
      DB_MYSQL_PORT: 3306
      DB_MYSQL_USER: "npm"
      DB_MYSQL_PASSWORD: "npm"
      DB_MYSQL_NAME: "npm"
      # Uncomment this if IPv6 is not enabled on your host
      # DISABLE_IPV6: 'true'
    volumes:
      - ./data:/data
      - ./letsencrypt:/etc/letsencrypt
    depends_on:
      - db

  db:
    image: 'jc21/mariadb-aria:latest'
    restart: unless-stopped
    environment:
      MYSQL_ROOT_PASSWORD: 'npm'
      MYSQL_DATABASE: 'npm'
      MYSQL_USER: 'npm'
      MYSQL_PASSWORD: 'npm'
    volumes:
      - ./mysql:/var/lib/mysql

Più sicurezza

Uno dei fork che ho apprezzato di più è quello fatto da baudneo che aggiunge funzionalità molto interessanti.

Potremmo avere modsec abilitato e funzionante oltre che un bouncer pronto per Crowdsec.

version: "3"
services:
  app:
    image: 'baudneo/nginx-proxy-manager:bullseye'
    restart: unless-stopped
    ports:
      # These ports are in format <host-port>:<container-port>
      - '80:80' # Public HTTP Port
      - '443:443' # Public HTTPS Port
      - '81:81' # Admin Web Port
      # Add any other Stream port you want to expose
      # - '21:21' # FTP

    # Uncomment the next line if you uncomment anything in the section
    environment:
      # Uncomment this if you want to change the location of
      # the SQLite DB file within the container
      # DB_SQLITE_FILE: "/data/database.sqlite"
      TZ: "Europe/Rome"
      ADMIN_PANEL_LOG: "1"
      CROWDSEC_BOUNCER: "1"
      OPENRESTY_DEBUG: "0"
      MODSEC_CREATE: "1"

      CROWDSEC_LAPI: "http://172.17.0.1:8080"
      CROWDSEC_KEY: "[CROWDSEC-API-KEY-FOR-BOUNCER]"
      CROWDSEC_RECAP_SECRET: "[GOOGLE-SECRET]"
      CROWDSEC_RECAP_SITE: "{[GOOGLE-SITE]}"

      # Uncomment this if IPv6 is not enabled on your host
      # DISABLE_IPV6: 'true'

    volumes:
      - ./data:/data
      - ./letsencrypt:/etc/letsencrypt

Ho già parlato nel dettaglio di entrambe le soluzioni per cui non starò a ripetere.

Accorgimenti

Una cosa che faccio sempre è permettere l’accesso in chiaro solo in localhost

...
- '80:80' # Public HTTP Port
- '443:443' # Public HTTPS Port
- '127.0.0.1:81:81' # Admin Web Port
...

e successivamente creo un proxy per esporre il pannello in https.

Altro accorgimento che ritengo molto importante è l’aggiunta del health check

....
    healthcheck:
      test: ["CMD", "curl", "localhost"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 30s
...

Questo permetterà a docker di capire se il nostro container sta funzionando nel modo corretto e se necessario, riavviarlo.


Le opinioni in quanto tali sono opinabili e nulla ti vieta di approfondire l’argomento.

Risorse: