Struggling with caddy2 configuration

Hi!

Since upgrading to caddy2, I didn’t manage to replicate the behaviour of my old configuration completely. It’s probably just a small tweak, perhaps somebody knows the answer.

The caddy version I use is 2.2.1.

I run caddy in a FreeBSD 12.2-RC3 jail and start it with the normal rc.d script.

My complete Caddyfile or JSON config:

{
        # debug
        #acme_ca https://acme-staging-v02.api.letsencrypt.org/directory
        email xxx@gmail.com
        # default_sni share.fp.on.at
}

:80 {
       root * /usr/local/www/restricted/
       file_server
}

web.fp.on.at {
        root   * /usr/local/www/shares.web/
        file_server
        encode gzip
        header / Strict-Transport-Security "max-age=31536000"
}

share.fp.on.at {
        root * /usr/local/www/nextcloud
        file_server
        log {
                output file /var/log/share.fp.on.at.log
                format single_field common_log
        }

        php_fastcgi 127.0.0.1:9000 {
                env front_controller_active true
        }

        header {
                enable HSTS
                Strict-Transport-Security max-age=31536000
        }

        redir /.well-known/carddav /remote.php/dav 301
        redir /.well-known/caldav /remote.php/dav 301

        # .htaccess / data / config / ... shouldn't be accessible from outside
        @forbidden {
                path /.htaccess
                path /data/*
                path /config/*
                path /db_structure
                path /.xml
                path /README
                path /3rdparty/*
                path /lib/*
                path /templates/*
                path /occ
                path /console.php
        }

        respond @forbidden 404
}

The problem I’m having is - as you see I run two different FQDN for two services I run on this server. For these two servies, HTTPS is used of course, and an HTTP–>HTTPS redirect should happen.

Additionally, I have the “:80” section at the top of the configuration, because I also want the webserver to serve some files unencrypted if you just “browse” to the IP of the server, without giving one of the proper DNS-names.

This all worked fine as described with caddy1. With caddy2, after I migrated the configuration to the best of my knowledge, everything still works fine like described except the fact that there is no redirection from HTTP->HTTPS is done any more for the two named virtual servers. Instead, I get a 404 code returned.

I tried to remove the “:80” section completely, after which the redirection works fine again. But I need the functionality of the simple unencrpyted webserver for IP only connections. What is the correct way to do this?

First, a few comments:

        header {
                enable HSTS
                Strict-Transport-Security max-age=31536000
        }

enable HSTS here isn’t a valid header, I think this was meant to be a comment? Put a # in front of that line to make it a comment. The Strict-Transport-Security itself is what enabled HSTS.

header / Strict-Transport-Security "max-age=31536000"

Note that the / here will make it only apply to requests to exactly / and nothing else. To make it apply to all requests, just remove the / matcher. Caddy v2 uses exact matching for paths.

And finally - yeah, having a :80 site block overrides the HTTP->HTTPS redirects. IIRC there should be a note about that in your startup logs.

So because of that you need to do the redirects yourself. What you can do is use a host matcher in your :80 block to handle requests to the domains your care about, and fallback to serving your other stuff otherwise:

:80 {
	@redirect host *.fp.on.at
	handle @redirect {
		redir https://{hostport}{uri}
	}

	handle {
		root * /usr/local/www/restricted
		file_server
	}
}
1 Like

First, thank you for your analysis and the additional advice (regarding HSTS etc).

I now played around and implemented your suggestions and it works very fine. :pray:

Regarding failed redirection. You write that the :80 directive is disabling them and that it should be noted in the logs. Actually, the logs show somewhat contradicting information regarding this:

{"level":"info","ts":1607174769.6450539,"logger":"http","msg":"server is listening only on the HTTP port, so no automatic HTTPS will be applied to this server","server_name":"srv0","http_port":80}
{"level":"info","ts":1607174769.6450942,"logger":"http","msg":"server is listening only on the HTTPS port but has no TLS connection policies; adding one to enable TLS","server_name":"srv1","https_port":443}
{"level":"info","ts":1607174769.6451113,"logger":"http","msg":"enabling automatic HTTP->HTTPS redirects","server_name":"srv1"}
{"level":"warn","ts":1607174769.645137,"logger":"http","msg":"user server is listening on same interface as automatic HTTP->HTTPS redirects; user-configured routes might override these redirects","server_name":"srv0","interface":"tcp/:80"}

I assume the “user-configured routes might override these redirects” is the info that you meant.

When trying to read the log-files correctly, I see mentions of different server_names “srv0” and “srv1”. Which entities are these referring to? Can I rename them more meaningful?

If you run the caddy adapt --pretty command you’ll get a better idea of what that means.

Caddy v2’s primary configuration language is actually JSON, and the Caddyfile is a UX layer that maps to JSON (called a config adapter).

Those server names are auto-generated by the Caddyfile adapter. If you were to write your config in JSON, you could set them to whatever you want. But know that there’s no tooling to go from JSON config back to Caddyfile, it’s a one-way conversion.

And yes that last log message is what I was talking about.

1 Like

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