Migration to Traefik with Nextcloud/LinuxServer image: need help!

I have been trying to setup my Nextcloud behind the Traefik Reverse Proxy with Let’s Encrypt enabled. It worked fine with the nginx proxy of the LinuxServer/SWAG container.

At this point the Nextcloud site gives me a “404 page not found” message. I’ll share what I think are the relevant bits of my configuration.

docker-compose.yml

# Traefik
  Traefik:
    container_name: traefik
    image: traefik:v2.2
    restart: always
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - ${APPDATA}/Traefik/traefik.toml:/traefik.toml
      - ${APPDATA}/Traefik/traefik_dynamic.toml:/traefik_dynamic.toml
      - ${APPDATA}/Traefik/acme.json:/acme.json
      - ${APPDATA}/Traefik/traefik.log:/traefik.log
    ports:
      - 82:80
      - 446:443
      - 9999:9999
    networks:
      - web

# Nextcloud
  nextcloud:
    container_name: nextcloud
    image: linuxserver/nextcloud
    restart: always
    environment:
      - PUID=${PUID}
      - PGID=${PGID}
      - TZ=${TZ}
    volumes:
      - ${APPDATA}/Nextcloud:/config
      - ${NEXTCLOUD}:/data
      - ${DOWNLOADS}:/extern/downloads
      - ${MEDIA}:/extern/mediabieb
      - ${PERSOONLIJK}:/extern/persoonlijk
      - ${UPLOADMAP}:/extern/uploadmap
      - ${WATCHED}:/extern/watched
    depends_on:
      - mariadb
    labels:
      - "traefik.enable=true"
      - "traefik.port=80"
      - "traefik.docker.network=webproxy"
      # Entrypoint and TLS
      - "traefik.http.routers.cloud.entrypoints=websecure"
      - "traefik.http.routers.cloud.rule=Host(`[REDACTED]`)"
      - "traefik.http.routers.cloud.tls.certresolver=lets-encrypt"
      # Middlewares:
      - "traefik.http.routers.cloud.middlewares=cloud@docker,cloud-dav@docker"
      # Middleware cloud adds additional headers:
      - "traefik.http.middlewares.cloud.headers.customFrameOptionsValue=SAMEORIGIN"
      - "traefik.http.middlewares.cloud.headers.framedeny=true"
      - "traefik.http.middlewares.cloud.headers.sslredirect=true"
      - "traefik.http.middlewares.cloud.headers.stsIncludeSubdomains=true"
      - "traefik.http.middlewares.cloud.headers.stsPreload=true"
      - "traefik.http.middlewares.cloud.headers.stsSeconds=15552000"
      # Middleware cloud-dav replaces .well-known paths for caldav and carddav with proper nextcloud path
      - "traefik.http.middlewares.cloud-dav.replacepathregex.regex=^/.well-known/ca(l|rd)dav"
      - "traefik.http.middlewares.cloud-dav.replacepathregex.replacement=/remote.php/dav/"
    networks:
      - web
      - internal
  mariadb:
    container_name: nextclouddb
    image: linuxserver/mariadb
    restart: always
    environment:
      - PUID=${PUID}
      - PGID=${PGID}
      - TZ=${TZ}
      - MYSQL_ROOT_PASSWORD=${NCDBROOTPASS}
      - MYSQL_DATABASE=${NCDBNAME}
      - MYSQL_USER=${NCDBUSER}
      - MYSQL_PASSWORD=${NCDBPASS}
    volumes:
      - ${APPDATA}/Nextclouddb:/config
    networks:
      - internal

networks:
  web:
    driver: bridge
    external: true
  internal:
    external: false

traefik.toml

[log]
  level = "ERROR"
  filePath = "/traefik.log"

[api]
  dashboard = true

[providers]
  [providers.docker]
    watch = true
    network = "web"
    exposedbydefault = false
  [providers.file]
    filename = "traefik_dynamic.toml"

