Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Layered Complexity in Configuration #1

Open
johnpyp opened this issue Mar 1, 2024 · 7 comments
Open

Layered Complexity in Configuration #1

johnpyp opened this issue Mar 1, 2024 · 7 comments
Labels
F-Configuration Functionality relating to configuration
Milestone

Comments

@johnpyp
Copy link

johnpyp commented Mar 1, 2024

This project looks awesome, and something I've been waiting for for years.

Something I noticed was not touched on very heavily was the topic of where this fits in the "complexity hierarchy" of existing tools, and not really calling out complexity or minimal complexity as a goal/non-goal.

I imagine Caddy is a point of inspiration for the project to some degree, given the automatic tls provisioning - something else I think worth looking at Caddy for is the Caddyfile, and the way they approach layered complexity. Caddy does a really, really good job at making it dead simple to have an https proxy up and running with completely sane defaults. I'd hate to see River go down the route of nginx, haproxy or envoy requiring either extensive configuration (like nginx, envoy), or using very technical vocabulary and organizational concepts (like haproxy, envoy) to do the basics. On the other hand, in no way does a simple entrypoint for common usecases preclude the full complexity and scope of those other projects - it just needs to be "layered".

Power users and beginners who have never used a reverse proxy should be able to pick up River and do what they need to without significant unexpected behavior or poor defaults. This will end up with more work on the "thoughtful interfaces" side of building river, but I think the investment is worth it.

Anecdotally, I understand that Caddy lacks in the power, performance, and reliability that the other mentioned proxies have - but still I use it as my default to start because of how easy it is to configure, and the automatic tls. It would be amazing for River to still be able to fill that same role, because then it may be close to a real zero-compromises experience :)

@cxw620
Copy link

cxw620 commented Mar 1, 2024

There's a great news that ACME support must be introduced in River according to docs of TODOs.

@glauber1992
Copy link

👏

@jamesmunns jamesmunns added the F-Configuration Functionality relating to configuration label Mar 25, 2024
@jamesmunns jamesmunns added this to the Kickstart Spike 1 milestone Mar 25, 2024
@jamesmunns
Copy link
Collaborator

Hey @johnpyp, thanks for the shout! If you have any favorite docs from Caddy that demonstrates how they achieve that, I'd appreciate it! I'm starting https://github.com/memorysafety/river/milestone/1 today, and getting some of the configuration work started and planned out is on the table.

I'm most familiar with nginx's configuration format, but I'll definitely start looking at Caddy's docs soon.

@johnpyp
Copy link
Author

johnpyp commented Mar 26, 2024

Totally, here's one example I like off the top of my head, and I'll comment some more later:

File server - https://caddyserver.com/docs/caddyfile/directives/file_server

(Not to suggest a file server fits into river necessarily, just a nice api)

To serve some files from your site, in the most basic form, you just do something like this:

example.com {
  fileserver /static/*
}

With this, you can hit example.com/myfile.txt and download it. Now, you want to add a basic file browser? Add the browse parameter:

example.com {
  fileserver /static/* browse
}

This probably already covers 80% of the common usecases, without any nested configuration or "opinions" really having to be decided on. The 80/20 rule is really useful for thinking about this, and Caddy seems to follow it - 80% of the usecases can usually be done with opinionated, good defaults in one line of config.

For the 20%, you go into extra options with a simple nesting extension, like this:

example.com {
  fileserver /static/* browse {
    hide .git # Hide files matching pattern
    pass_thru # Forward requests to the next http handler instead of a 404, if there's no match
    index index.txt # Set my "index file" as index.txt
    # ...
  }
}

I think the hardest parts about making some really good configuration apis like this are:

  1. Identifying the 80/20 upfront - it sucks when basically every user has to add configuration to do the same thing, because the api wasn't thought about in the first place. In my experience with nginx, this is super common - I have to specify compression support, forwarding completely industry-standard forwarding headers, set ssl caching settings, ssl stapling, ssl ciphers, etc. etc. etc. - it's a really big opportunity for me to forget things and end up less secure than otherwise.

  2. Working reasonable defaults into backwards compatibility guarantees - As a policy decision, it can be tricky to decide how best to treat reasonable defaults. How do you change them without breaking customers, and without forcing large amounts of your userbase to do "migrations"? I'd just make sure to think about this upfront, and think about how this might influence the api design.


Finally, to help mitigate the effects of repetitive configuration (if something can't be done concisely or clearly), I'd strongly advocate for some level of metaprogramming capability in whatever the configuration format takes, and not requiring other preprocessing tools to do so.

I think Caddy does a good job here too, with basic reusable snippets and basic "parameter" passing to those snippets: https://caddyserver.com/docs/caddyfile/concepts#snippets

Comparatively, I remember Nginx not supporting environment variables (I think they support it now) for the longest time, and the amount of pain and random bugs that little separation of preprocessing and templates caused.

@jamesmunns
Copy link
Collaborator

Thanks @johnpyp, that's perfectly illustrative!

I think this does get into "designing a configuration language" territory - which is reasonable, but i'm unsure when it'll be scheduled.

@jamesmunns
Copy link
Collaborator

I've written up an RFC regarding this here: #13, if you have any feedback I'd appreciate it!

@jamesmunns
Copy link
Collaborator

Moving this to the backlog until we tackle the "later" parts mentioned in #13

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
F-Configuration Functionality relating to configuration
Projects
None yet
Development

No branches or pull requests

4 participants