Tailnet join follows the provider, not the service - #9
Merged
Conversation
TAILSCALE_ENABLED is service-global, and provision() read it as every host joins: join credentials, bootstrap script, internal_ssh_host, device discovery. A docker host is a local container with no path onto the tailnet, so the docker provider failed fast — a tailnet-mode drukbox could not serve docker hosts at all, and one box serving remote agent VMs over the tailnet plus local browser containers needs exactly that. Providers now declare supports_tailnet beside the other per-provider traits; docker leaves it False. provision() binds the tailscale client only for providers whose hosts can join, so a docker host under a tailnet-mode service skips the join entirely and keeps its published 127.0.0.1 port as the only path. The docker provider's fail-fast on a setup script stays as the backstop. ENG-857
czpython
force-pushed
the
commonzenpython/eng-857-tailnet-per-provider
branch
from
August 17, 2026 10:29
4f0ccc8 to
94fe4fc
Compare
czpython
added a commit
that referenced
this pull request
Aug 18, 2026
Review fixes: declare supports_tailnet=False (base gained the flag in #9 after this branch was drafted — without it a tailnet-mode service minted and leaked a Tailscale auth key per create), stop the template entrypoint truncating authorized_keys on restart, anchor the not-found stderr match to the CLI's own message so an auth failure can't be read as sandbox-gone and destroy live state, translate workspace mkdir errors at the provider boundary, attempt sandbox removal when create fails partway, bracket IPv6 publish specs, honor ssh_username in the bootstrap script, bound sbx calls at 600s, and move workspace rmtree off the event loop. Test prunes: drop config-mirroring and implementation-detail tests, merge the port-parse and binary-launch variants, move diagnose coverage to test_diagnose.py per docs/add-a-provider.md. Docs: networking.md and security.md now name the provider; deploy.md notes the missing SERVICE_LABEL mechanism.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
TAILSCALE_ENABLEDis service-global, andprovision()read it as "every host joins the tailnet": join credentials, bootstrap script,internal_ssh_host, device discovery. A docker host is a local container with no path onto the tailnet, so the docker provider failed fast on the script — a tailnet-mode drukbox could not serve docker hosts at all. One box serving remote agent VMs over the tailnet plus local browser containers (the druks browser-session flow requestsprovider=dockerper borrow) needs exactly that.Providers now declare
supports_tailnetbeside the other per-provider traits (supports_instance_type,supports_disk_gb); docker leaves it False, the VM providers inherit True.provision()binds the tailscale client once —tailscale = self.tailscale if get_vm_provider(host.provider).supports_tailnet else None— and its three tailnet blocks key on that local, so a docker host under a tailnet-mode service skips the join entirely: no credentials minted, no setup script, nointernal_ssh_host, no discovery wait. The keyscan and teardown paths already follow the host's own fields and need no change. The docker provider's fail-fast on a setup script stays as the backstop for a mis-flagged provider.Nothing widens: docker containers still publish sshd on
127.0.0.1only, reachable from the box alone. Docs updated (deploy.md docker section, networking.md two-modes intro). One service-level test beside the tailscale-off tests: tailnet-mode service + docker host stays local end to end.ENG-857