# How to Start a Tailcat Server: CLI Configuration and Examples

> Learn how to start a Tailcat server using the CLI. Configure ports, services, and directories with simple commands for easy server setup.

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

---

**Run `tailcat serve` to start a server that listens for incoming connections over Tailscale's WireGuard data-plane, optionally specifying ports, services, or directories via command-line flags.**

Tailcat is an open-source command-line utility maintained in the `tailscale/tailcat` repository that enables secure networking over Tailscale's mesh. To start a Tailcat server, you invoke the binary with the `serve` sub-command (or no sub-command) and configure behavior through flags defined in [`main/cmd/tailcat/tailcat.go`](https://github.com/tailscale/tailcat/blob/main/main/cmd/tailcat/tailcat.go). The server implementation in [`main/tailcat.go`](https://github.com/tailscale/tailcat/blob/main/main/tailcat.go) handles the underlying WireGuard connections and service multiplexing.

## Understanding Tailcat Server Architecture

Tailcat operates as a multi-mode program capable of functioning as a server, client, or utility. When starting a server, the CLI parses flags in [`main/cmd/tailcat/tailcat.go`](https://github.com/tailscale/tailcat/blob/main/main/cmd/tailcat/tailcat.go) and initializes a `tailcat.Server` struct from [`main/tailcat.go`](https://github.com/tailscale/tailcat/blob/main/main/tailcat.go). The server's `Start` method manages DERP region selection, listener setup, and address generation for client connections.

## Essential Configuration Flags

### Port and Service Exposure (--serve)

The `--serve` flag accepts a comma-separated list of ports or service names. Valid service names include **ssh**, **files**, **exec**, and **exit-node**. When omitted, the server accepts a single connection on any available port and streams data to stdout.

### Authentication and Access Control (--key, --allow, --psk)

- `--key`: Specifies the path or name of the server's private key (defaults to "default")
- `--allow`: Whitelist of client public keys; empty allows all clients
- `--psk`: Embeds a WireGuard pre-shared key in the address for additional security

### Service-Specific Configuration (--files, --ssh-authorized-keys)

- `--files`: Directory path for SFTP access with optional mode suffixes (`:ro`, `:rw`, `:wo`, `:wo+`)
- `--ssh-authorized-keys`: File containing authorized SSH public keys when running the SSH service

### Output Formatting (--full-address, --json)

- `--full-address`: Embeds DERP node information directly in the printed address
- `--json`: Outputs the listening address as parseable JSON to stdout

## Practical Examples for Starting a Tailcat Server

### Minimal Server (Default Mode)

Start a basic server that accepts one connection and writes to stdout:

```bash
tailcat serve

```

### TCP Port Forwarding

Expose a specific TCP port to incoming connections:

```bash
tailcat serve --serve 8080

```

### SSH Service with Public Key Authentication

Run an SSH server restricted to specific keys:

```bash
tailcat serve \
  --serve ssh \
  --ssh-authorized-keys ~/.ssh/id_rsa.pub

```

### SFTP File Server (Read-Only)

Serve a directory over SFTP with read-only access:

```bash
tailcat serve \
  --serve files \
  --files /srv/shared:ro

```

### Command Execution per Connection (Exec Service)

Run a command for each incoming connection, piping stdin/stdout through the WireGuard tunnel:

```bash
tailcat serve -- /usr/bin/tee /tmp/connection.log

```

### Multiple Simultaneous Services

Combine SSH, SFTP, and TCP port listening:

```bash
tailcat serve \
  --serve ssh,files,8080 \
  --ssh-authorized-keys ~/.ssh/authorized_keys \
  --files /var/www:rw

```

### Scripting and Automation

Output the address in JSON format for programmatic use:

```bash
tailcat serve --json

```

## Server Initialization Lifecycle

When `tailcat serve` executes, the following sequence occurs in the source code:

1. **Flag Parsing**: [`main/cmd/tailcat/tailcat.go`](https://github.com/tailscale/tailcat/blob/main/main/cmd/tailcat/tailcat.go) validates CLI arguments and service combinations
2. **Server Construction**: The CLI instantiates a `tailcat.Server` from [`main/tailcat.go`](https://github.com/tailscale/tailcat/blob/main/main/tailcat.go) with the parsed configuration
3. **DERP Selection**: The `Start` method selects a DERP region (or extracts it from a provided address)
4. **Listener Setup**: The server binds to requested ports and initializes service handlers
5. **Address Publication**: The server prints the Tailcat address (or JSON) to stdout for client connection

## Summary

- Run `tailcat serve` to start a server with default settings that streams to stdout
- Use `--serve` to expose specific ports or activate services like SSH, SFTP, or exec
- Configure authentication via `--key`, `--allow`, and `--ssh-authorized-keys`
- Control file access modes with suffixes like `:ro` (read-only) and `:rw` (read-write)
- Use `--json` or `--full-address` to simplify automated client connections

## Frequently Asked Questions

### What is the difference between running `tailcat` and `tailcat serve`?

When invoked without sub-commands, Tailcat defaults to server mode identical to `tailcat serve`. Both commands initialize the `tailcat.Server` implementation in [`main/tailcat.go`](https://github.com/tailscale/tailcat/blob/main/main/tailcat.go) and listen for incoming WireGuard connections. The explicit `serve` sub-command is recommended for clarity in scripts and documentation.

### How does Tailcat handle authentication for incoming connections?

Tailcat uses WireGuard public keys for transport-layer authentication. The `--allow` flag restricts connections to specific client public keys, while service-level authentication (like `--ssh-authorized-keys`) controls access to individual services such as SSH. The `--psk` flag adds a pre-shared key for additional security layers.

### Can Tailcat serve multiple protocols simultaneously?

Yes. The `--serve` flag accepts comma-separated values allowing you to combine TCP ports with service names like `ssh`, `files`, and `exec`. The server multiplexes these services over the same Tailscale connection, as implemented in the listener setup logic within [`main/tailcat.go`](https://github.com/tailscale/tailcat/blob/main/main/tailcat.go).

### Where are the server configuration flags defined in the source code?

All CLI flags—including `--serve`, `--files`, and `--ssh-authorized-keys`—are defined in [`main/cmd/tailcat/tailcat.go`](https://github.com/tailscale/tailcat/blob/main/main/cmd/tailcat/tailcat.go). The `tailcat.Server` struct and its `Start` method, which processes these configurations into running services, are located in [`main/tailcat.go`](https://github.com/tailscale/tailcat/blob/main/main/tailcat.go).