V2: Serve Rails application with static assets

I have a Rails6 application that I run on a normal server (no docker). I connect to Puma via socket.

There are static files in folders
/var/www/site/current/public/ as robots.txt Or favicon.ico
/var/www/site/current/public/packs/**/*.css (png, jpg etc) files
(eg. URL /packs/media/images/site-100500.png)

and there are dynamic URL addresses like
/user/{ID}
/page/{PAGE_NAME}

How do I set it up to take turns checking:

  1. if the file exists on the disk in public folder then to give out
  2. if not, send it to reverse_proxy.

An example of my config, but it doesn’t work:

https://site.com {
  root * /var/www/site/current/public

  encode zstd gzip

  file_server
  reverse_proxy / {
    to unix//var/www/site/shared/tmp/sockets/puma.sock
  }
}

This allows you to give away all static files - ok.
Redirects / to Rails application - ok.

But all dynamic addresses of which there are many (like /user/{ID}/something/else{XX}) do not work and give 404.

I need some rule to check if there are any static files on the disk, if not then send them to Rails app.

How can I do this?

Thanks.

In Caddy v2, request matching is exact-match, so a path matcher of / for your proxy will only match requests to the root of your site and nothing else. Just remove that /. See the request matching docs here for more detail on how it works:

You can also move the socket to the same line instead of using the to subdirective, it reads cleaner in my opinion:

reverse_proxy unix//var/www/site/shared/tmp/sockets/puma.sock

Anyways, what you want to do is something like this:

@notStatic {
	not file
}
reverse_proxy @notStatic unix//var/www/site/shared/tmp/sockets/puma.sock

This will make the reverse_proxy only match requests when the requested path is not a file that exists on disk. You could further limit this to only requests in your public dir by adding not path /public/* in the named matcher.

The reason for taking the approach of excluding requests to reverse_proxy is because the default directive order for Caddyfile config has reverse_proxy sorted before file_server, so you either need to exclude the reverse_proxy from handling certain requests that you want to have served statically, or you need to reorder the file_server before reverse_proxy and add a matcher on file_server to only match requests to /public/* etc.

3 Likes

very helpful! thanks a lot, it works!

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