How to Generate a Persistent WireGuard Key for Tailcat
To generate a persistent WireGuard key for Tailcat, either let the binary create it automatically at $HOME/.config/tailcat/wireguard.key on first launch, or manually generate one using wg genkey and place it in that location; Tailcat reuses this key across restarts to maintain a stable network identity.
Tailcat is a networking utility from the tailscale/tailcat repository that establishes secure connections using WireGuard. According to the source code, the application manages cryptographic identity persistence by automatically generating and storing private keys in the user's configuration directory, eliminating the need for manual key management in typical deployments.
Automatic Key Generation on First Run
When Tailcat initializes, the logic in config.go checks for an existing private key file. If the file does not exist, the program invokes the generation routine in wire.go, which calls tailscale.com/wgkey.NewPrivateKey() to create a cryptographically secure private key. The application then writes this key to the configuration directory with restrictive permissions, ensuring it persists for subsequent executions.
To trigger automatic generation, simply execute the Tailcat binary:
./tailcat
On first run, Tailcat creates the directory $HOME/.config/tailcat/ (respecting $XDG_CONFIG_HOME on Linux) and writes the wireguard.key file containing the base64-encoded private key.
Manual Key Generation Methods
For infrastructure-as-code deployments or when you require key control before the first execution, you can generate the key manually using two approaches supported by the Tailcat architecture.
Using the WireGuard Command-Line Tools
The standard WireGuard utilities provide the simplest method for key generation. Create the configuration directory and generate the key in one pipeline:
# Create the config directory and generate the key
mkdir -p "$HOME/.config/tailcat"
wg genkey | tee "$HOME/.config/tailcat/wireguard.key"
# Set restrictive permissions (owner read/write only)
chmod 600 "$HOME/.config/tailcat/wireguard.key"
This approach uses the wg genkey utility to produce a Curve25519 private key and immediately persists it to the location Tailcat expects.
Programmatic Generation with Go
For applications integrating Tailcat's logic directly, replicate the exact method used in wire.go by importing the Tailscale wireless key library:
package main
import (
"fmt"
"io/ioutil"
"os"
"path/filepath"
"tailscale.com/wgkey"
)
func main() {
// Generate a new private WireGuard key using Tailcat's implementation
priv, err := wgkey.NewPrivateKey()
if err != nil {
panic(err)
}
// Encode in the format Tailcat expects (base64 string plus newline)
data := []byte(priv.String() + "\n")
// Determine configuration directory
cfgDir, _ := os.UserConfigDir()
keyPath := filepath.Join(cfgDir, "tailcat", "wireguard.key")
// Ensure directory exists with appropriate permissions
if err := os.MkdirAll(filepath.Dir(keyPath), 0o700); err != nil {
panic(err)
}
// Write key with restricted permissions (0o600 = owner read/write only)
if err := ioutil.WriteFile(keyPath, data, 0o600); err != nil {
panic(err)
}
fmt.Printf("Persistent WireGuard key written to %s\n", keyPath)
}
This Go implementation mirrors the behavior in wire.go, utilizing wgkey.NewPrivateKey() to ensure cryptographic compatibility with Tailcat's WireGuard stack.
Configuration File Locations
Tailcat follows platform-specific conventions for configuration storage:
- Linux:
$HOME/.config/tailcat/wireguard.key(or$XDG_CONFIG_HOME/tailcat/wireguard.keyif set) - macOS:
$HOME/Library/Application Support/tailcat/wireguard.key - Windows:
%AppData%\tailcat\wireguard.key
The key file must contain a single line with the base64-encoded private key. When config.go loads on startup, it reads this file and derives the corresponding public key automatically for WireGuard handshake negotiations.
Security Best Practices
The private key generated for Tailcat operations requires strict confidentiality:
- File permissions: Always set
0o600(read/write for owner only) on the key file. Both automatic generation and manual scripts must respect this permission mask. - Backup considerations: If you back up the key, encrypt the backup. Anyone with access to this private key can impersonate your node on the WireGuard network.
- Rotation: To rotate keys, delete the
wireguard.keyfile and restart Tailcat. The application will generate a new key inwire.goand establish a fresh network identity.
Summary
- Automatic approach: Run Tailcat once to trigger the generation logic in
wire.go, which creates the key at the platform-appropriate config path. - Manual approach: Use
wg genkeyor the Gowgkey.NewPrivateKey()API to create the key file before launching the application. - Key location: Store the file at
$HOME/.config/tailcat/wireguard.key(Linux) or the equivalent platform-specific path handled byconfig.go. - Permissions: Always restrict the key file to
0o600to prevent unauthorized access. - Persistence: Once created, Tailcat reuses this key across all subsequent executions, maintaining a stable WireGuard public key for network authentication.
Frequently Asked Questions
Where does Tailcat store the WireGuard private key?
Tailcat stores the private key in your user configuration directory under a subdirectory named tailcat. On Linux systems, this defaults to $HOME/.config/tailcat/wireguard.key. The exact path determination logic resides in config.go, which respects platform standards such as $XDG_CONFIG_HOME on Linux and Library/Application Support on macOS.
Can I use an existing WireGuard key with Tailcat?
Yes. If you have an existing private key generated by wg genkey or another WireGuard-compatible tool, you can place it at the expected configuration path. Ensure the file contains only the base64-encoded private key followed by a newline, and set permissions to 0o600. Tailcat's config.go loader will accept any valid Curve25519 private key that conforms to the WireGuard specification.
What happens if I delete the wireguard.key file?
If you delete the key file and restart Tailcat, the automatic generation routine in wire.go triggers immediately upon startup. The application generates a new private key using wgkey.NewPrivateKey(), writes it to the configuration directory, and uses the new key for all subsequent connections. This effectively rotates your node's WireGuard identity, though you will need to re-authenticate with any coordination servers or peers that whitelist specific public keys.
Is the private key generated by Tailcat compatible with standard WireGuard tools?
Yes. Tailcat uses the standard WireGuard key format implemented in the tailscale.com/wgkey package. The private keys are standard Curve25519 keys encoded in base64, fully compatible with wg, wg-quick, and other WireGuard implementations. You can extract the key from Tailcat's config directory and use it with other tools, or import keys generated by wg genkey into Tailcat.
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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →