DockerTut's Linux

[docker-compose] Traefik, nginx et Nextcloud

Objectif de l’article : obtenir un serveur Nextcloud derrière Nginx et le reverse-proxy Traefik. La configuration HTTPS effectuée par le fichier « traefik_dynamic.toml » et les labels correspondants.

  • Mise à jour le 04/07/2020 : ajout des configurations en .yml pour Traefik
  • Mise à jour le 20/07/2020 : suppression des fichiers .toml, mise à jour intégrale des fichiers (ajout des manquants), ajout de quelques commentaires et précisions quant à la mise en place
  • Mise à jour le 12/08/2020 : correction du montage du dossier de configuration nginx + suppression des labels « container_name »

Logiciels exploités :

  • Ubuntu 18.04 LTS
  • Docker CE = 19.03.8
  • Docker-compose = 1.25.4
  • Traefik = 2.3 « picodon »
  • Nginx = 1.19.x « alpine » (version stable)
  • MariaDB = 10.15
  • Nextcloud =  19.0.4
  • PHP = 7.3.16-fpm « alpine »
  • Redis = 6

J’utilise le dossier /srv/docker pour mettre en place ces conteneurs. Libre à vous de modifier l’emplacement. A l’intérieur de ce dossier, plusieurs choses sont faites : création des dossiers nécessaires (conf, conf/traefikdynamic, logs, fichier acme.json (pour Let’s Enycrypt)

mkdir -p /srv/docker/conf/traefikdynamic
mkdir /srv/docker/conf/nginx-nextcloud
mkdir /srv/docker/logs
touch /srv/docker/logs/traefik.log
touch /srv/docker/conf/acme.json
chmod 0600 /srv/docker/conf/acme.json

Fichier « traefik.yml » (/srv/docker/conf/traefik.yml)

global:
  sendAnonymousUsage: false
  checkNewVersion: false

api:
  #insecure: true
  dashboard: true
  #debug: true

log:
  filePath: "/etc/traefik/applog.log"
  level: INFO

providers:
  docker:
    endpoint: unix:///var/run/docker.sock
    exposedByDefault: false
    watch: true
    swarmMode: false

  file:
    directory: /traefikdynamic
    watch: true

entryPoints:
  web:
    address: ":80"
    http:
      redirections:
        entryPoint:
          to: websecure
          scheme: https
  websecure:
    address: ":443"

certificatesResolvers:
  letsencrypt:
    acme:
      email: [email protected]
#      caServer: https://acme-staging-v02.api.letsencrypt.org/directory
      caServer: https://acme-v02.api.letsencrypt.org/directory
      storage: acme.json
      keyType: EC256
      httpChallenge:
        entryPoint: web

Fichier « traefik_dynamic.yml » (/srv/docker/conf/traefikdynamic/traefik_dynamic.yml)

tls:
  options:
    default:
      minVersion: VersionTLS12
      sniStrict: true
      cipherSuites:
        - TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
        - TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
        - TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305
        - TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
        - TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
        - TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305
        - TLS_AES_128_GCM_SHA256
        - TLS_AES_256_GCM_SHA384
        - TLS_CHACHA20_POLY1305_SHA256
      curvePreferences:
        - CurveP521
        - CurveP384

http:
  middlewares:
    compression:
      compress:
        excludedContentTypes:
          - text/event-stream

    security:
      headers:
        accessControlAllowMethods:
          - GET
          - OPTIONS
          - PUT
        #accessControlAllowOriginList = "*"
        accessControlMaxAge: 100
        addVaryHeader: true
        browserXssFilter: true
        contentTypeNosniff: true
        forceSTSHeader: true
        frameDeny: true
        sslRedirect: true
        sslForceHost: true
        stsPreload: true
        #ContentSecurityPolicy = "default-src 'self' 'unsafe-inline'"
        customFrameOptionsValue: SAMEORIGIN
        referrerPolicy: same-origin
        featurePolicy: vibrate 'self'
        stsSeconds: 315360000

    authentification:
      basicAuth:
        users: # admon / totolasticot
        - admon:$2y$10$4IgUsvlCwENsF18B9t7AoegQ7eWZVfWxPFRhNfBWz7F00h1X2oZFe

Ci-dessous le fichier docker-compose :

---
version: '3.6'
services:
  traefik:
    image: traefik:${TRAEFIKVERSION}
    restart: unless-stopped
    ports:
      - 80:80
      - 443:443
      - 8080:8080 # used to have the traefik dashboard
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - ./conf/traefik.yml:/etc/traefik/traefik.yml:ro
      - ./conf/traefikdynamic:/traefikdynamic:ro
      - ./logs/traefik.log:/etc/traefik/applog.log
      - ./conf/acme.json:/acme.json

  nginxnextcloud:
    image: nginx:${NGINXVERSION}
    restart: unless-stopped
    container_name: nginxnextcloud
    volumes:
      - datanextcloud:/var/www/html
      - datanginxnextcloudlogs:/var/log/nginx
      - ./conf/nginx-nextcloud:/etc/nginx
    labels:
      traefik.enable: true
      traefik.http.routers.nginxnextcloud-https.entrypoints: "websecure"
      traefik.http.routers.nginxnextcloud-https.rule: "Host(`nextcloud.czs.local`)"
      traefik.http.routers.nginxnextcloud-https.middlewares: "[email protected], [email protected]"
      traefik.http.routers.nginxnextcloud-https.tls: "true"
      traefik.http.routers.nginxnextcloud-https.tls.certresolver: "letsencrypt"

  nextcloud:
    image: nextcloud:${NEXTCLOUDVERSION}
    restart: unless-stopped
    container_name: nextcloudfpm
    volumes:
      - datanextcloud:/var/www/html
    environment:
      MYSQL_HOST: sqlnextcloud
      MYSQL_USER: ${MYSQLUSER}
      MYSQL_PASSWORD: ${MYSQLPASSWORD}
      MYSQL_DATABASE: ${MYSQLDB}
      REDIS_HOST: redisnextcloud
    links:
      - mariadb
    labels:
      traefik.enable: false

  mariadb:
    image: mariadb:${MARIADBVERSION}
    command: --transaction-isolation=READ-COMMITTED --binlog-format=ROW
    restart: unless-stopped
    container_name: sqlnextcloud
    volumes:
      - datadbnextcloud:/var/lib/mysql
    environment:
      MYSQL_RANDOM_ROOT_PASSWORD: '1'
      MYSQL_USER: ${MYSQLUSER}
      MYSQL_PASSWORD: ${MYSQLPASSWORD}
      MYSQL_DATABASE: ${MYSQLDB}
    labels:
      traefik.enable: false

  redis:
    image: redis:${REDISVERSION}
    restart: unless-stopped
    volumes:
      - dataredisnextcloud:/data
    labels:
      traefik.enable: false

volumes:
  datanextcloud:
  datadbnextcloud:
  datanginxnextcloudlogs:
  dataredisnextcloud:

Le fichier de variables d’environnement (à mettre à la racine, dans /srv/docker, à côté du fichier docker-compose.yml en somme)

MYSQLUSER=nextcloudsqluser
MYSQLPASSWORD=nextcloudsqlpassword
MYSQLDB=nextclouddb
NEXTCLOUDVERSION=20-fpm-alpine
MARIADBVERSION=focal
REDISVERSION=6
NGINXVERSION=stable-alpine
TRAEFIKVERSION=picodon

Fichiers de configuration pour nginx/nextcloud :

nginx.conf (/srv/docker/conf/nginx-nextcloud/nginx.conf)

worker_processes auto; # use "grep processor /proc/cpuinfo | wc -l" and type the number here, or stay with automatic configuration

error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;

events {
    worker_connections  1024; # use "ulimit -n" and type the number here
}

http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile        on;
    #tcp_nopush     on;
    server_tokens   off;
    keepalive_timeout  65;

    set_real_ip_from  10.0.0.0/8;
    set_real_ip_from  172.16.0.0/12;
    set_real_ip_from  192.168.0.0/16;
    real_ip_header    X-Real-IP;

    upstream php-handler {
        server nextcloudfpm:9000;
    }

    server {
        listen 80;

        add_header Referrer-Policy "no-referrer" always;
        add_header X-Content-Type-Options "nosniff" always;
        add_header X-Download-Options "noopen" always;
        add_header X-Frame-Options "SAMEORIGIN" always;
        add_header X-Permitted-Cross-Domain-Policies "none" always;
        add_header X-Robots-Tag "none" always;
        add_header X-XSS-Protection "1; mode=block" always;

        fastcgi_hide_header X-Powered-By;

        root /var/www/html;

        location = /robots.txt {
            allow all;
            log_not_found off;
            access_log off;
        }

        location = /.well-known/carddav {
            return 301 $scheme://$host:$server_port/remote.php/dav;
        }

        location = /.well-known/caldav {
            return 301 $scheme://$host:$server_port/remote.php/dav;
        }

        client_max_body_size 10G;
        fastcgi_buffers 64 4K;

        gzip on;
        gzip_vary on;
        gzip_comp_level 4;
        gzip_min_length 256;
        gzip_proxied expired no-cache no-store private no_last_modified no_etag auth;
        gzip_types application/atom+xml application/javascript application/json application/ld+json application/manifest+json application/rss+xml application/vnd.geo+json application/vnd.ms-fontobject application/x-font-ttf application/x-web-app-manifest+json application/xhtml+xml application/xml font/opentype image/bmp image/svg+xml image/x-icon text/cache-manifest text/css text/plain text/vcard text/vnd.rim.location.xloc text/vtt text/x-component text/x-cross-domain-policy;

        location / {
            rewrite ^ /index.php;
        }

        location ~ ^\/(?:build|tests|config|lib|3rdparty|templates|data)\/ {
            deny all;
        }
        location ~ ^\/(?:\.|autotest|occ|issue|indie|db_|console) {
            deny all;
        }

        location ~ ^\/(?:index|remote|public|cron|core\/ajax\/update|status|ocs\/v[12]|updater\/.+|oc[ms]-provider\/.+)\.php(?:$|\/) {
            fastcgi_split_path_info ^(.+?\.php)(\/.*|)$;
            set $path_info $fastcgi_path_info;
            try_files $fastcgi_script_name =404;
            include fastcgi.conf;
            fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
            fastcgi_param PATH_INFO $path_info;
            fastcgi_param HTTPS on;
            fastcgi_param modHeadersAvailable true;
            fastcgi_param front_controller_active true;
            fastcgi_pass php-handler;
            fastcgi_intercept_errors on;
            fastcgi_request_buffering off;
            fastcgi_read_timeout 600;
        }

        location ~ ^\/(?:updater|oc[ms]-provider)(?:$|\/) {
            try_files $uri/ =404;
            index index.php;
        }

        location ~ \.(?:css|js|woff2?|svg|gif|map)$ {
            try_files $uri /index.php$request_uri;
            add_header Cache-Control "public, max-age=15778463";
            add_header Referrer-Policy "no-referrer" always;
            add_header X-Content-Type-Options "nosniff" always;
            add_header X-Download-Options "noopen" always;
            add_header X-Frame-Options "SAMEORIGIN" always;
            add_header X-Permitted-Cross-Domain-Policies "none" always;
            add_header X-Robots-Tag "none" always;
            add_header X-XSS-Protection "1; mode=block" always;
            access_log off;
        }

        location ~ \.(?:png|html|ttf|ico|jpg|jpeg|bcmap|mp4|webm)$ {
            try_files $uri /index.php$request_uri;
            access_log off;
        }
    }
}