[certificatesResolvers.lets-encrypt.acme]
  email = "[REDACTED]"
  storage = "acme.json"
  [certificatesResolvers.lets-encrypt.acme.tlsChallenge]

[entryPoints]
  [entryPoints.web]
    address = ":80"
    [entryPoints.web.http.redirections.entryPoint]
      to = "websecure"
      scheme = "https"

  [entryPoints.websecure]
    address = ":443"

traefik_dynamic.toml

[http.middlewares.simpleAuth.basicAuth]
  users = [
    "[REDACTED]"
  ]

[http.routers.api]
  rule = "Host(`[REDACTED]`)"
  entrypoints = ["websecure"]
  middlewares = ["simpleAuth"]
  service = "api@internal"
  [http.routers.api.tls]
    certResolver = "lets-encrypt"

[http.services]
    [http.services.jellyfin-svc]
      [[http.services.jellyfin-svc.loadBalancer.servers]]
        url = "http://192.168.1.100:8096"
[tls.options]
  [tls.options.default]
    sniStrict = true
    minVersion = "VersionTLS12"
    curvePreferences = [
      "secp521r1",
      "secp384r1"
    ]
    cipherSuites = [
      "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",
      "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
      "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305",
      "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305",
      "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
      "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
      "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256",
      "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256"
    ]
    [tls.options.mintls13]
      minVersion = "VersionTLS13"

Nextcloud/nginx/nginx.conf

## Version 2018/08/16 - Changelog: https://github.com/linuxserver/docker-baseimage-alpine-nginx/commits/master/root/defaults/nginx.conf

