`respond` with a file instead of a string

1. Caddy version (caddy version):

v2.5.0 h1:eRHzZ4l3X6Ag3kUt8nj5IxATprhqKq/wToP7OHlXWA0=

2. How I run Caddy:

Installed via apt repositories, run via systemd.

deb https://dl.cloudsmith.io/public/caddy/stable/deb/debian any-version main

a. System environment:

Ubuntu 22.04, systemd 249 (249.11-0ubuntu3)

b. Command:

systemctl enable caddy

c. Service/unit/compose file:

Unedited default.

d. My complete Caddyfile or JSON config:

mta-sts.qualcuno.xyz {
  respond /.well-known/mta-sts.txt "version: STSv1
mode: enforce
max_age: 1296000
mx: bjorn.qualcuno.xyz
"
  respond 404
}

autoconfig.qualcuno.xyz {
  respond /mail/config-v1.1.xml "<?xml version=\"1.0\"?>
  <clientConfig version=\"1.1\">
  <emailProvider id=\"%EMAILDOMAIN%\">
  <domain>%EMAILDOMAIN%</domain>
  <displayName>Email</displayName>
  <displayShortName>Email</displayShortName>
  <incomingServer type=\"imap\">
  <hostname>bjorn.qualcuno.xyz</hostname>
  <port>993</port>
  <socketType>SSL</socketType>
  <username>%EMAILADDRESS%</username>
  <authentication>password-cleartext</authentication>
  <addThisServer>true</addThisServer>
  <useGlobalPreferredServer>true</useGlobalPreferredServer>
  </outgoingServer>
  <documentation url=\"https://bjorn.qualcuno.xyz/admin/ui/client\">
  <descr lang=\"en\">Configure your email client</descr>
  </documentation>
  </emailProvider>
</clientConfig>"
  respond 404
}
  

3. The problem I’m having:

No problem, I just want to put that big string in a separate file.

4. Error messages and/or full log output:

No error

5. What I already tried:

I read the documentation looking for something like the curl @ syntax. I wanted to avoid creating a whole file_server to serve a single file.

6. Links to relevant resources:

I would just use file_server and then rewrite all requests to a specific file.

1 Like

Yeah, but I don’t need to rewrite. I need to serve one file and 404 everything else.

Maybe I can try something like this:

file_server /.well-known/mta-sts.txt {
  root /etc/caddy/responses
  try_files mta-sts.txt =404
}
respond 404

Ok, that doesn’t work.

I went for

mta-sts.qualcuno.xyz {
  handle /.well-known/mta-sts.txt {
    file_server {
      root /etc/caddy/responses
    }
  }
  handle {
    respond 404
  }
}
1 Like

Oh, I understand now.

Does the first stanza work if you remove the try_files?

It validates but I don’t think it serves the file.

FYI, you can use backticks instead of double quotes, especially if the string you’re trying to use has a lot of double quotes, so you can skip escaping them.

One less line, less indentation:

	handle /.well-known/mta-sts.txt {
		root * /etc/caddy/responses
		file_server
	}
1 Like

Oh, cool. I still have to learn where directives can and cannot go.

I fought a while with that positioning, for tls and issuer.

1 Like

Directives which affect the server itself like tls, log, bind must go top-level, can’t be within a route. issuer is specifically an option for tls, so it must go within tls.

I fought those because I wanted to put tls in the global block, but it didn’t work :smiley:

Then I tried at the root level, and it didn’t work either.

At last I put it in a snippet and I imported it in every website block.

Only these can appear in global options:

And the only thing that can appear top-level is snippets or site blocks:

1 Like

So I can define one acme CA in the global options, but not several. For that I need several issuer blocks inside tls inside the site block.

why not just simply use the file server which is going to 404 anyway?

i do think a directive to send a file would be convenient though. more intuitive than doing a rewrite with a file server.

Well… There’s no reason for the webserver to check every time if a file is there, when I can tell it there isn’t one.