mime.types (/srv/docker/conf/nginx-nextcloud/mime.types)

types {
  text/html                             html htm shtml;
  text/css                              css;
  text/xml                              xml rss;
  image/gif                             gif;
  image/jpeg                            jpeg jpg;
  image/svg+xml                         svg svgz;
  application/x-javascript              js;
  text/plain                            txt;
  text/x-component                      htc;
  text/mathml                           mml;
  image/png                             png;
  image/x-icon                          ico;
  image/x-jng                           jng;
  image/vnd.wap.wbmp                    wbmp;
  application/java-archive              jar war ear;
  application/mac-binhex40              hqx;
  application/pdf                       pdf;
  application/x-cocoa                   cco;
  application/x-java-archive-diff       jardiff;
  application/x-java-jnlp-file          jnlp;
  application/x-makeself                run;
  application/x-perl                    pl pm;
  application/x-pilot                   prc pdb;
  application/x-rar-compressed          rar;
  application/x-redhat-package-manager  rpm;
  application/x-sea                     sea;
  application/x-shockwave-flash         swf;
  application/x-stuffit                 sit;
  application/x-tcl                     tcl tk;
  application/x-x509-ca-cert            der pem crt;
  application/x-xpinstall               xpi;
  application/zip                       zip;
  application/octet-stream              deb;
  application/octet-stream              bin exe dll;
  application/octet-stream              dmg;
  application/octet-stream              eot;
  application/octet-stream              iso img;
  application/octet-stream              msi msp msm;
  audio/mpeg                            mp3;
  audio/x-realaudio                     ra;
  video/mpeg                            mpeg mpg;
  video/quicktime                       mov;
  video/x-flv                           flv;
  video/x-msvideo                       avi;
  video/x-ms-wmv                        wmv;
  video/x-ms-asf                        asx asf;
  video/x-mng                           mng;
}

