Skip to content

feat/add tailscale module#849

Open
dy-ma wants to merge 15 commits intocoder:mainfrom
dy-ma:feat/add-tailscale-module
Open

feat/add tailscale module#849
dy-ma wants to merge 15 commits intocoder:mainfrom
dy-ma:feat/add-tailscale-module

Conversation

@dy-ma
Copy link
Copy Markdown

@dy-ma dy-ma commented Apr 17, 2026

Description

Adds a Tailscale module that installs Tailscale and joins the workspace to a tailnet on startup.

Supports:

  • OAuth client credentials flow (default) or a pre-generated auth key
  • Kernel and userspace networking (auto-detected, or set explicitly)
  • Tailscale SSH, subnet route advertising, MagicDNS, ephemeral/persistent nodes
  • SOCKS5 and HTTP proxies in userspace mode

Tailscale seemed like an obvious fit for a Coder module and I was surprised one didn't already exist. I needed it for my own deployments so I built it.

This is my first open-source contribution. I've done my best to follow the contribution guidelines, but please tell me if I've done something horribly wrong.

Type of Change

  • New module
  • New template
  • Bug fix
  • Feature/enhancement
  • Documentation
  • Other

Module Information

Path: registry/dy-ma/modules/tailscale
New version: v1.0.0
Breaking change: [ ] Yes [x] No

Template Information

Path: registry/[namespace]/templates/[template-name]

Testing & Validation

  • Tests pass (bun test)
  • Code formatted (bun fmt)
  • Changes tested locally

Related Issues

None

Generated with Claude Code using Claude Sonnet 4.5

@35C4n0r 35C4n0r self-requested a review April 20, 2026 16:37
@35C4n0r
Copy link
Copy Markdown
Collaborator

35C4n0r commented Apr 20, 2026

@dy-ma can you fix the failing test ?

@dy-ma
Copy link
Copy Markdown
Author

dy-ma commented Apr 28, 2026

Fixed the ShellCheck failure - sudo doesn't affect redirects, so I changed line 96 from &> /tmp/tailscaled.log to use sudo tee instead.

The fix passes ShellCheck locally. Ready for another review when you have a chance.

@matifali
Copy link
Copy Markdown
Member

Hi @dy-ma, can you update the module to conform with instructions in AGENTS.md?

@dy-ma
Copy link
Copy Markdown
Author

dy-ma commented Apr 29, 2026

As far as I can see, the only non-conformance was the Tailscale icon being referanced via CDN link instead of local path. I initially wasn't sure of the correct approach for adding new icons, but since I had already added the icon to .icons/ for the README, I've updated the module to use the local path as well.

Also, I wasn't aware of the AI attribution policy, so I edited my comment. I appreciate the patience, as this is my first open source contribution.

data "coder_workspace" "me" {}

locals {
icon_url = "${path.module}/../../../../.icons/tailscale.svg"
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This will not work. Coder can only show bundled icons or something accessible over the network.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

I see. The guidelines mention the README icon must be a local path. There isn't a bundled Tailscale icon. Is the correct approach for me to add the icon in .icons, but only reference it for the README, and use a network call for the module?

Comment on lines +182 to +209
resource "coder_script" "install_tailscale" {
agent_id = var.agent_id
display_name = "Tailscale"
icon = local.icon_url
script = templatefile("${path.module}/run.sh", {
TAILSCALE_API_URL = var.tailscale_api_url
AUTH_KEY = var.auth_key
OAUTH_CLIENT_ID = var.oauth_client_id
OAUTH_CLIENT_SECRET = var.oauth_client_secret
TAILNET = var.tailnet
HOSTNAME = local.hostname
TAGS_JSON = local.tags_json
TAGS_CSV = local.tags_csv
EPHEMERAL = var.ephemeral
PREAUTHORIZED = var.preauthorized
NETWORKING_MODE = var.networking_mode
SOCKS5_PORT = var.socks5_proxy_port
HTTP_PROXY_PORT = var.http_proxy_port
ACCEPT_DNS = var.accept_dns
ACCEPT_ROUTES = var.accept_routes
ADVERTISE_ROUTES = join(",", var.advertise_routes)
SSH = var.ssh
EXTRA_FLAGS = var.extra_flags
STATE_DIR = var.state_dir
})
run_on_start = true
run_on_stop = false
}
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

You could try using the coder-utils module to manage installation and start the service.

This would also help comply with the suggested logs storage preference.

Copy link
Copy Markdown
Member

matifali commented Apr 29, 2026

.icons is for the registry.coder.com and this repo.
But for the scripts to show this icon on real coder deployments we need the icon refrenced from built-in icons at coder/coder or a network path.

@dy-ma
Copy link
Copy Markdown
Author

dy-ma commented Apr 29, 2026

I split run.sh into install.sh and start.sh, and used the coder_utils module to orchestrate them, and added a module directory for logging (I believe this is what you were mentioning by "log storage preference"?)

I considered using a post-install configuration, but in order to configure tailscale, the daemon needs to be running first, and I figure I'd want the flags to be reapplied on restart anyways. So I kept it to just a start.sh.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants