Help Needed - Unable to Chain BasicAuth and Security-Header Middlewares Together in Traefik 3.3.4 Docker Deployment, and Other Things

I'm looking to replace my SWAG (Nginx-based) reverse proxy with Traefik, however I'm having some issues with chaining basicauth and security-header middlewares together, it appears I can only get one of the middlewares to function at a time, not both.

I can get an A+ rating at securityheaders.io when they're running correctly, however the current Content Security Policy security headers break Portainer formatting, and I'm not exactly sure where I need to make additional changes... would it be in contentSecurityPolicy or accessControlAllowOriginList ?

Also appreciate a check of my current configurations, as I want to have access to the Traefik dashboard externally, however I think I'm also exposing the raw API, which I'd prefer not to do - I understand I need to make a change to the "insecure" setting, however then the dashboard doesn't appear to work.

Have added my current working configs for reference - appreciate any assistance.

Docker Compose:

networks:
  mediastack:
    name: mediastack
    driver: bridge
    ipam:
      driver: default
      config:
      - subnet: ${DOCKER_SUBNET:?err}
        gateway: ${DOCKER_GATEWAY:?err}

services:
  portainer:
    image: portainer/portainer-ce:latest
    container_name: portainer
    restart: always
    security_opt:
      - no-new-privileges=true
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - ${FOLDER_FOR_DATA:?err}/portainer:/data
#    ports:
#      - "${WEBUI_PORT_PORTAINER:?err}:9443"
    networks:
      - mediastack
    labels:
      - traefik.enable=true
      - traefik.docker.network=mediastack
      # ROUTERS
      - traefik.http.routers.portainer.rule=Host(`portainer.${CLOUDFLARE_DNS_ZONE:?err}`)
      - traefik.http.routers.portainer.entrypoints=secureweb
      - traefik.http.routers.portainer.tls=true
      - traefik.http.routers.portainer.tls.certresolver=letsencrypt
      - traefik.http.routers.portainer.tls.options=default
      - traefik.http.routers.portainer.middlewares=portainer-auth@docker    # No CSP Headers - They Break Portainer Formatting
#      - traefik.http.routers.portainer.middlewares=security-headers@file,portainer-auth@docker
      # SERVICES
      - traefik.http.services.portainer.loadbalancer.server.scheme=http
      - traefik.http.services.portainer.loadbalancer.server.port=9000
      # MIDDLEWARES
      - traefik.http.middlewares.portainer-auth.basicauth.users=${BASIC_WEB_AUTH:?err}

  traefik:
    image: traefik:latest
    container_name: traefik
    restart: unless-stopped
    networks:
      - mediastack
    environment:
      - TZ=${TIMEZONE:?err}
      - CF_DNS_API_TOKEN=${CLOUDFLARE_DNS_API_TOKEN:?err}
    ports:
      - 80:80
      - 443:443
      - 8080:8080
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - ${FOLDER_FOR_DATA:?err}/traefik:/etc/traefik:ro
      - ${FOLDER_FOR_DATA:?err}/traefik/letsencrypt:/letsencrypt:rw
    labels:
      - traefik.enable=true
      - traefik.docker.network=mediastack
      # ROUTERS
      - traefik.http.routers.traefik.rule=Host(`traefik.${CLOUDFLARE_DNS_ZONE:?err}`)
      - traefik.http.routers.traefik.entrypoints=secureweb
      - traefik.http.routers.traefik.tls=true
      - traefik.http.routers.traefik.tls.certresolver=letsencrypt
      - traefik.http.routers.traefik.tls.options=default
      - traefik.http.routers.traefik.middlewares=security-headers@file,traefik-auth@docker
      # SERVICES
      - traefik.http.services.traefik.loadbalancer.server.scheme=http
      - traefik.http.services.traefik.loadbalancer.server.port=8080
      # MIDDLEWARES
      - traefik.http.middlewares.traefik-auth.basicauth.users=${BASIC_WEB_AUTH:?err}

Docker ENV

