Log

Access Logs

Simple Logs

In general, you should create a snippet and import into each block.

#
# Global Options Block
#
{
    ...
    ...
}
#
# Importable Snippets
#
(logging) {
    log {
        output file /var/log/caddy/access.log
    }
}
#
# Host Blocks
#
site.your.org {
    import logging     
    reverse_proxy * http://some.server.lan:8080
}
other.your.org {
    import logging     
    reverse_proxy * http://other.server.lan:8080
}

Per VHost Logs

If you want separate logs for each vhosts you can still use a snippit by adding a parameter for the site name.

#
# Global Options Block
#
{
    ...
    ...
}
#
# Importable Snippets
#
(logging) {
    log {
        output file /var/log/caddy/{args[0]}.log        
}
#
# Host Blocks
#
site.your.org {
    # Add the argument "site.your.org" at the end sets the log file name to "site.your.org.log"
    import logging site.your.org
    reverse_proxy * http://some.server.lan:8080
}
other.your.org {
    import logging other.your.org    
    reverse_proxy * http://other.server.lan:8080
}

Wildcard Sites

Wildcard sites only have one block but you must use the hostname matcher to separate logs. Note the slight difference in the handling of log names.

#
# Global Options Block
#
{
    ...
    ...
}
#
# Importable Snippets
#
(logging) {
    log {
        output file /var/log/caddy/{args[0]}       
}
#
# Main Block
#
*.site.org, site.org {

        # Everything goes to the file named here (access.log) unless it's filtered out by a more specific log block
        import logging access.log

        # This site will write to the access.log 
        @site host other.site.org
        handle @site {
                reverse_proxy * http://other.site
        }

        # This site will write to just this log file. Make sure to import logging BEFORE the '@www host' matcher or requests don't get logged here.
        import logging www.site.org.log 
        @www host www.site.org                
        handle @www { 
                root * /var/www/www.site.org 
                file_server 
        }

Logging Credentials

If you want to track users that have authenticated, add a directive to the global headers so their usernames are included in the request log.

# 
# Global Options Block 
# 
{        
        servers { 
                log_credentials 
        }
}

File Permissions

By default, only caddy can read the log files. This is a problem when you have a log analysis package. In recent versions of caddy however, you can set the mode.

    log {
        output file /var/log/caddy/access.log {
                mode 644
        }
    }

If the log file doesn’t change modes, check the version of caddy. It must be newer than v2.8.4 for the change and you must restart.

Troubleshooting

You can have a case where the domain specific file never gets created. This usually happens when there us nothing to write to it. Check the hostname is correct.


Last modified March 17, 2026: Shorten menus (c0227ad)