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

Feature Request: Support Caddyfile #16

Open
ghost opened this issue Feb 2, 2021 · 29 comments
Open

Feature Request: Support Caddyfile #16

ghost opened this issue Feb 2, 2021 · 29 comments
Labels
enhancement New feature or request

Comments

@ghost
Copy link

ghost commented Feb 2, 2021

I'm creating this issue just to be able to gauge support for Caddyfile being supported in addition to JSON. I'm sure this is already a niche plugin/module and the desire for Caddyfile support is even more niche within that niche...but nonetheless.

@francislavoie
Copy link
Sponsor Collaborator

francislavoie commented Feb 2, 2021

I think caddyserver/caddy#3990 should theoretically make this possible, but uh, it'll still be pretty awkward because it'll be configured via global options, if taking that route.

Ultimately, I think this plugin would need to provide its own config adapter that works similarly to the Caddyfile, but the top-level bits will likely need to work differently. It's not a simple thing to implement though. Maybe call it "Connfile" or "L4file" 😂

The Caddyfile adapter that ships with vanilla Caddy is pretty tightly bound to the http app, which isn't really compatible with the way caddy-l4 is configured (via a layer4 Caddy app, that looks kinda similar to the http app)

@mholt
Copy link
Owner

mholt commented Feb 2, 2021

