Skip to Content
IntegrationsTailscale

Tailscale Integration

Vend Mode: Creddy creates real Tailscale auth keys. Agents use them directly with tailscale up.

Creddy’s Tailscale plugin creates ephemeral auth keys for joining your tailnet. Agents request a key, join the network, and when they disconnect the device is automatically removed.

How It Works

Tailscale vend flow diagram
  1. Agent requests creddy get tailscale
  2. Creddy creates a single-use auth key via Tailscale API
  3. Agent runs tailscale up --auth-key=<key>
  4. Device joins the tailnet with configured ACL tags
  5. When device disconnects → automatically removed (ephemeral)
  6. On TTL expiry → key revoked (can’t be used)

Key benefits:

  • No hardcoded auth keys in CI/CD or agent configs
  • Devices are ephemeral (auto-cleaned on disconnect)
  • ACL tags control network access
  • Keys are single-use and time-limited

Requirements

Installation

creddy plugin install tailscale

Server Setup

Add the backend with your Tailscale API key:

creddy backend add tailscale

You’ll be prompted for:

  • api_key: Tailscale API key
  • tailnet: Your tailnet name (e.g., mycompany.com)

Configuration Options

{ "api_key": "tskey-api-xxx", "tailnet": "mycompany.com", "default_tags": ["tag:agent"], "ephemeral": true, "preauthorized": true }
OptionDescriptionDefault
api_keyTailscale API key (required)
tailnetTailnet name (required)
default_tagsACL tags for all devices[]
ephemeralAuto-remove on disconnecttrue
preauthorizedSkip manual device approvaltrue

Agent Enrollment

Agents request Tailscale access during enrollment:

creddy enroll --server http://creddy:8400 --name ci-agent \ --can tailscale

Authentication: Agents can authenticate to Creddy using either vend tokens (ckr_xxx) or OIDC (client_id/client_secret). Both work with Tailscale.

Or with specific tags:

creddy enroll --server http://creddy:8400 --name ci-agent \ --can tailscale:tag:ci

Requesting Auth Keys

Once enrolled and approved:

# Get an auth key (default 10 min TTL) AUTH_KEY=$(creddy get tailscale) # Join the tailnet tailscale up --auth-key=$AUTH_KEY

With Specific Tags

# Request a key with specific ACL tag AUTH_KEY=$(creddy get tailscale --scope tailscale:tag:ci) tailscale up --auth-key=$AUTH_KEY

Custom TTL

# Key valid for 30 minutes AUTH_KEY=$(creddy get tailscale --ttl 30m)

Use Cases

CI/CD Pipeline

# GitHub Actions jobs: deploy: steps: - name: Join tailnet run: | AUTH_KEY=$(creddy get tailscale --ttl 30m) sudo tailscale up --auth-key=$AUTH_KEY - name: Access internal services run: | curl http://internal-api.tail123.ts.net/deploy - name: Leave tailnet run: sudo tailscale down

Ephemeral VMs

#!/bin/bash # VM startup script # Get auth key from Creddy AUTH_KEY=$(creddy get tailscale) # Join tailnet tailscale up --auth-key=$AUTH_KEY --hostname="worker-$(hostname)" # VM is now on the tailnet # When VM shuts down, device auto-removes

AI Agents

import subprocess import os # Agent needs to access internal API auth_key = subprocess.check_output( ["creddy", "get", "tailscale", "--ttl", "1h"] ).decode().strip() subprocess.run(["tailscale", "up", f"--auth-key={auth_key}"]) # Now agent can reach internal services response = requests.get("http://internal-llm.tail123.ts.net/v1/chat")

Scopes

ScopeDescription
tailscaleCreate auth keys with default tags
tailscale:tag:*Create keys with specific ACL tag

Examples:

  • tailscale — uses default_tags from config
  • tailscale:tag:ci — device gets tag:ci
  • tailscale:tag:prod-agent — device gets tag:prod-agent

TTL Constraints

  • Minimum TTL: 1 minute
  • Maximum TTL: 24 hours
  • Default TTL: 10 minutes

ACL Configuration

Use Tailscale ACLs to control what devices can access:

{ "acls": [ // CI agents can only reach internal APIs {"action": "accept", "src": ["tag:ci"], "dst": ["tag:api:*"]}, // Production agents have broader access {"action": "accept", "src": ["tag:prod-agent"], "dst": ["*:*"]} ], "tagOwners": { "tag:ci": ["group:devops"], "tag:prod-agent": ["group:sre"], "tag:agent": ["group:platform"] } }

Security Considerations

Auth Key Security

  • Keys are single-use (only one device can join)
  • Keys are ephemeral (device removed on disconnect)
  • Keys have TTL (expire even if unused)
  • Keys are pre-authorized (no manual approval step)

Network Access

Devices joining via Creddy are controlled by:

  1. ACL tags — what they can access on the tailnet
  2. Ephemeral flag — auto-removed on disconnect
  3. TTL — limited window to use the key

Best Practices

  • Use specific tags per use case (tag:ci, tag:staging-agent)
  • Keep TTLs short for untrusted environments
  • Review Tailscale admin logs for unusual join patterns
  • Use ACLs to limit blast radius

Troubleshooting

”invalid API key”

Ensure your API key:

  • Is a valid Tailscale API key (starts with tskey-api-)
  • Has permission to create auth keys
  • Hasn’t expired

”tailnet not found”

Check the tailnet name matches exactly:

  • For personal accounts: your email domain or gmail.com
  • For organizations: the organization name from admin console

Device not joining

  1. Check key hasn’t expired: creddy get tailscale generates fresh key
  2. Check Tailscale daemon is running: tailscale status
  3. Check for conflicting state: tailscale logout then retry

ACL errors

If device joins but can’t reach services:

  1. Verify tags are applied: tailscale status
  2. Check ACL rules allow the tag to access the destination
  3. Review Tailscale admin logs for denied connections
Last updated on

Apache 2.0 2026 © Creddy