Skip to content

blog: Tailscale for DDEV: Simple and Secure Project Sharing#423

Merged
rfay merged 38 commits intoddev:mainfrom
atj4me:main
Sep 9, 2025
Merged

blog: Tailscale for DDEV: Simple and Secure Project Sharing#423
rfay merged 38 commits intoddev:mainfrom
atj4me:main

Conversation

@atj4me
Copy link
Contributor

@atj4me atj4me commented Aug 26, 2025

The Issue

Add blog post about ddev-tailscale-router add-on covering integration with Tailscale for secure development environment sharing, cross-device testing, and stable webhook endpoints.

How This PR Solves The Issue

This PR adds a comprehensive blog post that introduces the ddev-tailscale-router add-on to the DDEV community. The post covers:

  • How the add-on extends DDEV's capabilities with Tailscale networking
  • Installation and configuration instructions
  • Practical use cases for webhook development, OAuth callbacks, and cross-device testing
  • Technical considerations and troubleshooting guidance
  • Comparison with existing DDEV sharing solutions

Manual Testing Instructions

Review https://20250827-atj4me-tailscale.ddev-com-front-end.pages.dev/blog/tailscale-router-ddev-addon/

  1. Verify the blog post renders correctly in the Astro build
  2. Check that all external links are functional
  3. Confirm the frontmatter follows DDEV.com blog post standards
  4. Ensure code blocks display properly with syntax highlighting
  5. Test that the post appears in the blog listing with correct categories

Automated Testing Overview

No automated tests are needed for this content addition. The blog post follows standard Markdown formatting and DDEV.com content guidelines.

Related Issue Link(s)

Release/Deployment Notes

This is a content-only addition with no code changes. The blog post will be published to the DDEV.com blog upon merge and deployment.

Copy link
Member

@stasadev stasadev left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I pushed a branch for this https://20250827-atj4me-tailscale.ddev-com-front-end.pages.dev/blog/tailscale-router-ddev-addon/

  1. Please run ddev prettier to fix formatting issues.
  2. Maybe add some image to the blog, AI generated is good too.

@rfay rfay added this to Next TODOs Aug 27, 2025
Copy link
Member

@rfay rfay left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks so much for this contribution!

It looks like AI had a big hand in it, and that doesn't appear to be acknowledged here.

  • Please massively simplify and shorten in general. You want people to actually read it.
  • Remove the intro stuff about how good DDEV is
  • Remove the stuff about how good Tailscale is and replace it with a simple explanation of what Tailscale is.
  • Simplify sharing into just a statement that ddev share uses ngrok but there are other ways. Link to the docs.
  • In "Introducing ddev-tailscale-router" make it "ddev-tailscale-router Add-on"
  • Then simplify it massively. Just say what it does and how to use it.

In general: Remove all the AI stuff and simplify it to say just what you want to say about the add-on and why you made it.

@atj4me
Copy link
Contributor Author

atj4me commented Aug 27, 2025

@rfay

I wouldn't say massive, but I mostly used it to make my writing more professional and in Laymans terms, and to refactor to markdown. I also took some time to write intros to everything, since this is first time I am actually writing like this, since I mostly write on Linkedin or Medium. So pardon my ignorance. I learn something new everyday!

I will make this more concise as per your sugggestions

@rfay
Copy link
Member

rfay commented Aug 27, 2025

Thank you. I've been using AI quite a lot myself, and finding it very useful. But it can be way, way too verbose a lot of times. Please do add credit at the bottom saying what you used and what for.

@atj4me
Copy link
Contributor Author

atj4me commented Aug 27, 2025

@stasadev
@rfay

I added an SVG from claude and made it concise. Cut down a lot of explanation and just the core data on the addon.

Let me know your thoughts on the same.

@atj4me
Copy link
Contributor Author

atj4me commented Aug 27, 2025 via email

@rfay
Copy link
Member

rfay commented Aug 27, 2025

It is a docker image, so as long as docker runs the image, it should work!

That is not correct at all. For more background, see this and related blogs:

https://ddev.com/blog/amd64-with-rosetta-on-macos/

@stasadev
Copy link
Member

https://hub.docker.com/r/tailscale/tailscale/tags has arm64 arch.

But I'm not sure if the add-on itself is compatible with macOS.

@atj4me
Copy link
Contributor Author

atj4me commented Aug 27, 2025

@stasadev

I think it works with UserSpace Networking. I tested it locally, and it worked and platform independent. I will do a whole lot of testing on other devices just to make sure.

BTW, I added a disclaimer that it hasn't been tested on Mac

@stasadev
Copy link
Member

I think it works with UserSpace Networking.

Pinned comment https://www.youtube.com/watch?v=tqvvZhGrciQ says:

