trouble getting [[statics]] to work

I’m running a node docker app on a custom subdomain, devnull.noreply.zone. That app/domain only does email things, but I’d like to host some html there to explain what it does in case people manually navigate to it. I was excited to see that the [[statics]] config would save me from going multi-process to do this, but I’m having trouble getting it to work.

Here’s my fly.toml:

app = "noreplyzone-ingress"

kill_signal = "SIGINT"
kill_timeout = 5

[env]

[experimental]
  auto_rollback = true

[[statics]]
  guest_path = "/app/static"
  url_prefix = "/"

[[services]]
  http_checks = []
  internal_port = 25
  protocol = "tcp"
  script_checks = []

  [services.concurrency]
    hard_limit = 25
    soft_limit = 20
    type = "connections"

  [[services.ports]]
    port = 25

  [[services.ports]]
    port = 465

  [[services.ports]]
    port = 587

I use fly to build my image, and I think the file is set up properly going by this:

$ flyctl ssh console
Connecting to top1.nearest.of.noreplyzone-ingress.internal... complete
# cat /app/static/index.html
<html>
  This domain handles mail processing for <a href="https://www.noreply.zone/">www.noreply.zone</a>.
</html>

There’s nothing in the logs about statics. flyctl config display shows this under statics (the processes bit seems interesting, but I’m not sure what it should show normally):

    "statics": [
        {
            "cache_key": "___app_static",
            "guest_path": "/app/static",
            "processes": [],
            "url_prefix": "/"
        }
    ]

Any ideas? I feel like I must be missing something obvious.

Hi @simon-weber

I may be wrong but I think you need a service in your fly.toml that operates on external port 80/443 for statics to work. I don’t think you actually need any web serving running in your container though so you could just set the internal port to a dummy port that you know won’t be used.

1 Like

Yeah - statics may not be ideal for this case. You still need a service on the 80/443 ports with the HTTP handler (and TLS on 443 if you want that). There may also be issues with health checks on these ports causing downtime. So probably it’s better to run a small HTTP service even though it means going multiprocess.

Oh, that’s a surprise to me. The docs say “this means you don’t even need to run a web server in your VM” – I’d read that to mean any http server, but I guess it means running something like nginx in addition to your app in something like gunicorn?

It turns out haraka can run an http server without much trouble so I can use that for now, but I’d much rather have fly do it for me!

Another note now that I’ve got this running: I was surprised that requesting / didn’t map to index.html. It does work if I request /index.html. Is there another convention statics uses to serve directory roots?

Nope, no convention for that. Statics was really designed to allow full stack apps to offload delivery of static assets. More interest here on this forum should encourage us to make it better :slight_smile:

I’ll update the docs as it’s definitely misleading!

3 Likes

@jsierles Is url_prefix = "/" valid for statics blocks when an app does have a web service running? I’m wondering if it is possible to configure one statics block that covers every directory inside guest_path, instead of adding each individual directory? Any request for a path that doesn’t exist inside guest_path should fall back to the web service.

This scenario isn’t mentioned in the documentation, but in my initial testing I’m seeing every request time out for both static assets and valid application routes.

One statics block should work. Timeouts for all requests would mean something else is up. Is your service running on the same port as internal_port in fly.toml?

@jsierles Yes, the service is running on internal_port, and is working without the ``[[statics]]` block.

[[statics]]
  guest_path = "/app/public"
  url_prefix = "/"

I’ve switched to defining more than one [[statics]] block as a workaround (one block for each directory inside /app/public), but would prefer to define one catch-all for all static files if it is possible to do that.