DOCKER_SUBNET=172.28.10.0/24
DOCKER_GATEWAY=172.28.10.1
FOLDER_FOR_DATA=/docker/appdata
TIMEZONE=Europe/Zurich
WEBUI_PORT_PORTAINER=9000
BASIC_WEB_AUTH=portal:REDACTED
CLOUDFLARE_EMAIL=REDACTED
CLOUDFLARE_DNS_ZONE=ADD-DOMAIN-NAME-HERE
CLOUDFLARE_DNS_API_TOKEN=REDACTED

Static Config

############################################
############################################
#
# Traefik.YAML - Static Configuration File
#
############################################
############################################

global:
  checkNewVersion: true
  sendAnonymousUsage: true

log:
  level: INFO
#  level: DEBUG

accessLog:
  filePath: /letsencrypt/access.log
  format: json

api:
  dashboard: true
  insecure: true

entryPoints:
  web:
    address: :80
    http:
      redirections:
        entryPoint:
          to: secureweb
          scheme: https
          permanent: true
  secureweb:
    address: :443
    http:
      tls:
        options: default
        certResolver: letsencrypt
        domains:
          - main: ADD-DOMAIN-NAME-HERE
            sans:
              - "*.ADD-DOMAIN-NAME-HERE"

providers:
  docker:
    exposedByDefault: false
  file:
    directory: /etc/traefik
    watch: true

certificatesResolvers:
  letsencrypt:
    acme:
      storage: /letsencrypt/acme.json
      keyType: EC384
      caServer: https://acme-v02.api.letsencrypt.org/directory
      dnsChallenge:
        provider: cloudflare
        resolvers:
          - 1.1.1.1:53
          - 1.0.0.1:53
        propagation:
          delayBeforeChecks: 2s

Dynamic Config

############################################
############################################
#
# Dynamic.YAML - Dynamic Configuration File
#
############################################
############################################

tls:
  stores:
    default:
      defaultGeneratedCert:
        resolver: letsencrypt
        domain:
          main: ADD-DOMAIN-NAME-HERE
          sans:
            - "*.ADD-DOMAIN-NAME-HERE"
  options:
    default:
      minVersion: VersionTLS12
      cipherSuites:
        - TLS_AES_256_GCM_SHA384
        - TLS_CHACHA20_POLY1305_SHA256
        - TLS_AES_128_GCM_SHA256
        - TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
        - TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
        - TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256
        - TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256
        - TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
        - TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
      curvePreferences:
        - CurveP521
        - CurveP384
      sniStrict: true

http:
  middlewares:
    security-headers:
      headers:
        accessControlAllowCredentials: true
        accessControlAllowHeaders: "*"
        accessControlAllowMethods:
          - GET
          - OPTIONS
          - PUT
        accessControlAllowOriginList:
          - https://ADD-DOMAIN-NAME-HERE
          - https://*.ADD-DOMAIN-NAME-HERE
        accessControlMaxAge: 100
        addVaryHeader: true
        browserXssFilter: true
        stsSeconds: 63072000
        stsIncludeSubdomains: true
        stsPreload: true
        forceSTSHeader: true
        customFrameOptionsValue: SAMEORIGIN
        contentTypeNosniff: true
        contentSecurityPolicy: default-src 'self'; script-src 'self'; object-src 'none'; base-uri 'none'
        referrerPolicy: strict-origin-when-cross-origin
        permissionsPolicy: camera=(), microphone=(), geolocation=(), payment=(), usb=(), bluetooth=()

In general this looks ok:

      - traefik.http.routers.traefik.middlewares=security-headers@file,traefik-auth@docker

It seems you have some double config. Place http-to-https redirect and TLS only on entrypoint. Place headers on entrypoint, too (doc). Then you only need auth in labels.

It could be as simple as:

    labels:
      - traefik.enable=true
      - traefik.http.routers.mydashboard.rule=Host(`traefik.example.com`)
      - traefik.http.routers.mydashboard.service=api@internal
      - traefik.http.routers.mydashboard.middlewares=myauth
      - traefik.http.middlewares.myauth.basicauth.users=test:$$apr1$$H6uskkkW$$IgXLP6ewTrSuBkTrqE8wj/

Why do you have labels on Traefik? You don't declare a service for the router, so dashboard is probably not working. Also you have api.insecure enabled, which will create Traefik dashboard on :8080 without auth. Maybe check simple Traefik example for best practice.