tailscale / tailscale/caddy-tailscale

Document best practice for a site to listen on Tailscale _and_ other interfaces

Open
#88 5 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Go
Stars
978
Forks
96
PR merge metrics
No merged PRs in 30d

Description

First off, thanks for this module! It's really helpful for integrating Tailscale into an existing Caddy reverse proxy setup with minimal changes!

One thing that wasn't obvious to me right away was how to make a site available on both normal physical interfaces and via a Tailscale node. (My use case: I have Caddy serving a number of different sites on my LAN. I want to expose a proper subset of those sites to a friend via Tailscale node sharing, without needing to spin up a separate Caddy instance for this.)

Let's say I start with this Caddyfile....

# Only listens on physical interfaces.
site.example.com {
  ...
}

If I add in Tailscale like so, the site starts listening on the Tailscale node addresses... but it also stops listening on other interfaces. Totally makes sense, as being able to share privately with Tailscale is important. It's just not the use case I specifically have. :)

{
  tailscale {
    shared {
      auth_key ...
      hostname shared
      state_dir /tailscale
    }
  }
}

# Only listens on Tailscale node.
# (Useful for some cases, but not what I want here.)
site.example.com {
  bind tailscale/shared

  ...
}

I natively tried also binding on [::], but that just causes Caddy to die with a panic: connection already exists error at startup (presumably since I have other sites without a bind directive that already set up servers on [::]:80 and [::]:443):

# It would be nice if this worked, but it doesn't!
site.example.com {
  bind [::] tailscale/shared

  ...
}

The best solution I could find is defining the site twice and using a snippet to share the implementation details:

(site) {
  ...
}

# Listens on non-Tailscale interfaces.
site.example.com {
  import site
}

# Listens on Tailscale node.
site.example.com {
  bind tailscale/shared
  import site
}

I'd be happy to send a quick PR adding an example like this to the README, but first I wanted to double check I'm not just being dumb and missing a cleaner way to enable this pattern without the duplicate site + snippet boilerplate.

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Read the README and compare its Caddyfile examples with the binding and shared-snippet pattern shown in the issue. Confirm whether the duplicate site definitions are the recommended approach, then document the working example and its expected listening behavior in the README.

Written by the indexing model from the issue text.

Assessment

Domain
documentation
Issue type
Documentation
Difficulty
2/5
Estimated time
1-3 hours
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.