fastcgi.conf (/srv/docker/conf/nginx-nextcloud/fastcgi.conf)

fastcgi_param  SCRIPT_FILENAME    $document_root$fastcgi_script_name;
fastcgi_param  QUERY_STRING       $query_string;
fastcgi_param  REQUEST_METHOD     $request_method;
fastcgi_param  CONTENT_TYPE       $content_type;
fastcgi_param  CONTENT_LENGTH     $content_length;
fastcgi_param  SCRIPT_NAME        $fastcgi_script_name;
fastcgi_param  REQUEST_URI        $request_uri;
fastcgi_param  DOCUMENT_URI       $document_uri;
fastcgi_param  DOCUMENT_ROOT      $document_root;
fastcgi_param  SERVER_PROTOCOL    $server_protocol;
fastcgi_param  GATEWAY_INTERFACE  CGI/1.1;
fastcgi_param  SERVER_SOFTWARE    nginx/$nginx_version;
fastcgi_param  REMOTE_ADDR        $remote_addr;
fastcgi_param  REMOTE_PORT        $remote_port;
fastcgi_param  SERVER_ADDR        $server_addr;
fastcgi_param  SERVER_PORT        $server_port;
fastcgi_param  SERVER_NAME        $server_name;

fastcgi_param  REDIRECT_STATUS    200;

Avec toute cette configuration, désormais, vous êtes en mesure d’avoir votre serveur Nextcloud derrière Traefik, en SSL (automatique) et avec une « empreinte logicielle » la plus faible possible !

Vous pouvez retrouver l’intégralité des scripts sur le GitHub à cette adresse.

Qu'en pensez-vous ?

Woaw !
0
Content
0
In Love
0
Incertain
0
Bercé par l'informatique depuis mon plus jeune âge, je transforme ma passion en expertise.

Leave a reply

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *

You may also like

More in:Docker

0 %