# How to Use tailcat with Ephemeral Keys for Stateless WireGuard Sessions

> Learn how to use tailcat with ephemeral keys for stateless WireGuard sessions. Generate new in-memory keys that disappear when the process exits for enhanced security.

- Repository: [Tailscale/tailcat](https://github.com/tailscale/tailcat)
- Tags: how-to-guide
- Published: 2026-09-06

---

**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](https://github.com/tailscale/tailcat) 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`](https://github.com/tailscale/tailcat/blob/main/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](https://github.com/tailscale/tailcat/blob/main/cmd/tailcat/tailcat.go#L95-L102).

## Ephemeral Key Generation in the Core Library

The actual key creation happens in [`tailcat.go`](https://github.com/tailscale/tailcat/blob/main/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](https://github.com/tailscale/tailcat/blob/main/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:

```bash
tailcat client --addr tcomABCdef1234567890abcdef

```

### Force New Ephemeral Key Every Run

Explicitly request a fresh key for complete statelessness:

```bash
tailcat client --addr tcomABCdef1234567890abcdef --key new

```

### Ephemeral Keys for Servers

Servers can also run without persistent identity:

```bash
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`:

```go
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`](https://github.com/tailscale/tailcat/blob/main/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](https://github.com/tailscale/tailcat/blob/main/web/main_js.go#L43-L45) for initialization and [web/main_js.go#L135-L137](https://github.com/tailscale/tailcat/blob/main/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`](https://github.com/tailscale/tailcat/blob/main/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.