Unable to go past the “etc/traefik/traefik.yaml: is a directory” error

Hello,
I'm a newbie at servers and unable to fix the traefik-docker error. I'm traying to put traefik on my portainer machine and facing this error when running docker compose up.

[+] Running 1/0
 ✔ Container traefik  Created                                                                                      0.0s
Attaching to traefik
traefik  | {"level":"error","error":"command traefik error: read /etc/traefik/traefik.yaml: is a directory","time":"2024-07-03T07:48:54Z","message":"Command error"}
traefik exited with code 0

I've created traefik folder in my / catalog with docker-compose.yaml file containing this script

---
# -- (Optional) When using a custom network
 networks:
   frontend:
     external: true
 services:
  traefik:
    image: docker.io/library/traefik:v3.0.3
    container_name: traefik
    ports:
      - 80:80
      - 443:443
      # -- (Optional) Enable Dashboard, don't do in production
      # - 8080:8080
    volumes:
      - ./config:/etc/traefik
      - /var/run/docker.sock:/var/run/docker.sock:ro
    # -- (Optional) When using Cloudflare as Cert Resolver
    environment:
       - CF_DNS_API_TOKEN=SIstTuieaC0fhnatt4zcJ3ix7zKfMv3I0Ky1jpHo
    # -- (Optional) When using a custom network
    networks:
       - frontend
    restart: unless-stopped

And config catalog in this folder containing traefik.yaml file with this script

global:
  checkNewVersion: false
  sendAnonymousUsage: false

# -- (Optional) Change Log Level and Format here...
#     - loglevels [DEBUG, INFO, WARNING, ERROR, CRITICAL]
#     - format [common, json, logfmt]
# log:
#  level: ERROR
#  format: common
#  filePath: /var/log/traefik/traefik.log

# -- (Optional) Enable Accesslog and change Format here...
#     - format [common, json, logfmt]
# accesslog:
#   format: common
#   filePath: /var/log/traefik/access.log

# -- (Optional) Enable API and Dashboard here, don't do in production
# api:
#   dashboard: true
#   disableDashboardAd: true
#   insecure: true

# -- Change EntryPoints here...
entryPoints:
  web:
    address: :80
    # -- (Optional) Redirect all HTTP to HTTPS
    http:
       redirections:
         entryPoint:
           to: websecure
           scheme: https
  websecure:
    address: :443
  # -- (Optional) Add custom Entrypoint
  # custom:
  #   address: :8080

# -- Configure your CertificateResolver here...
# certificatesResolvers:
#   staging:
#     acme:
#       email: your-email@example.com
#       storage: /etc/traefik/certs/acme.json
#       caServer: "https://acme-staging-v02.api.letsencrypt.org/directory"
#       -- (Optional) Remove this section, when using DNS Challenge
#       httpChallenge:
#         entryPoint: web
#       -- (Optional) Configure DNS Challenge
#       dnsChallenge:
#         provider: your-resolver (e.g. cloudflare)
#         resolvers:
#           - "1.1.1.1:53"
#           - "8.8.8.8:53"
    production:
     acme:
       email: christianignaczak@gmail.com
       storage: /etc/traefik/certs/acme.json
       caServer: "https://acme-v02.api.letsencrypt.org/directory"
#       -- (Optional) Configure DNS Challenge
     dnsChallenge:
         provider: cloudflare
         resolvers:
           - "1.1.1.1:53"
           - "8.8.8.8:53"

# -- (Optional) Disable TLS Cert verification check
serversTransport:
   insecureSkipVerify: true

# -- (Optional) Overwrite Default Certificates
# tls:
#   stores:
#     default:
#       defaultCertificate:
#         certFile: /etc/traefik/certs/cert.pem
#         keyFile: /etc/traefik/certs/cert-key.pem
# -- (Optional) Disable TLS version 1.0 and 1.1
#   options:
#     default:
#       minVersion: VersionTLS12

providers:
  docker:
    # -- (Optional) Enable this, if you want to expose all containers automatically
    exposedByDefault: false
  file:
    directory: /etc/traefik
    watch: true

I've even copied this script to etc/traefik but this didint work to. I dont know what to do now.

So you solved it already (post) :slight_smile:

I just wanted to note that

gives the impression of added security, but it does not do what it promises.

ro works for files, but not for sockets. The socket is used to send GET and POST and receive a responses, so it’s working two ways.

The potential security issue here is that a attacker inside your Traefik container can use GET to see more than Traefik needs to and POST do do whatever, export data, kill containers and run crypto-miners.

If you want to secure that attack vector, you would need to place some kind of docker-socket-proxy in between.

Note that I am personally a bit skeptical of the usual Tecnativa solution. You want to increase security, and introduce an additional image from a kind of unknown source - an additional attack vector. Recently, the latest image was a three year old version, so I am not sure how well they control their build pipeline.

You can also create your own docker-socket-proxy, I trust nginx more:

services:
  dockersock:
    image: nginx:alpine-slim
    restart: unless-stopped
    security_opt:
      - no-new-privileges:true
    cap_add:
      - CHOWN
      - SETGID
      - SETUID
      - NET_BIND_SERVICE
    cap_drop:
      - ALL
    networks:
      - dockersock
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
    configs:
      - source: nginx
        target: /etc/nginx/nginx.conf
    expose:
      - 2375

configs:
  nginx:
    content: |
      user root;
      events { worker_connections 1024; }
      http {
        server {
          listen 2375;
          location ~ ^/v1\.24/(events|containers|services|version|networks|tasks) {
            if ($$request_method != GET) { return 405; }
            proxy_pass http://unix:/var/run/docker.sock;
            proxy_set_header Host $$host;
            proxy_set_header X-Real-IP $$remote_addr;
            proxy_set_header X-Forwarded-For $$proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $$scheme;
            proxy_read_timeout 3600s;
          }
          location / { return 405; }
        }
      }

But note that the inline config probably doesn't work like this in Swarm.