Skip to content

feat(config): add TSDPROXY_* env var override system#384

Open
pdevito3 wants to merge 1 commit intoalmeidapaulopt:mainfrom
pdevito3:fix/env-overrides-and-oauth-expiry
Open

feat(config): add TSDPROXY_* env var override system#384
pdevito3 wants to merge 1 commit intoalmeidapaulopt:mainfrom
pdevito3:fix/env-overrides-and-oauth-expiry

Conversation

@pdevito3
Copy link
Copy Markdown

@pdevito3 pdevito3 commented Mar 2, 2026

Summary

Fixes #256 — I've been using this on my NAS successfully with OAuth via env vars in Docker Compose.

Adds a general TSDPROXY_* environment variable override system so users can configure tsdproxy via env vars (e.g. in Docker Compose) without mounting a YAML config file. This allows OAuth credentials (clientId, clientSecret) and other sensitive settings to be supplied securely through environment variables instead of being committed to version control.

Naming convention: TSDPROXY_<UPPERCASED_YAML_PATH> with underscores between levels. Map fields (docker, providers) consume one segment as the map key, auto-creating entries with default values when the key doesn't exist. Multi-word yaml tags (e.g. defaultProxyProvider) are matched greedily without separators.

Legacy first-run env vars (TSDPROXY_AUTHKEY, TSDPROXY_AUTHKEYFILE, TSDPROXY_CONTROLURL, TSDPROXY_DATADIR, TSDPROXY_HOSTNAME) are excluded so the override system doesn't conflict with the existing generateDefaultProviders flow.

Changes

  • internal/config/envoverride.go — New env var override system that maps TSDPROXY_* env vars to config fields
  • internal/config/envoverride_test.go — Tests for the env override system (19 cases)
  • internal/config/config.go — Integrate env override into config loading (6-line hook after defaults.Set)
  • docs/content/docs/v2/serverconfig.md — Document env var override usage
  • docs/content/docs/v2/advanced/tailscale.md — Document Docker Compose with env-var OAuth credentials

Test plan

  • Unit tests for env var override mapping (`envoverride_test.go`, 19 cases pass)
  • Verified OAuth flow works end-to-end on personal NAS deployment with credentials supplied entirely via `TSDPROXY_TAILSCALE_PROVIDERS_DEFAULT_*` env vars

@sbrocket
Copy link
Copy Markdown

Though it appears unlikely this will get merged unless someone new gets motivated to pick up maintenance, I'm bandaiding fixes onto my own fork for now (for my own purposes only...configuring proxies just by setting a few Docker labels is too nice an interface compared to any alternative I've found yet) and appreciate you contributing this fix. Thanks!

Copy link
Copy Markdown
Owner

@almeidapaulopt almeidapaulopt left a comment

Choose a reason for hiding this comment

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

Thank you for this excellent contribution, @pdevito3! I really appreciate the thorough test coverage.\n\nI've reviewed both parts of this PR:\n\n### OAuth Key Expiry Fix ✅\nThis is a genuine bug fix — cached OAuth keys were being reused without checking expiry, which would cause authentication failures. The implementation is clean:\n- isExpired() with a 5-minute buffer is a good practice\n- Zero-value Expires (legacy cache files) correctly treated as expired\n- Great test coverage for edge cases\n\n### Environment Variable Override System ✅\nThis is a much-requested feature. The implementation is well-designed:\n- Greedy matching for multi-word YAML tags is clever\n- Auto-creation of map entries with defaults is the right behavior\n- Legacy env var exclusion prevents conflicts\n- Comprehensive test suite (15+ test cases)\n\n### Blocking Issues:\n1. Merge conflicts — This PR has conflicts with the base branch that need to be resolved. Could you please rebase on the latest main?\n2. Dockerfile changes — The Dockerfile modification adding VERSION build arg may conflict with the goreleaser build pipeline (which handles version injection via ldflags). This needs careful consideration.\n3. API changeKeys().CreateKeys().CreateAuthKey — is this a method rename in a newer version of the Tailscale client, or a custom change? Want to make sure this is compatible.\n\nCould you rebase and we can move forward with this? Thanks again for the great work! 👏

Add a general TSDPROXY_* environment variable override system so users can
configure tsdproxy via env vars (e.g. in Docker Compose) without mounting a
YAML config file.

Naming convention: TSDPROXY_<UPPERCASED_YAML_PATH> with underscores between
levels. Map fields (docker, providers) consume one segment as the map key,
auto-creating entries with default values when the key doesn't exist.
Multi-word yaml tags (e.g. defaultProxyProvider) are matched greedily without
separators.

Legacy first-run env vars (TSDPROXY_AUTHKEY, TSDPROXY_AUTHKEYFILE,
TSDPROXY_CONTROLURL, TSDPROXY_DATADIR, TSDPROXY_HOSTNAME) are excluded so the
override system doesn't conflict with the existing generateDefaultProviders
flow.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@pdevito3 pdevito3 force-pushed the fix/env-overrides-and-oauth-expiry branch from c73203e to f58b5d2 Compare May 1, 2026 21:00
@pdevito3 pdevito3 changed the title feat: add env var config overrides and fix OAuth key expiry feat(config): add TSDPROXY_* env var override system May 1, 2026
@pdevito3
Copy link
Copy Markdown
Author

pdevito3 commented May 1, 2026

Thanks for the thorough review! Pushed an update that addresses all three blocking concerns by narrowing the PR scope to just the env var override system.

1. Merge conflicts — fixed. Rebased onto current main (post 3880868) as a single clean commit on a fresh branch. No more conflicts.

2. Dockerfile VERSION build arg — dropped. Agreed it was out of scope and the goreleaser concern is fair. Removed entirely; this was a separate issue not needed in here

3. Keys().CreateCreateAuthKey — dropped along with the OAuth fix. For context: Create is actually marked // Deprecated: Use CreateAuthKey instead in tailscale.com/client/tailscale/v2 (both v2.0.0 and v2.9.0), so the rename was real, not a custom hack. But it's moot now — see below.

OAuth key expiry fix — dropped. Your d4a2e3c ("stop caching single-use OAuth keys and auto-recover stale tsnet state") supersedes my fix entirely. I actually noticed this myself in my private fork and i jsut hadn't got to update this pr as i didn't think it was going anywhere 😅

So the PR is now scoped to just the env var override feature: 5 files, single commit, all 19 unit tests pass, and I've been running this in production on my NAS for a couple of months with OAuth credentials supplied via TSDPROXY_TAILSCALE_PROVIDERS_DEFAULT_CLIENTID/CLIENTSECRET/TAGS env vars in docker-compose.

Let me know if you'd like any other changes!

@pdevito3
Copy link
Copy Markdown
Author

pdevito3 commented May 1, 2026

btw @almeidapaulopt i'm going to make a separate PR for another issue i noticed in my fork but don't want to muddy up this PR with it

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.

Ability to use OAuth credentials securely in v2

3 participants