I don’t understand the Compose yaml at @6:45. If you don’t define it, TS_USERSPACE will default to true, and not need the /dev/net/tun and net_admin/sys_module capabilities. So either remove those lines and run in userspace, or leave them in and also add TS_USERSPACE=false. The combination as shown seems self-contradictory.

@atj4me
Copy link
Contributor Author

atj4me commented Aug 27, 2025

@stasadev

When I was developing the addon, it didn't worked with UserSpace Networking true. So I shuffled around a couple of configurations to make it work on 2 projects, and one of them was to turn it off. I don't know what changed, I turned it back on and it seems to be working for me. So I will test it on a fresh install and then push that change.

Tailscale also recommends to have this container as a sidecar container to handle all traffic ( using network_mode ) which doesn't apparently work with ddev.

This particular mix is slightly different from the usual use cases of running tailscale in a container, because I am literally using an addon solution of tailscale as the main factor in this addon, the funnel and serve. It is like a small slice of a big pie!

@atj4me
Copy link
Contributor Author

atj4me commented Aug 27, 2025

@rfay @stasadev

I made the changes and released an update here: https://github.com/atj4me/ddev-tailscale-router/releases/tag/2.5

I tested it on my mac, and it was working for me. So I removed the disclaimer.

Ideally, it now uses user space networking now. Tailscale doesn't have much documentation on whether one compliments the other, but it seems to be working! Hope others will try it out and gave feedback.

Also, I kept the TS_USERSPACE in the docker-compose and setting the value as true , instead of relying on the default.

@rfay
Copy link
Member

rfay commented Aug 27, 2025

Awesome. I assume it's an arm64/Apple Silicon mac?

@atj4me
Copy link
Contributor Author

atj4me commented Aug 27, 2025

@rfay I don't exactly know. Mine is a 2013 Macbook Air with Intel chip. But I hope it works on new ones too, just need someone to test it 😄

@stasadev
Copy link
Member

stasadev commented Sep 9, 2025

AFAICT, the only thing left is to add the ACL settings for TS_PRIVACY=public to https://github.com/atj4me/ddev-tailscale-router#prerequisites
and update this blog.

@atj4me
Copy link
Contributor Author

atj4me commented Sep 9, 2025

@stasadev

Done :)

@stasadev
Copy link
Member

stasadev commented Sep 9, 2025

There is some difference between README.md and this blog.

For example, prerequisites are explained better in README.md, along with usage for TS_AUTHKEY and .ddev/.env.tailscale-router and ~/.bashrc.

@stasadev
Copy link
Member

stasadev commented Sep 9, 2025

Sorry to be a pain, I just want it to look good in both places.

@atj4me
Copy link
Contributor Author

atj4me commented Sep 9, 2025

@stasadev

Sorry, I forgot about the changes in readme. It has been to and fro between readme and this blog. Now I have updated it, didn't include the Tailscale Funnel ACL rule in the blog, as it might change leaving readers with incorrect content. So I added references

@stasadev stasadev self-requested a review September 9, 2025 14:31
@atj4me atj4me requested a review from rfay September 9, 2025 14:32
@rfay
Copy link
Member

rfay commented Sep 9, 2025

First time setup on two devices (not one) is a requirement, otherwise auth key is not available at all.

So that was why I couldn't get auth key.

Copy link
Member

@stasadev stasadev left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add information that certificates may take some time to generate (or even add example how to add them manually) because it is confusing when you install the add-on, start the DDEV project, open the Tailscale URL, and it doesn't work.

It works quite unpredictably with TS_PRIVACY=public, I couldn't open it for 10 minutes for some site and then it suddenly started working. Then I deleted the project's device in Tailscale, restarted the project, and it doesn't work for public (but works for private) - I think that's what you mentioned in atj4me/ddev-tailscale-router#13

I don't see such issues with TS_PRIVACY=private.


Edit: or don't add the information I asked for here, it's probably too much for a blog, but add that to README.md, maybe create a new section for Troubleshooting, and add a link from README.md to this blog.

Edit2: and now I waited for 25 minutes, and TS_PRIVACY=public finally worked.

