Skip to content

Tailscale Funnel as a new Service Mode tunnel option - #2378

Open
mnaqvi-ks wants to merge 6 commits into
feature/tailscale-funnel-service-modefrom
feature/tailscale-funnel-service-mode-int
Open

mnaqvi-ks wants to merge 6 commits into
feature/tailscale-funnel-service-modefrom
feature/tailscale-funnel-service-mode-int

Conversation

@mnaqvi-ks

Copy link
Copy Markdown

Adds Tailscale Funnel as a new tunnel option for Commander Service Mode, alongside the existing Ngrok and Cloudflare integrations. Users can now expose the Service Mode REST API over a public HTTPS URL using their own Tailscale account, with no changes to how Ngrok/Cloudflare already work.

# Plain personal auth key
keeper service-create -p 8090 -ts '<tailscale-auth-key>' -rm foreground -q y -f yaml -c "ls"

# OAuth-issued auth key (needs the ACL tag it's scoped to)
keeper service-create -p 8090 -ts '<oauth-client-secret>' -tst 'tag:commander-service' -rm foreground -q y -f yaml -c "ls"

Features

  • New tunnel provider-ts, --tailscale <auth-key> / -tst, --tailscale_advertise_tags <tags>, following the same single-flag convention as -ng/-cf. Mutually exclusive with Ngrok/Cloudflare.
  • CLI detection & auto-install — detects a missing Tailscale CLI and, with explicit user confirmation, installs it automatically (Homebrew on macOS, official script on Linux, MSI with UAC elevation on Windows). Falls back to manual guidance if declined or if it fails.
  • Daemon detection & auto-start — same consent-gated flow if tailscaled isn't running.
  • Authentication — supports both plain personal auth keys and OAuth-client-issued keys. Used only for tailscale up; never touches the Service Mode API Key, which continues to gate every API request unchanged.
  • Full Funnel lifecycle — start, live status, and reset wired into service-create/service-start/service-status/service-stop. Startup failures roll back cleanly (including already-started Ngrok/Cloudflare processes).
  • Public URL retrieval — real HTTPS URL pulled from the node's Tailscale hostname; printed on create, persisted to config, reported via service-status, and included in Docker vault-record metadata (-ur).
  • Security — auth key passed via a short-lived, owner-only temp file (--auth-key=file:...) instead of a raw CLI argument, avoiding exposure via ps to other local users. Never logged.

Design notes

  • service-stop only resets the Funnel exposure — it doesn't log the machine out of Tailscale or stop the daemon, since tailscaled is system-wide and may be used for other things on the same machine.
  • CLI flag naming (-ts <key> as a single flag) intentionally matches the existing -ng/-cf convention rather than a separate enable+key pair.

Files changed

File Purpose
keepercommander/service/config/tailscale_config.py (new) Orchestrates CLI/daemon checks, authentication, Funnel start, and URL retrieval — the Tailscale equivalent of ngrok_config.py/cloudflare_config.py
keepercommander/service/util/tunneling.py Adds all low-level tailscale CLI wrapper functions (install, daemon start, auth, Funnel start/stop/status, URL lookup)
keepercommander/service/core/service_manager.py Wires Tailscale into start_service/stop_service/get_status, including rollback-on-failure and interrupt handling
keepercommander/service/core/process_info.py Adds tailscale_enabled/tailscale_port lifecycle tracking (no PID — Tailscale has no Commander-owned subprocess)
keepercommander/service/core/globals.py Transient, same-process global for deferring vault-metadata write-back until the real Funnel URL is known
keepercommander/service/commands/create_service.py Adds -ts/-tst CLI flags and config schema fields
keepercommander/service/commands/service_config_handlers.py Interactive and streamlined config prompts/assembly for Tailscale, extending the existing mutual-exclusion chain
keepercommander/service/commands/integrations/vault_metadata.py Extracts the shared get_service_url() helper; fixes Docker metadata write-back timing so it waits for the real URL
keepercommander/service/config/config_validation.py Adds validate_tailscale_auth_key
keepercommander/service/config/models.py / service_config.py Adds tailscale, tailscale_auth_key, tailscale_advertise_tags, tailscale_public_url config fields, defaults, and backward-compat migration
keepercommander/resources/service_config.ini Adds interactive prompt text for Tailscale
keepercommander/service/README.md Documents the new flags, examples, and the --force-reauth/single-use-key note
unit-tests/service/test_create_service.py Tests for the new CLI flag behavior, mutual exclusion, and streamlined config assembly

Compatibility

No changes to ngrok_config.py or cloudflare_config.py. All changes to shared files are additive, confirmed via diff review. Full existing test suite (279 tests) passes unchanged.

- Introduced Tailscale configuration and management in the service.
- Added functions for installing, starting, and managing Tailscale daemons and funnels.
- Enhanced ProcessInfo to track Tailscale status and ports.
- Updated ServiceManager to handle Tailscale alongside existing tunneling options (ngrok, Cloudflare).
- Implemented validation for Tailscale configuration parameters.
- Created a new TailscaleConfigurator class for managing Tailscale setup and validation.
- Added logging for Tailscale subprocess activities.
- Updated unit tests to cover new Tailscale functionality.
- Introduced `tailscale_advertise_tags` to ServiceConfig and related classes.
- Updated ServiceConfigHandler to handle new argument for Tailscale.
- Modified TailscaleConfigurator to utilize advertise tags during authentication.
- Adjusted validation logic to check for presence of Tailscale auth key and tags.
- Enhanced installation and daemon management functions to ensure proper handling of Tailscale.
- Updated unit tests to cover new `tailscale_advertise_tags` parameter.
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.

1 participant