# Ephemeral vs. Persistent Keys in Tailcat: What's the Difference?

> Understand ephemeral vs persistent keys in Tailcat. Learn how each key type manages identities for temporary sessions or across multiple restarts. Get the details now.

- Repository: [Tailscale/tailcat](https://github.com/tailscale/tailcat)
- Tags: deep-dive
- Published: 2026-09-08

---

**Ephemeral keys are temporary session-only identities generated on startup and discarded when the process exits, while persistent keys are saved as JSON files to disk and reused across multiple Tailcat sessions.**

When running the `tailscale/tailcat` application, you choose between two identity key types that determine how your node authenticates to the network. Understanding the differences between ephemeral and persistent keys ensures you select the right option for short-lived debugging sessions versus long-running production servers. This guide breaks down the technical implementation in [`tailcat.go`](https://github.com/tailscale/tailcat/blob/main/tailcat.go), storage mechanisms, and CLI usage patterns.

## Core Differences Between Ephemeral and Persistent Keys

Tailcat distinguishes between these key types based on storage persistence and lifecycle management.

### Ephemeral Keys (Session-Only)

**Ephemeral keys** are cryptographically generated on-the-fly when the `Start` function in [`tailcat.go`](https://github.com/tailscale/tailcat/blob/main/tailcat.go) detects no existing key is provided. According to the source code comments, "If zero, Start generates a new ephemeral key." These credentials exist only in memory for the duration of the process and are never written to disk.

- **Lifetime**: Exists only for the current process lifecycle; discarded on exit.
- **Use case**: Ideal for temporary debugging, one-off connections, or disposable containers where node identity does not need to persist.
- **CLI option**: Use `--key new` to force generation of a fresh ephemeral key.

### Persistent Keys (Saved Identities)

**Persistent keys** are stored as `*.private.json` files in the Tailcat configuration directory and maintain a stable node identity across restarts. The default saved key names are **`default`** for server mode and **`client-default`** for client modes, as defined in the command-line handling logic in [`cmd/tailcat/tailcat.go`](https://github.com/tailscale/tailcat/blob/main/cmd/tailcat/tailcat.go).

- **Lifetime**: Stored indefinitely on disk until explicitly deleted.
- **Use case**: Required for long-running servers or when other peers need a consistent, recognizable node identity.
- **Storage location**: `$CONFIG/tailcat/keys/` (typically `$HOME/.config/tailcat/keys/` on Unix systems).
- **CLI options**: Specify a key name or file path, or omit the flag to use the default.

## How Tailcat Handles Key Generation and Storage

The underlying implementation in `tailscale/tailcat` treats these key types differently in terms of file operations and JSON serialization.

### Automatic Generation Logic

In [`tailcat.go`](https://github.com/tailscale/tailcat/blob/main/tailcat.go), the `Start` method implements the following logic: if the key value is zero, it generates a new ephemeral key automatically at first use. This ensures Tailcat can start immediately without pre-configuration, falling back to temporary credentials when no persistent key exists.

### File Format and Directory Structure

Persistent keys follow the JSON structure defined by the `PrivateKey` type in [`tailcat.go`](https://github.com/tailscale/tailcat/blob/main/tailcat.go). When saved, Tailcat writes a [`.private.json`](https://github.com/tailscale/tailcat/blob/main/.private.json) file containing the serialized key material. You can reference named keys stored in `$CONFIG/tailcat/keys/` by simple identifiers like `foo` rather than full file paths.

## Using the --key Flag to Control Key Selection

The `--key` flag implemented in [`cmd/tailcat/tailcat.go`](https://github.com/tailscale/tailcat/blob/main/cmd/tailcat/tailcat.go) accepts several argument patterns to determine identity:

- **`--key new`** – Forces generation of a fresh ephemeral key that is discarded when the process exits.
- **`--key <name>`** – Loads a persistent key from `$CONFIG/tailcat/keys/<name>.private.json`.
- **`--key <path>`** – Loads a persistent key directly from a specific `*.private.json` file path.
- **Omitting `--key`** – Attempts to load the default saved key (`default` in server mode, `client-default` in client modes); if no default exists, Tailcat automatically falls back to generating an ephemeral key.

### Practical Examples

Generate a temporary ephemeral key for a quick session:

```bash
tailcat --key new --ssh :2222

```

Run with the default persistent key (or ephemeral if no default exists):

```bash
tailcat --ssh :2222

```

Load a named persistent key from the config directory:

```bash
tailcat --key work-node --ssh :2222

```

Load a key from a specific file path:

```bash
tailcat --key /etc/secrets/mykey.private.json --ssh :2222

```

## Summary

- **Ephemeral keys** are generated automatically when no key is supplied, exist only in RAM, and vanish when the process terminates.
- **Persistent keys** are saved as JSON files in `$CONFIG/tailcat/keys/`, providing stable identities across restarts.
- The `--key` flag accepts `new` for ephemeral generation, a name for persistent keys in the config directory, or a direct file path.
- Server mode defaults to the `default` key, while client modes use `client-default` when no flag is specified.

## Frequently Asked Questions

### What happens if I start Tailcat without specifying a --key flag?

If you omit the `--key` flag, Tailcat attempts to load the default saved key—`default` for server mode or `client-default` for client modes—from the `$CONFIG/tailcat/keys/` directory. According to the [`cmd/tailcat/tailcat.go`](https://github.com/tailscale/tailcat/blob/main/cmd/tailcat/tailcat.go) implementation, if no default key exists, the system automatically generates a new ephemeral key instead.

### Where are persistent keys stored on my system?

Persistent keys are written to the `$CONFIG/tailcat/keys/` directory, which typically resolves to `$HOME/.config/tailcat/keys/` on Unix systems. Each key is saved as a separate [`.private.json`](https://github.com/tailscale/tailcat/blob/main/.private.json) file containing the serialized `PrivateKey` structure defined in [`tailcat.go`](https://github.com/tailscale/tailcat/blob/main/tailcat.go).

### Can I convert an ephemeral key to a persistent key?

Tailcat does not automatically convert ephemeral keys to persistent ones during runtime. To save an ephemeral identity, you would need to manually export the current key material and write it to a [`.private.json`](https://github.com/tailscale/tailcat/blob/main/.private.json) file in the correct directory format, then reference it by name in subsequent invocations.

### Is there a security difference between ephemeral and persistent keys?

Yes. **Ephemeral keys** reduce long-term exposure because they never touch the filesystem and cannot be recovered after the process exits, making them ideal for untrusted environments. **Persistent keys** require proper file permissions (typically `0600`) on the [`.private.json`](https://github.com/tailscale/tailcat/blob/main/.private.json) files since they represent reusable credentials that could be compromised if the disk is accessed by unauthorized users.