ddev restart
```

> **Note:** For public access, you need to configure your [Access Control List (ACL)](https://tailscale.com/kb/1223/funnel#funnel-node-attribute) to enable Funnel. See the [Tailscale Funnel documentation](https://tailscale.com/kb/1223/funnel) for details on setting up the required ACL policy.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

BTW, it is not clear in their documentation where the "Add funnel to policy" button is located.

But I don't think it's our problem to solve.

You have to:

  1. Open https://login.tailscale.com/admin/acls
  2. Click on "JSON editor"
    image
  3. Scroll down in the right sidebar to see "Add Funnel to policy"
    image

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

They added that UI very recently. It wasn't there in July. I guess they still haven't updated the Readme, since this is still in Beta


Before installing the add-on, you need to set up Tailscale:

1. **Install Tailscale** on at least two devices (phone, tablet, or computer) by following the [installation guide](https://tailscale.com/download). This is required to generate an auth key.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tested removing all devices, and it didn't ask me to add more again, so it's really first time setup, that can block people.

@stasadev
Copy link
Member

stasadev commented Sep 9, 2025

Or don't add the information I asked for here, it's probably too much for a blog, but add that to README.md, maybe create a new section for Troubleshooting, and add a link from README.md to this blog.

@atj4me
Copy link
Contributor Author

atj4me commented Sep 9, 2025

@stasadev I just added a note on the blog. And the certificate issuance is from LetsEncrypt. They are unpredictable. Once you set it up, it won't regenerate the certificate again. And it worked for me with an insecure certificate until it got issued.

Don't think that has to do with the blog anyways

@stasadev
Copy link
Member

stasadev commented Sep 9, 2025

I just added a note on the blog.

Some new note? I don't see any new changes.

Don't think that has to do with the blog anyways

Agreed.

Copy link
Member

@stasadev stasadev left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me.

@rfay
Copy link
Member

rfay commented Sep 9, 2025

I show a valid (?) Let's Encrypt cert, but it's not trusted.

The apparent error is this:

net::ERR_CERTIFICATE_TRANSPARENCY_REQUIRED

Certificate Transparency:
SCT DigiCert 'Wyvern2025h2' Log (Embedded in certificate, Verified)
SCT Google 'Xenon2025h2' log (Embedded in certificate, Invalid timestamp)
image

@rfay
Copy link
Member

rfay commented Sep 9, 2025

I tried it on phone, and it connected fine.

Then I restarted Chrome on macOS and it connected fine. Might have been passage of time or something else?

Copy link
Member

@rfay rfay left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a great addition to DDEV sharing techniques! Thanks for sticking with this all the way! It's still a little tweaky, but I'm interested in what else I can learn about tailscale and other usages.


To switch between modes:

Switch to public mode (accessible to anyone on the internet):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since this requires extra config ("For public access", hidden below!), it should be stated here in advance. (You don't have to fix this right now, but it would be nice to fix it later maybe.)

And I haven't found a way to enable funnel, I got lost at this point:

Image

@rfay
Copy link
Member

rfay commented Sep 9, 2025

One note: This has the same problem as any other sharing technique with WordPress and Magento* (and occasionally some other CMS types), which embed the URL in their database, etc. So won't work OOTB with those.

@rfay
Copy link
Member

rfay commented Sep 9, 2025

Thanks for the great work on this! Amazing. It's a great new addition.

You can do PRs to this as time goes on to maintain it, and of course you can maintain and improve the add-on readme.

@rfay rfay merged commit 296d194 into ddev:main Sep 9, 2025
1 check passed
@rfay
Copy link
Member

rfay commented Sep 9, 2025

@rfay
Copy link
Member

rfay commented Sep 9, 2025

I was going to promote this on the socials, if you give me your various socials I'll tag you. Feel free to PR them into your https://ddev.com/blog/author/ajith-thampi-joseph/ as well, thanks!

@atj4me
Copy link
Contributor Author

atj4me commented Sep 9, 2025

@stasadev @rfay

I added a note as seen in the screenshot. Anyone who wants to use funnel, can go through official docs.

Screenshot_20250909_153706_Chrome

And when I build URL dependent sites, I make the TS one main.

@atj4me
Copy link
Contributor Author

atj4me commented Sep 10, 2025

I was going to promote this on the socials, if you give me your various socials I'll tag you. Feel free to PR them into your https://ddev.com/blog/author/ajith-thampi-joseph/ as well, thanks!

My linkedin is https://www.linkedin.com/in/thampiajit and is kind of the only social I actively use nowadays. thampiajit is my handle on most social platforms, though I am not active in them.

This is a great addition to DDEV sharing techniques! Thanks for sticking with this all the way! It's still a little tweaky, but I'm interested in what else I can learn about tailscale and other usages.

It isn't supposed to be used this way, but this works better for me. My initial use case with TS was remote development, like instead of setting up OpenVPN server or other VPN, I can just install a simple software on all my devices and login, allowing me to access my home server from anywhere in the world, connected to internet and secure. Since I use a server to run ddev and connect using VSCODE Remote SSH for coding, this was the only viable option for me to work, as I can work from anywhere and use the same URL to access ( so no need to change APP_URL in the .env files everytime ). It is a specific usecase, but one I depend on heavily!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

3 participants