user abc;
worker_processes 4;
pid /run/nginx.pid;
include /etc/nginx/modules/*.conf;

events {
	worker_connections 768;
	# multi_accept on;
}

http {

	##
	# Basic Settings
	##

	sendfile on;
	tcp_nopush on;
	tcp_nodelay on;
	keepalive_timeout 65;
	types_hash_max_size 2048;
	# server_tokens off;

	# server_names_hash_bucket_size 64;
	# server_name_in_redirect off;

	client_max_body_size 0;

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

	##
	# Logging Settings
	##

	access_log /config/log/nginx/access.log;
	error_log /config/log/nginx/error.log;

	##
	# Gzip Settings
	##

	gzip on;
	gzip_disable "msie6";

	# gzip_vary on;
	# gzip_proxied any;
	# gzip_comp_level 6;
	# gzip_buffers 16 8k;
	# gzip_http_version 1.1;
	# gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;

	##
	# nginx-naxsi config
	##
	# Uncomment it if you installed nginx-naxsi
	##

	#include /etc/nginx/naxsi_core.rules;

	##
	# nginx-passenger config
	##
	# Uncomment it if you installed nginx-passenger
	##

	#passenger_root /usr;
	#passenger_ruby /usr/bin/ruby;

	##
	# Virtual Host Configs
	##
	include /etc/nginx/conf.d/*.conf;
	include /config/nginx/site-confs/*;
  
}


#mail {
#	# See sample authentication script at:
#	# http://wiki.nginx.org/ImapAuthenticateWithApachePhpScript
#
#	# auth_http localhost/auth.php;
#	# pop3_capabilities "TOP" "USER";
#	# imap_capabilities "IMAP4rev1" "UIDPLUS";
#
#	server {
#		listen     localhost:110;
#		protocol   pop3;
#		proxy      on;
#	}
#
#	server {
#		listen     localhost:143;
#		protocol   imap;
#		proxy      on;
#	}
#}
daemon off;

Two other relevant files I have edited along the way.

In this file I removed basically everything referencing 443:

Nextcloud/nginx/site-confs/default

server {
    listen 80;
    add_header X-Content-Type-Options nosniff;
    add_header X-XSS-Protection "1; mode=block";
    add_header X-Robots-Tag none;
    add_header X-Download-Options noopen;
    add_header X-Permitted-Cross-Domain-Policies none;
    add_header Referrer-Policy no-referrer;
    add_header Feature-Policy "geolocation 'self'";

    root /var/www/html;

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

Here I changed the trusted proxy from letsencrypt to traefik.

Just the relevant parts from: Nextcloud/www/nextcloud/config/config.php

  'memcache.local' => '\\OC\\Memcache\\APCu',
  'datadirectory' => '/data',
  'instanceid' => '[REDACTED]',
  'trusted_proxies' => 
  array (
    0 => 'traefik',
  ),
  'overwrite.cli.url' => 'https://[REDACTED]',
  'overwritehost' => '[REDACTED]',
  'overwriteprotocol' => 'https',
  'trusted_domains' => 
  array (
    0 => '[REDACTED]',
  ),

Please someone! Spot my mistake! @Reiner_Nippes seems to be an expert on this so I’ll just boldly tag you here (:

All the best,

well. let’s start with the best tutorial I could find up to now.

using this as an example I clean my playbook and only this labels are left for the nginx container:

    labels:
      traefik.enable: "true"
      traefik.http.routers.nginx.entrypoints: "web-secure"
      traefik.http.routers.nginx.rule: "Host(`{{ nextcloud_server_fqdn }}`)"
      traefik.http.routers.nginx.middlewares: "nextcloud@file,nextcloud-redirect@file"
      traefik.http.routers.nginx.service: "nginx"
      traefik.http.services.nginx.loadbalancer.server.port: "80"

the permanent redirection http->https, security heades and the .wellknown stuff went to dynamik.yml.

if you follow this it’s super easy to add other container. because you only need these six labels. just look at the protainer and adminer container.

sure that is will work since traefik listens to port 82/446?

I don’t use a separate nginx container, will that be a problem?

I tried. It did not work: “too many redirects” is now the error in the browser. Other containers do work with this configuration.

Here we go:

docker-compose.yml

# Traefik
  Traefik:
    container_name: traefik
    image: traefik:latest
    restart: always
    security_opt:
      - no-new-privileges:true
    volumes:
      - /etc/localtime:/etc/localtime:ro
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - ${APPDATA}/Traefik/traefik.yml:/traefik.yml
      - ${APPDATA}/Traefik/dynamic.yml:/dynamic.yml
      - ${APPDATA}/Traefik/acme.json:/acme.json:ro
      - ${APPDATA}/Traefik/traefik.log:/traefik.log
    labels:
      - "traefik.enable=true"
      - "traefik.docker.network=proxy"
      - "traefik.http.routers.traefik-secure.entrypoints=websecure"
      - "traefik.http.routers.traefik-secure.rule=Host(`${TTDOMAIN}`)"
      - "traefik.http.routers.traefik-secure.service=api@internal"
      - "traefik.http.routers.traefik-secure.middlewares=user-auth@file"
    ports:
      - 82:80
      - 446:443
    networks:
      - proxy

# Nextcloud
  nextcloud:
    container_name: nextcloud
    image: linuxserver/nextcloud
    restart: always
    environment:
      - PUID=${PUID}
      - PGID=${PGID}
      - TZ=${TZ}
    volumes:
      - ${APPDATA}/Nextcloud:/config
      - ${NEXTCLOUD}:/data
      - ${DOWNLOADS}:/extern/downloads
      - ${MEDIA}:/extern/mediabieb
      - ${PERSOONLIJK}:/extern/persoonlijk
      - ${UPLOADMAP}:/extern/uploadmap
      - ${WATCHED}:/extern/watched
    depends_on:
      - mariadb
    labels:
      - "traefik.enable=true"
      - "traefik.docker.network=proxy"
      - "traefik.http.routers.nextcloud-secure.entrypoints=websecure"
      - "traefik.http.routers.nextcloud-secure.rule=Host(`${NCTDOMAIN}`)"
    networks:
      - proxy
      - nextcloud_net
  mariadb:
    container_name: nextclouddb
    image: linuxserver/mariadb
    restart: always
    environment:
      - PUID=${PUID}
      - PGID=${PGID}
      - TZ=${TZ}
      - MYSQL_ROOT_PASSWORD=${NCDBROOTPASS}
      - MYSQL_DATABASE=${NCDBNAME}
      - MYSQL_USER=${NCDBUSER}
      - MYSQL_PASSWORD=${NCDBPASS}
    volumes:
      - ${APPDATA}/Nextclouddb:/config
    networks:
      - nextcloud_net

networks:
  proxy:
    driver: bridge
    external: true
  nextcloud_net:
    external: false

traefik.yml

api:
  dashboard: true

log:
  level: ERROR
  filepath: traefik.log

entryPoints:
  web:
    address: :80
    http:
      redirections:
        entryPoint:
          to: websecure

  websecure:
    address: :443
    http:
      middlewares:
        - secureHeaders@file
      tls:
        certResolver: letsencrypt

providers:
  docker:
    endpoint: "unix:///var/run/docker.sock"
    exposedByDefault: false
  file:
    filename: dynamic.yml

certificatesResolvers:
  letsencrypt:
    acme:
      email: [REDACTED]
      storage: acme.json
      keyType: EC384
      httpChallenge:
        entryPoint: web

dynamic.yml

http:
  middlewares:
    secureHeaders:
      headers:
        sslRedirect: true
        forceSTSHeader: true
        stsIncludeSubdomains: true
        stsPreload: true
        stsSeconds: 31536000

    user-auth:
      basicAuth:
        users:
          - "[REDACTED]"

tls:
  options:
    default:
      cipherSuites:
        - TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
        - TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
        - TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
        - TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
        - TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305
        - TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305
      minVersion: VersionTLS12

I changed this back because I got a 404 error.

Nextcloud/nginx/site-confs/default

upstream php-handler {
    server 127.0.0.1:9000;
}
server {
    listen 80;
    listen [::]:80;
    server_name _;
    return 301 https://$host$request_uri;
}
server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    server_name _;
    ssl_certificate /config/keys/cert.crt;
    ssl_certificate_key /config/keys/cert.key;

    # Add headers to serve security related headers
    # Before enabling Strict-Transport-Security headers please read into this
    # topic first.
    #add_header Strict-Transport-Security "max-age=15768000; includeSubDomains; preload;" always;
    #
    # WARNING: Only add the preload option once you read about
    # the consequences in https://hstspreload.org/. This option
    # will add the domain to a hardcoded list that is shipped
    # in all major browsers and getting removed from this list
    # could take several months.

    add_header X-Content-Type-Options nosniff;
    add_header X-XSS-Protection "1; mode=block";
    add_header X-Robots-Tag none;
    add_header X-Download-Options noopen;
    add_header X-Frame-Options "SAMEORIGIN";
    add_header X-Permitted-Cross-Domain-Policies none;
    add_header Referrer-Policy no-referrer;
    fastcgi_hide_header X-Powered-By;
    root /config/www/nextcloud/;
    # display real ip in nginx logs when connected through reverse proxy via docker network
    set_real_ip_from 172.0.0.0/8;
    real_ip_header X-Forwarded-For;
    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;
    }
    location = /.well-known/webfinger {
      return 301 $scheme://$host:$server_port/public.php?service=webfinger;
    }
    location = /.well-known/host-meta {
      return 301 $scheme://$host:$server_port/public.php?service=host-meta;
    }
    location = /.well-known/host-meta.json {
      return 301 $scheme://$host:$server_port/public.php?service=host-meta-json;
    }
    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\/.+|.+\/richdocumentscode\/proxy)\.php(?:$|\/) {
        fastcgi_split_path_info ^(.+?\.php)(\/.*|)$;
        set $path_info $fastcgi_path_info;
        try_files $fastcgi_script_name =404;
        include /etc/nginx/fastcgi_params;
        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;
    }
    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 headers to serve security related headers
        # Before enabling Strict-Transport-Security headers please read into this
        # topic first.
        #add_header Strict-Transport-Security "max-age=15768000; includeSubDomains; preload;" always;
        #
        # WARNING: Only add the preload option once you read about
        # the consequences in https://hstspreload.org/. This option
        # will add the domain to a hardcoded list that is shipped
        # in all major browsers and getting removed from this list
        # could take several months.
        add_header X-Content-Type-Options nosniff;
        add_header X-XSS-Protection "1; mode=block";
        add_header X-Robots-Tag none;
        add_header X-Download-Options noopen;
        add_header X-Frame-Options "SAMEORIGIN";
        add_header X-Permitted-Cross-Domain-Policies none;
        add_header Referrer-Policy no-referrer;
        access_log off;
    }
    location ~ \.(?:png|html|ttf|ico|jpg|jpeg|bcmap|mp4|webm)$ {
        try_files $uri /index.php$request_uri;
        access_log off;
    }
}

The other files are not changed. Hope you can make something of it.

this should be the network config of traefik. traefik is conected to the external (proxy) network and the internal nextcloud network. nextcloud is only connected to the nextcloud network.

grafik


you miss the middleware, service and loadbalancer.server.port statement. or?

Hm I tried. But still no luck. Now my Let’s Encrypt set up broke down. Every site going through Traefik now get’s an error because the Certificate: TRAEFIK DEFAULT CERT is not the Let’s Encrypt one. Even my monitor site has this error. With the monitor and the other sites I can ‘accept’ this risk and go through, for Nextcloud I cannot.

Isn’t it a problem that I don’t do the separate nginx container? Maybe I need to use a different configuration with that setup?

docker-compose.yml

# Traefik
  Traefik:
    container_name: traefik
    image: traefik:latest
    restart: always
    security_opt:
      - no-new-privileges:true
    volumes:
      - /etc/localtime:/etc/localtime:ro
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - ${APPDATA}/Traefik/traefik.yml:/traefik.yml
      - ${APPDATA}/Traefik/dynamic.yml:/dynamic.yml
      - ${APPDATA}/Traefik/acme.json:/acme.json:ro
      - ${APPDATA}/Traefik/traefik.log:/traefik.log
    labels:
      - "traefik.enable=true"
      - "traefik.docker.network=proxy"
      - "traefik.http.routers.traefik-secure.entrypoints=websecure"
      - "traefik.http.routers.traefik-secure.rule=Host(`${TTDOMAIN}`)"
      - "traefik.http.routers.traefik-secure.service=api@internal"
      - "traefik.http.routers.traefik-secure.middlewares=user-auth@file"
    ports:
      - 82:80
      - 446:443
    networks:
      - proxy
      - nextcloud_net

# Nextcloud
  nextcloud:
container_name: nextcloud
image: linuxserver/nextcloud
restart: always
environment:
  - PUID=${PUID}
  - PGID=${PGID}
  - TZ=${TZ}
volumes:
  - ${APPDATA}/Nextcloud:/config
  - ${NEXTCLOUD}:/data
  - ${DOWNLOADS}:/extern/downloads
  - ${MEDIA}:/extern/mediabieb
  - ${PERSOONLIJK}:/extern/persoonlijk
  - ${UPLOADMAP}:/extern/uploadmap
  - ${WATCHED}:/extern/watched
depends_on:
  - mariadb
labels:
  - "traefik.enable=true"
  - "traefik.docker.network=proxy"
  - "traefik.http.routers.nextcloud-secure.entrypoints=websecure"
  - "traefik.http.routers.nextcloud-secure.rule=Host(`${NCTDOMAIN}`)"
  - "traefik.http.routers.nginx.service=nginx"
  - "traefik.http.services.nginx.loadbalancer.server.port=80"
networks:
  - nextcloud_net
  mariadb:
container_name: nextclouddb
image: linuxserver/mariadb
restart: always
environment:
  - PUID=${PUID}
  - PGID=${PGID}
  - TZ=${TZ}
  - MYSQL_ROOT_PASSWORD=${NCDBROOTPASS}
  - MYSQL_DATABASE=${NCDBNAME}
  - MYSQL_USER=${NCDBUSER}
  - MYSQL_PASSWORD=${NCDBPASS}
volumes:
  - ${APPDATA}/Nextclouddb:/config
networks:
  - nextcloud_net

networks:
  proxy:
    driver: bridge
    external: true
  nextcloud_net:
    external: false

dynamic.yml

http:
  middlewares:
    secureHeaders:
      headers:
        sslRedirect: true
        forceSTSHeader: true
        stsIncludeSubdomains: true
        stsPreload: true
        stsSeconds: 31536000
    nextcloud:
      headers:
        referrerPolicy: "no-referrer"
        browserXSSFilter: true
        contentTypeNosniff: true
        customFrameOptionsValue: "SAMEORIGIN"
    nextcloud-redirect:
        redirectregex:
          permanent: true
          regex: "https://(.*)/.well-known/(card|cal)dav"
          replacement: "https://$1/remote.php/dav"

    user-auth:
      basicAuth:
        users:
          - "[REDACTED]"

tls:
  options:
    default:
      cipherSuites:
        - TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
        - TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
        - TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
        - TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
        - TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305
        - TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305
      minVersion: VersionTLS12

In these lines I changed the three nginx's to nextcloud-secure, nothing changed.

Shit we have another problem at our hands… It is clear why the certificate stuff is not working now. I have to wait another week for those to work? Well, I can still try to fix the reverse proxy in the mean time.

traefik.log
time="2021-01-13T12:21:58+01:00" level=error msg="Unable to obtain ACME certificate for domains \"REDACTED\": unable to generate a certificate for the domains [REDACTED]: acme: error: 429 :: POST :: https://acme-v02.api.letsencrypt.org/acme/new-order :: urn:ietf:params:acme:error:rateLimited :: Error creating new order :: too many certificates already issued for exact set of domains: REDACTED: see https://letsencrypt.org/docs/rate-limits/, url: " routerName=nextcloud-secure@docker rule="Host(REDACTED)" providerName=letsencrypt.acme

Oops, well this is of course not read-only anymore.

Extremely frustrating. I had the whole situation running except Nextcloud, now everything is broken again. I have to wait at least another week to be able to get certificates again…

It shouldn’t be this difficult… Hope someone can still help.

Alright. First I got the rest of my containers working properly again, than I got back to Nextcloud. It feels as if I’m this close.

I am now able to click through in the browser (Chromium) to ‘ignore’ the security threats of the ‘bad’ certificate. Which brings me to another error page: ERR_TOO_MANY_REDIRECTS.

About this

I fixed it by using the staging server.

So let’s take a look at the current configuration.

docker-compose.yml

# Traefik
  Traefik:
    container_name: traefik
    image: traefik:latest
    restart: always
    security_opt:
      - no-new-privileges:true
    volumes:
      - /etc/localtime:/etc/localtime:ro
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - ${APPDATA}/Traefik/traefik.yml:/traefik.yml
      - ${APPDATA}/Traefik/dynamic.yml:/dynamic.yml
      - ${APPDATA}/Traefik/acme.json:/acme.json
      - ${APPDATA}/Traefik/traefik.log:/traefik.log
    labels:
      - "traefik.enable=true"
      - "traefik.docker.network=proxy"
      - "traefik.http.routers.traefik-secure.entrypoints=websecure"
      - "traefik.http.routers.traefik-secure.rule=Host(`${TTDOMAIN}`)"
      - "traefik.http.routers.traefik-secure.service=api@internal"
      - "traefik.http.routers.traefik-secure.middlewares=user-auth@file,secureHeaders@file"
    ports:
      - 82:80
      - 446:443
    networks:
      - proxy
      - nextcloud_net

# Nextcloud
  nextcloud:
    container_name: nextcloud
    image: linuxserver/nextcloud
    restart: always
    environment:
      - PUID=${PUID}
      - PGID=${PGID}
      - TZ=${TZ}
    volumes:
      - ${APPDATA}/Nextcloud:/config
      - ${NEXTCLOUD}:/data
      - ${DOWNLOADS}:/extern/downloads
      - ${MEDIA}:/extern/mediabieb
      - ${PERSOONLIJK}:/extern/persoonlijk
      - ${UPLOADMAP}:/extern/uploadmap
      - ${WATCHED}:/extern/watched
    depends_on:
      - mariadb
    labels:
      - "traefik.enable=true"
      - "traefik.docker.network=proxy"
      - "traefik.http.routers.nextcloud-secure.entrypoints=websecure"
      - "traefik.http.routers.nextcloud-secure.rule=Host(`${NCTDOMAIN}`)"
      - "traefik.http.routers.nextcloud-secure.middlewares=secureHeaders@file,nextcloud-mw@file,nextcloud-redirect@file"
      - "traefik.http.routers.nextcloud-secure.service=nextcloud-secure"
      - "traefik.http.services.nextcloud-secure.loadbalancer.server.port=80"
    networks:
      - nextcloud_net
  mariadb:
    container_name: nextclouddb
    image: linuxserver/mariadb
    restart: always
    environment:
      - PUID=${PUID}
      - PGID=${PGID}
      - TZ=${TZ}
      - MYSQL_ROOT_PASSWORD=${NCDBROOTPASS}
      - MYSQL_DATABASE=${NCDBNAME}
      - MYSQL_USER=${NCDBUSER}
      - MYSQL_PASSWORD=${NCDBPASS}
    volumes:
      - ${APPDATA}/Nextclouddb:/config
    networks:
      - nextcloud_net

networks:
  proxy:
    driver: bridge
    external: true
  nextcloud_net:
    external: false

traefik.yml

log:
  level: ERROR
  filePath: /traefik.log

api:
  dashboard: true

providers:
  docker:
    watch: true
    network: proxy
    exposedbydefault: false
  file:
    filename: dynamic.yml

certificatesResolvers:
  letsencrypt:
    acme:
      email: [REDACTED]
      storage: acme.json
      caServer: 'https://acme-staging-v02.api.letsencrypt.org/directory'
      tlsChallenge: true

entryPoints:
  web:
    address: ':80'
    http:
      redirections:
        entryPoint:
          to: websecure
          scheme: https
  websecure:
    address: ':443'
    http:
      tls:
        certResolver: letsencrypt

dynamic.yml

http:
  middlewares:
    secureHeaders:
      headers:
        customResponseHeaders:
          sslRedirect: true
          forceSTSHeader: true
          stsIncludeSubdomains: true
          stsPreload: true
          stsSeconds: 31536000

    user-auth:
      basicAuth:
        users:
          - '[REDACTED]'

    jellyfin-mw:
      headers:
        customResponseHeaders:
          X-Robots-Tag: "noindex,nofollow,nosnippet,noarchive,notranslate,noimageindex"
          SSLHost: "[REDACTED]"
          SSLForceHost: true
          frameDeny: true
          contentTypeNosniff: true
          browserXSSFilter: true
          customFrameOptionsValue: 'allow-from https://[REDACTED]'

    nextcloud-mw:
      headers:
        customResponseHeaders:
          referrerPolicy: "no-referrer"
          browserXSSFilter: true
          contentTypeNosniff: true
          customFrameOptionsValue: "SAMEORIGIN"
    nextcloud-redirect:
      redirectregex:
        permanent: true
        regex: "https://(.*)/.well-known/(card|cal)dav"
        replacement: "https://$1/remote.php/dav"

  services:
    jellyfin-svc:
      loadBalancer:
        servers:
          - url: 'http://192.168.1.100:8096'
        passHostHeader: true

tls:
  options:
    default:
      sniStrict: true
      minVersion: VersionTLS12
      curvePreferences:
        - secp521r1
        - secp384r1
      cipherSuites:
        - TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
        - TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
        - TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305
        - TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305
        - TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
        - TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
        - TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256
        - TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
    mintls13:
      minVersion: VersionTLS13

i followed all the steps right, right? @Reiner_Nippes . I have no errors in the traefik logs or in the Traefik logs. So, where to look? Maybe the Nextcloud (nginx) config?

All the best,

just guessing. is the endpoint: in your providers missing?

grafik

did you use DEBUG loglevel to see what traefik ist doing?

I have included the docker socket in the docker-compose file. In the traefik.yml. it is a default value, not necessary to define.

Also, the problem is really with the Nextcloud container specifically, not with the other ones, and they also run via docker, so that must have come up then.

time="2021-01-14T23:32:32+01:00" level=debug msg="vulcand/oxy/roundrobin/rr: completed ServeHttp on request" Request="{\"Method\":\"GET\",\"URL\":{\"Scheme\":\"\",\"Opaque\":\"\",\"User\":null,\"Host\":\"\",\"Path\":\"/\",\"RawPath\":\"\",\"ForceQuery\":false,\"RawQuery\":\"\",\"Fragment\":\"\",\"RawFragment\":\"\"},\"Proto\":\"HTTP/2.0\",\"ProtoMajor\":2,\"ProtoMinor\":0,\"Header\":{\"Accept\":[\"text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9\"],\"Accept-Encoding\":[\"gzip, deflate, br\"],\"Accept-Language\":[\"en-US,en;q=0.9,nl;q=0.8\"],\"Cache-Control\":[\"max-age=0\"],\"Dnt\":[\"1\"],\"Sec-Fetch-Dest\":[\"document\"],\"Sec-Fetch-Mode\":[\"navigate\"],\"Sec-Fetch-Site\":[\"none\"],\"Sec-Fetch-User\":[\"?1\"],\"Upgrade-Insecure-Requests\":[\"1\"],\"User-Agent\":[\"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.141 Safari/537.36\"],\"X-Forwarded-Host\":[\"[REDACTED-DOMAIN]\"],\"X-Forwarded-Port\":[\"443\"],\"X-Forwarded-Proto\":[\"https\"],\"X-Forwarded-Server\":[\"fa10a11f7238\"],\"X-Real-Ip\":[\"[REDACTED-IP]\"]},\"ContentLength\":0,\"TransferEncoding\":null,\"Host\":\"[REDACTED-DOMAIN]\",\"Form\":null,\"PostForm\":null,\"MultipartForm\":null,\"Trailer\":null,\"RemoteAddr\":\"[REDACTED-IP]:37302\",\"RequestURI\":\"/\",\"TLS\":null}"

I am finding a lot of these in the logs. There is a connection but something is wrong with the redirect? What is port :37302 is it a clue? @Reiner_Nippes

Really, this probably not a problem with the Traefik config, but more with something going on in the Nextcloud configs (maybe in combo with Traefik). That’s why I put all these in the first post of this thread.

All the other containers are working just fine.

NB: I am using the LinuxServerIO maintained image.

This seemed to be the key. I found some topics concerning this:

Which eventually led me here:

Where you already solved this issue!

I removed these lines: docker-nextcloud/default at master · linuxserver/docker-nextcloud · GitHub

Do I need to do more than this?

I also tried another option: to change port 80 port 443 and leave the default file as is. Because I would prefer to change as little as possible in my docker container config files.

  - "traefik.http.services.nextcloud-secure.loadbalancer.server.port=443"

but that gave me this error:

400 Bad Request
The plain HTTP request was sent to HTTPS port

Do you think a solution like this would be possible?

of course. you can’t use such containers behind traefik. the redirect to 443 is handled by traefik. traefik is configured to talk to port 80. the container is sending all the time a redirect to 443. but traefik doesn’t care.

changing the image would be easier. :wink:

because I could only find this: [Traefik V2] Allow HTTPS -> [Traefik] -> HTTPS (backend service) · Issue #5346 · traefik/traefik · GitHub

and i always tend to use the official working image rather than an enhanced but not working one.