The Caddyfile format is itself extensible, and is designed to be interpreted by modules other than the http server type. So this is very doable, just needs to be done. I've been very busy lately but we'll see where the sponsorships sway. (Right now they're very heavily leaning in the mainstream Caddy direction.)

The docs at the bottom of this page are relevant: https://caddyserver.com/docs/extending-caddy/caddyfile#server-types

@binaryben
Copy link

Will be awesome to be able to use with the reverse proxy docker image. There is an opposite request for JSON support in that instead, but Caddyfile support in this would be awesome.

@Piehthyte
Copy link

Hi guys, I'm so sorry to necro this, I just wanted to put my support behind this as well, but....
Thank you so much, mholt, for the fantastic work on Caddy. It's really quite awesome(almost insane). I hope some day we do get Caddyfile support for this module, but no stress and for sure no rush. You and all the module makers are doing phenomenal work. Thank y'all!

@francislavoie francislavoie added the enhancement New feature or request label Nov 20, 2021
@mholt
Copy link
Owner

mholt commented Nov 21, 2021

Thanks for the feedback, and the interest in this.

I suppose anyone is welcome to contribute this, it would probably be faster than waiting for me to do it on my own. It's not a small task by any means, but it doesn't have to be as crazy complex as the HTTP Caddyfile, either.

@Piehthyte
Copy link

Thanks for the feedback, and the interest in this.

I suppose anyone is welcome to contribute this, it would probably be faster than waiting for me to do it on my own. It's not a small task by any means, but it doesn't have to be as crazy complex as the HTTP Caddyfile, either.

I am new to go, but I will give it a shot! It'll be a good learning experience.

@mholt
Copy link
Owner

mholt commented Nov 26, 2021

It's a big bite to chew if you're new to Go, but I won't stop you. Good luck!

@RussellLuo
Copy link
Collaborator

Since the best format of multi-app Caddyfile still needs a further discussion (caddyserver/caddy#3990), here is a quick implementation via global options (although not recommended): caddy-ext/layer4.

@francislavoie
Copy link
Sponsor Collaborator

Thanks @RussellLuo! That's a good start. I agree it probably makes sense to have that support as a plugin outside of caddy-l4 for now since there's still room for eventually having proper Caddyfile support as not-global-options 😅

Basically, to get this to actually work properly, the Caddyfile adapter in Caddy's main repo will need significant work to make it more flexible. Right now, too many features are tied to the HTTP Caddyfile so it's not quite viable.

A shower-thought, I think we could add a feature to the core Caddyfile adapter so that passes control of parsing a site block to an alternate implementation (i.e. not HTTP) based on the schemes used in the site address. For example, caddy-l4 could register itself as a handler for tcp:// and udp:// schemes, then a site block with addresses like tcp://:8080, udp://:8080 { would get passed to the caddy-l4 Caddyfile adapter. Obviously the default HTTP Caddyfile would register itself for http:// and https://, but also be the default when no scheme is given. If unknown schemes are seen, or not all schemes in a site address match a single adapter, then it would error out (i.e. no mixing HTTP and L4 addresses for a single site).

I haven't tried implementing this yet cause I don't feel I have time to see this through to the end right now, but unfortunately I feel like Matt or I are probably the ones most equipped to implement this. I still want to welcome enterprising individuals to take a crack at it, but I just have to warn that uh, it's ambitious 😄

@CEbbinghaus
Copy link

I think we could add a feature to the core Caddyfile adapter so that passes control of parsing a site block to an alternate implementation (i.e. not HTTP) based on the schemes used in the site address. For example, caddy-l4 could register itself as a handler for tcp:// and udp:// schemes

This is exactly what I was thinking or at least something akin to it. Although I 100% think that the same subdomain should be able to have both caddy-l4 as well as http caddy rules so a webserver could be run on port 80 while a game server is run on its native port.

I am very invested to see this implemented and ideally as unobstructively to the caddyfile itself as possible so ideally, it becomes a drop-in replacement with only minor or no changes having to be made.

+1 👍🏼 100/10 for that idea.

@mholt
Copy link
Owner

mholt commented Jan 24, 2022

@francislavoie

Right now, too many features are tied to the HTTP Caddyfile so it's not quite viable.

I think it depends what you need to do. Currently, the caddyfile package has all you need to parse a generic Caddyfile. It's up to each individual server type to make the blocks and directives meaningful. We've kind of hacked the "global options" together in the HTTP Caddyfile and it has been used to configure other apps that "support" the HTTP server, but yeah, there's no reason it can't be used for other server types entirely... I guess.

A shower-thought, I think we could add a feature to the core Caddyfile adapter so that passes control of parsing a site block to an alternate implementation (i.e. not HTTP) based on the schemes used in the site address. For example, ...

It's an interesting idea, but I'm afraid it would be a little too limiting. For example, "tcp" is not different from "http", rather, it is a superset of "http"; more precisely, HTTP is served over TCP (and UDP for HTTP/3 -- which is even more confusing), and TCP can be used for other protocols/applications like SSH, etc. I'm not super keen on making server types implicit. At least not for now.

For now, I think the best approach for an L4 caddyfile is to either implement it as its own proper ServerType, or as a global option in the HTTP Caddyfile. Major kudos to @RussellLuo for doing the latter, that's awesome.

@RussellLuo
Copy link
Collaborator

AFAIK, Nginx uses two blocks http and stream:

http {
    #...
    server {
        #...
    }
}
   
stream {
    #...
    server {
        #...
    }
}

almost the same idea as described by Matt.

Given that there are some general options (e.g. logging) for all apps, this may be a possible format of the new Caddyfile:

# General options
{
        debug
}

# HTTP app
http {
        example1.com {
                root * /www/example.com
                file_server
        }

        example2.com {
                reverse_proxy localhost:9000
        }
}

# Layer4 app
layer4 {
        :7070 {
                proxy localhost:8080
        }
}

@mholt
Copy link
Owner

mholt commented Jan 26, 2022

@RussellLuo That's actually pretty close to what I wish I had done for Caddy 2. But it was too late.

Nothing's stopping anyone from making a Caddyfile like that though! caddy adapt --adapter multicaddyfile or something like that. (I don't love the adapter name "multicaddyfile" but you get the idea.)

@francislavoie
Copy link
Sponsor Collaborator

Nothing's stopping anyone from making a Caddyfile like that though!

Actually, what is stopping it is that tons of the code for registering directives and global options are within the httpcaddyfile package. It will require refactoring in caddyserver/caddy for anything like this to be possible.

@mholt
Copy link
Owner

mholt commented Jan 26, 2022

A config adapter doesn't always have to be super extensible, even a different Caddyfile -- I don't think this one will need that. It's a much smaller-scoped project.

@CEbbinghaus
Copy link

I feel a completely separate file that follows the caddy file layout but defines the rules for L4 would be an excellent compromise. wouldn't require a refactor of the caddy project and would have all the benefits of a familiar layout. the only pain would be having to swap back and fourth between the two files to configure sites on both however that seems like a minor price to pay for the ability to use this great package

@KiARC
Copy link

KiARC commented Jun 6, 2023

Just going to add that I would also love to see this functionality, I'm currently trying to run a VPN in a docker container and using this alongside lucaslorentz/caddy-docker-proxy would be so much better than actually binding a bunch of ports directly to the container.

@mholt
Copy link
Owner

mholt commented Jun 6, 2023

(Remember there is a start of an implementation linked above you can try/use for now!)

@voltagex
Copy link

voltagex commented Sep 5, 2023

caddy-l4 could register itself as a handler for tcp:// and udp:// schemes, then a site block with addresses like tcp://:8080, udp://:8080 { would get passed to the caddy-l4 Caddyfile adapter.

I really like that as a design.

I've run across this issue again as the Caddy JSON format has never really clicked with me and I have a need for Caddy's automatic TLS wrapping another application.

@AndreKR
Copy link

AndreKR commented Sep 24, 2023

At least as a temporary solution, would it be possible to put a chunk of JSON into the Caddyfile that is then forwarded to the respective module? This way you could continue using the Caddyfile for HTTP and don't need to switch to JSON just to use the layer4 module.

Something like this:

{
  layer4 {
    json `
      {
        "servers": {
          "example": {
            "listen": [ "127.0.0.1:5000" ],
            "routes": [
              {
                "handle": [
                  { "handler": "echo" }
                ]
              }
            ]
          }
        }
      }
    `
  }
}

mydomain.com {
  root /var/www
}

@ausdrew
Copy link

ausdrew commented Oct 1, 2023

In case this is helpful for anyone else - an alternative approach is to convert your caddyfile to json and then add the layer4 details, I've built this into my deployment actions too.

My repository has a caddy folder with the following files:

./caddy
-- caddyfile (my regular caddyfile with my server's configuration)
-- build-caddy.sh (the below script)
-- layer4.txt (my configuration for l4)

#!/bin/bash

echo "Removing existing caddy.json file"
rm ./caddy.json

echo "Formatting Caddyfile"
caddy fmt --overwrite ./caddyfile
echo "Generating caddy.json file"
caddy adapt --config ./caddyfile --pretty --validate > caddy.json

echo "Reading layer4.txt"
layer4_content=$(<./layer4.txt)

echo "Inserting layer4 content into caddy.json"
jq --argjson layer4 "$layer4_content" '.apps.layer4 = $layer4' ./caddy.json > ./temp.json && mv ./temp.json ./caddy.json

@devsnek
Copy link

devsnek commented Apr 18, 2024

I tried modifying @RussellLuo's work into an Adapter here so it could automatically configure the tls section but its kind of hacky as I'm not really good with golang: https://github.com/devsnek/caddy-l4/blob/servertype/modules/l4caddyfile/caddyfile.go

I've also come across a couple use cases recently where I wanted bring l4 traffic into my existing caddy setup, which I think motivate better integration with the existing httpcaddyfile, and not being a separate config:

  • DNS: I run authoritative DNS servers that support DNS-over-{UDP,TCP,HTTP}. With caddy I'm able to add HTTPS, but for DNS-over-TLS I would need to work non-HTTP TLS termination into my existing caddy config somehow if I want everything to stay centralized.
  • Gemini: A weird niche protocol I have been playing with, which uses TLS. Being able to throw that in my existing config and let letsencrypt churn with the normal dns/http/etc proofs, but use the cert for terminating gemini protocol requests would be slick.

I'm not entirely sure how to make these configs be combined without integrating this into caddy itself though. The global directive can be combined with http, but it can't insert TLS provisioning afaict? Curious if folks have any ideas for improving this.

@mholt
Copy link
Owner

mholt commented Apr 18, 2024

This is something Francis also brought up, and I think I want to try to tackle it later this year. Stay tuned!

@AeonRemnant
Copy link

This is something Francis also brought up, and I think I want to try to tackle it later this year. Stay tuned!

What's the progress so far for Caddyfile support on your end? Bits missing? Where is help needed?
Trying to get some kind of mental inventory of stuff that needs to happen.

@francislavoie
Copy link
Sponsor Collaborator

We want to eventually move caddy-l4 to be part of Caddy's standard distribution (move the code into the main Caddy repo) and once we do that it'll be much easier to implement Caddyfile support. But this is unfortunately still not a top priority right now because there's still so many other pressing tasks to get through first.

@AeonRemnant
Copy link

We want to eventually move caddy-l4 to be part of Caddy's standard distribution (move the code into the main Caddy repo) and once we do that it'll be much easier to implement Caddyfile support. But this is unfortunately still not a top priority right now because there's still so many other pressing tasks to get through first.

Woah hang on what? Caddy is getting L4 support? This has been my single biggest Caddy gripe. O_O

@francislavoie
Copy link
Sponsor Collaborator

Don't hold your breath, it'll take a while.

@AeonRemnant
Copy link

Don't hold your breath, it'll take a while.

Do we have a mega rough ETA? 2024? 2025?

@mholt
Copy link
Owner

mholt commented Apr 29, 2024

Late 2024, perhaps 2025 maybe?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests