How to Use tailcat with Ephemeral Keys for Stateless WireGuard Sessions

When you omit the --key flag or pass --key new, tailcat generates a fresh, in-memory WireGuard key pair that never touches disk and disappears when the process exits.

The tailcat library from the Tailscale organization supports ephemeral keys as a first-class feature. This mode is ideal for short-lived sessions, CI pipelines, or any scenario where persistent node identity is unnecessary or undesirable. No secret material is written to $CONFIG/tailcat/keys or any other filesystem location.

How Ephemeral Key Selection Works

The --key flag in cmd/tailcat/tailcat.go implements a simple priority system:

Flag Value Behavior
(omitted or empty) Use saved default key if present; otherwise generate ephemeral key
new Force ephemeral key generation regardless of saved keys
file path or name Load private key from file or named key in config directory

See the flag definition at cmd/tailcat/tailcat.go#L95-L102.

Ephemeral Key Generation in the Core Library

The actual key creation happens in tailcat.go. The ConnInfo.Start method checks whether the node key is zero (uninitialized). If so, it generates a fresh key pair and stores it only in the ConnInfo struct for the current process lifetime.

As the source comment states: "If zero, Start generates a new ephemeral key." This logic appears at tailcat.go#L405-L409.

Using Ephemeral Keys from the Command Line

Default Ephemeral Behavior

Omit --key entirely to let tailcat decide. If no saved key exists, it automatically creates an ephemeral one:

tailcat client --addr tcomABCdef1234567890abcdef

Force New Ephemeral Key Every Run

Explicitly request a fresh key for complete statelessness:

tailcat client --addr tcomABCdef1234567890abcdef --key new

Ephemeral Keys for Servers

Servers can also run without persistent identity:

tailcat server --listen :7777 --key new

The server's node key is temporary and discarded on exit—useful for throwaway relay nodes or testing environments.

Programmatic Ephemeral Keys in Go

When using tailcat as a library, leave Key empty or omit it from your Config:

cfg := tailcat.Config{
    Addr: "tcomABCdef1234567890abcdef",
    // Key: ""  // empty string triggers ephemeral generation
}

c, err := tailcat.Start(cfg)
if err != nil {
    log.Fatal(err)
}
// c.Start creates a fresh key in-memory if needed

The tailcat.Start function handles key generation internally through ConnInfo.Start.

Ephemeral Keys in WebAssembly Builds

When tailcat is compiled to WebAssembly, the JavaScript glue code in web/main_js.go mirrors the CLI behavior. An empty privateKey field in the configuration JSON triggers the same in-memory key generation path.

This is documented in two locations: web/main_js.go#L43-L45 for initialization and web/main_js.go#L135-L137 for the runtime check.

Security Model and Trade-offs

Ephemeral keys eliminate persistent secrets. Because the private key never leaves RAM:

  • No key file can be exfiltrated from disk
  • No cleanup is required after process termination
  • Compromised hosts reveal only the current session's key

The trade-off is identity continuity. Each new ephemeral key appears as a distinct node on your tailnet. For long-running services or nodes that require stable addressing, use persisted keys instead.

Summary

  • Ephemeral mode is the default when no saved key exists—no explicit flag required
  • --key new forces ephemeral generation even when saved keys are present
  • Keys live only in ConnInfo during process lifetime, per tailcat.go implementation
  • WebAssembly builds support the same semantics via empty privateKey JSON fields
  • Ideal for CI/CD, scripting, and transient workloads where disk persistence adds risk without value

Frequently Asked Questions

What happens to my ephemeral key when tailcat exits?

The key is permanently lost. Ephemeral keys exist only in process memory and are not serialized to any storage medium. When the process terminates, the WireGuard key pair is unrecoverable. This is by design for security-sensitive or single-use scenarios.

Can I restart a tailcat client with the same ephemeral key?

No. By definition, ephemeral keys cannot be restored. If you need identity persistence across restarts, omit --key new and allow tailcat to save the default key to $CONFIG/tailcat/keys, or specify a named key file for explicit management.

Does using --key new affect connection performance?

No measurable impact. The ConnInfo.Start method generates the key pair once during initialization using standard WireGuard key generation, which completes in microseconds. The ephemeral flag changes only storage behavior, not cryptographic operations or network performance.

How do I verify that tailcat is actually using an ephemeral key?

Check your tailnet admin panel for node expiration. Ephemeral keys register as new nodes with unique public keys on each run. If you see a fresh node entry with no historical key fingerprint, and no file appears in your tailcat keys directory, the ephemeral path is active.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →