Redacting Vaultwarden access_token parameter with Caddy

1. The problem I’m having:

I am trying to make my vaultwarden docker container instance more secure by following this hardening guide. Specifically I am trying to follow the part of the guide that advises to redact the value of the access_token parameter in the access.log file for caddy. I run caddy, vaultwarden and another service all as docker containers. However when I try to add this suggestion from Chat GPT to add to my Caddyfile:

format filter {
			wrap json
			fields {
				request>uri redact {
					query access_token
				}
			}
		}

I get errors when I run the command docker logs -f caddy which can be seen below. I think the issue is related to the caddy binary I’m using but I have to use this specific caddy binary because it has support for DNS challenges and duckdns domains. I have added further details in the appropriate sections.

2. Error messages and/or full log output:

docker logs -f caddy:
{"level":"info","ts":1735148027.6933646,"msg":"using config from file","file":"/etc/caddy/Caddyfile"}
Error: adapting config using caddyfile: parsing caddyfile tokens for 'log': getting module named 'caddy.logging.encoders.filter.redact': module not registered: caddy.logging.encoders.filter.redact, at /etc/caddy/Caddyfile:55
{"level":"info","ts":1735148030.4536636,"msg":"using config from file","file":"/etc/caddy/Caddyfile"}
Error: adapting config using caddyfile: parsing caddyfile tokens for 'log': getting module named 'caddy.logging.encoders.filter.redact': module not registered: caddy.logging.encoders.filter.redact, at /etc/caddy/Caddyfile:55
{"level":"info","ts":1735148032.3835313,"msg":"using config from file","file":"/etc/caddy/Caddyfile"}

3. Caddy version:

caddy version:
v2.8.4 h1:q3pe0wpBj1OcHFZ3n/1nl4V4bxBrYoSoab7rL9BMYNk=

file caddy binary:
caddy: ELF 64-bit LSB executable, ARM aarch64, version 1 (SYSV), statically linked, Go BuildID=d2CUgHd5v5KarbWhll50/spUmDDdeK-sOxRIzlMTs/ODBKUlz7E8KeiCtYfzIm/dhB6KAm-bEo07d_o6xDW, stripped

4. How I installed and ran Caddy:

Followed this guide and installed Linux arm64 caddy-dns/duckdns caddy binary:

a. System environment:

Host OS is a Raspberry Pi 4B running Raspberry Pi OS kernal version:
6.1.21-v8+ #1642 SMP PREEMPT Mon Apr 3 17:24:16 BST 2023 aarch64 GNU/Linux

docker version:
27.4.1

b. Command:

c. Service/unit/compose file:

docker compose file:

services:
  caddy:
    container_name: caddy
    image: caddy:2
    restart: always
    ports:
      - 80:80
      - 443:443
      - 443:443/udp # Needed for HTTP/3.
    volumes:
      - /usr/local/bin/caddy:/usr/bin/caddy  
      - /usr/local/bin/Caddyfile:/etc/caddy/Caddyfile:ro
      - ./caddy-config:/config
      - ./caddy-data:/data
      - /opt/docker_secrets/caddy:/run/secrets:ro
    env_file:
      - /opt/docker_env/caddy/caddy.env
    environment:
      - DUCKDNS_TOKEN=<redacted>

  unifi-network-application:
    container_name: unifi-network-application
    image: lscr.io/linuxserver/unifi-network-application:latest
    restart: unless-stopped
    ports:
      #- 8443:8443
      - 3478:3478/udp
      - 10001:10001/udp
      - 8080:8080
      - 1900:1900/udp #optional
      #- 8843:8843 #optional
      #- 8880:8880 #optional
      #- 6789:6789 #optional
      #- 5514:5514/udp #optional
    volumes:
      - ./unifi-network-application/config:/config
      - ./unifi-network-application/data:/data
    env_file:
      - /opt/docker_env/unifi/unifi.env
    environment:
      - MONGO_PASS=<redacted>

  unifi-db:
    container_name: unifi-db
    image: mongodb-raspberrypi4-unofficial-r7.0.0:latest
    restart: unless-stopped
    volumes:
      - ./unifi-db/data:/data/db
      - ./init-mongo.js:/docker-entrypoint-initdb.d/init-mongo.js:ro

  vaultwarden:
    container_name: vaultwarden
    image: vaultwarden/server:latest
    restart: always
    volumes:
      - ./vw-data:/data # the path before the : can be changed
    env_file:
      - /opt/docker_env/vaultwarden/vaultwarden.env
    environment:
       - ADMIN_TOKEN=<redacted>

caddy.env file for compose file:

DOMAIN=<redacted>
LOG_FILE=/data/access.log

d. My complete Caddy config:

Caddyfile:

*.{$DOMAIN} {
	tls {
		dns duckdns {$DUCKDNS_TOKEN}
	}

	# Logs configuration (optional, adjust as necessary)
	log {
		level INFO
		output file {$LOG_FILE} {
			roll_size 10MB
			roll_keep 10
		}
	}

	# Default reverse proxy to a generic service if no specific service matches
	reverse_proxy service_default:80
}

# Vaultwarden Service
vaultwarden.{$DOMAIN} {
	reverse_proxy vaultwarden:80
	log {
		level INFO
		output file {$LOG_FILE} {
			roll_size 10MB
			roll_keep 10
		}
		format filter {
			wrap json
			fields {
				request>uri redact {
					query access_token
				}
			}
		}
	}
}

unifi.{$DOMAIN} {
	reverse_proxy unifi-network-application:8443 {
		transport http {
			tls_insecure_skip_verify
		}
	}

	# Add an optional redirect rule for "http://unifi.<your-domain>"
	#redir https://unifi.{$DOMAIN} permanent

	log {
		level INFO
		output file {$LOG_FILE} {
			roll_size 10MB
			roll_keep 10
		}
	}
}

unifi.{$DOMAIN}:8443 {
	redir https://unifi.{$DOMAIN} permanent
}

5. Links to relevant resources:

Do not ask LLM for knowledge because they aren’t good at it.

Always refer to the official documentation because it’s, well, official:

So your config would look something like this:

format filter {
	wrap json
	fields {
		request>uri query {
			delete access_token
		}
	}
}

Thank you for your answer. I checked out the documentation and in the end adapted this example:

example.com {
   log {
   	format filter {
   		request>headers>Cookie cookie {
   			replace session REDACTED
   			delete secret
   		}
   	}
   }
}

It now replaces the access token with the string ‘REDACTED’. Thank you for pointing me in the right direction.