Is it okay to have two log output locations in my Caddyfile?

1. The problem I’m having:

Is it okay to have two log output locations in my Caddyfile like this?

{
    log {
        output file /var/log/caddy/access.log
        output stdout
    }
}

I’ve tried it, and it seems to work, but I was wondering if it will cause issues. I don’t see anything mentioning having two output locations in the documentation.

2. Error messages and/or full log output:

N/A

3. Caddy version:

v2.7.6 h1:w0NymbG2m9PcvKWsrXO6EEkY9Ru4FJK8uQbYcev1p3A=

4. How I installed and ran Caddy:

a. System environment:

Podman 4.8.1

b. Command:

caddy

c. Service/unit/compose file:

---
apiVersion: v1
kind: Pod
metadata:
  labels:
    app: caddy-pod
    io.containers.autoupdate: registry
    io.containers.sdnotify: conmon
  name: caddy-pod
spec:
  securityContext:
    seLinuxOptions:
      type: spc_t
  containers:
    - name: caddy
      image: ghcr.io/poperigby/caddy:latest
      env:
        - name: SMTP_PASSWORD
          value: REDACTED
        - name: PERSONAL_EMAIL
          value: REDACTED
        - name: CLOUDFLARE_API_TOKEN
          value: REDACTED
      ports:
        - containerPort: 80
          hostPort: 80
        - containerPort: 443
          hostPort: 443
      volumeMounts:
        - name: caddyfile-mount
          mountPath: /etc/caddy/Caddyfile
        - name: caddy-data
          mountPath: /data
        - name: caddy-config
          mountPath: /config
  volumes:
    - name: caddyfile-mount
      hostPath:
        path: /home/cassidy/.config/containers/systemd/services/caddy/Caddyfile
        type: File
    - name: caddy-data
      persistentVolumeClaim:
        claimName: caddy-data
    - name: caddy-config
      persistentVolumeClaim:
        claimName: caddy-config
    - name: caddy-config
      persistentVolumeClaim:
        claimName: caddy-config

d. My complete Caddy config:

(auth) {
    forward_auth authelia-pod:9091 {
        uri /api/verify?rd=https://auth.haddock.cc
        copy_headers Remote-User Remote-Groups Remote-Name Remote-Email
    }
}

{
    # Global configuration
    acme_dns cloudflare {env.CLOUDFLARE_API_TOKEN}
    email {env.PERSONAL_EMAIL}
    order webdav before file_server

    log {
        output file /var/log/caddy/access.log
        output stdout
    }

    crowdsec {
        api_url https://localhost:8080
        api_key {env.CROWDSEC_BOUNCER_API_KEY}
        ticker_interval 15s
    }
}

haddock.cc {
    respond "Hello, world!"
}

auth.haddock.cc { # Authelia
    reverse_proxy authelia-pod:9091
}

media.haddock.cc { # Jellyfin
    import auth
    reverse_proxy jellyfin-pod:8096
}

food.haddock.cc { # Mealie
    import auth
    reverse_proxy mealie-pod:9000
}

torrent.haddock.cc { # qBittorrent
    import auth
    reverse_proxy qbittorrent-pod:8080
}

prowl.haddock.cc { # Prowlarr
    import auth
    reverse_proxy arr-pod:9696
}

tv.haddock.cc { # Sonarr
    import auth
    reverse_proxy arr-pod:8989
}

movies.haddock.cc { # Radarr
    import auth
    reverse_proxy arr-pod:7878
}

cloud.haddock.cc { # Nextcloud
    reverse_proxy nextcloud-pod:80 {
        header_down Strict-Transport-Security "max-age=15552000; includeSubDomains"
    }
    rewrite /.well-known/carddav /remote.php/dav
    rewrite /.well-known/caldav /remote.php/dav
}

news.haddock.cc { # FreshRSS
    import auth
    reverse_proxy freshrss-pod:80
}

drive.haddock.cc { # File Browser
    import auth
    reverse_proxy filebrowser-pod:80
}

There are 2 issues with your assumptions

Firstly, log configuration in the global options section does not configure access logs. It configures everything but access logs. This is mentioned in the documentation of the log global option:

The differs from the log directive, which only configures HTTP request logging (also known as access logs). The log global option shares its configuration structure with the directive (except for include and exclude), and complete documentation can be found on the directive’s page.

Secondly, your configuration doesn’t work the way you think it works. The latter value of output is overwriting the earlier value, so your configuration will only print logs to stdout but nothing to the file. If you want to write logs to both outputs, configure 2 log global options with names and then a log directive in the site block. A contrived Caddyfile for that behavior looks like this:

{
	log stdoutlogger {
		output stdout
	}
	log filelogger {
		output file caddy-log.log
	}
}
localhost {
	respond "OK!"

	# access log
	log {
		output file access.log
	}
}
2 Likes

Thank you. Is it okay to route access logging for every site to the same file? I’m using CrowdSec. Weirdly, CrowdSec still seemed to be scanning /var/log/caddy/access.log correctly, because it was banning a ton of IP addresses, even though that isn’t actually an access log?

Also, to make it so I don’t have to write a bunch of stuff for every site, should I just use a snippet like this, or is there a better way?

(crowdsec) {
  log {
    output /var/log/caddy/access.log
  }
}

Edit: I’m a bit confused. Here, it says the global log option does include HTTP access logs, and I can filter to only them with this

log default {
	output stdout
	format json
	include http.log.access admin.api
}

Global options configures “all logs”. Using the log directive enables access logs, plus can configure a logger (output & format) for access logs. Global loggers can include/exclude any log namespaces if you like. Adapt your config to JSON to get an idea of how it works.

If that’s what you want, sure.

2 Likes

I think I understand. Adapting it to JSON helped a bit. Is it possible to enable access logging for every site without putting an empty log directive in every site block?

It’s necessary to enable for each site.

2 Likes

Got it. I guess I’ll just create a snippet with all my repetitive stuff. Thanks!

1 Like

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.