# Tuning tunnels

> Adjust endpoint selection, connection pooling, and DNS behavior for tunnel clients.

This guide covers the tunnel settings you'll want to adjust as you move toward production or debug specific connectivity scenarios. The defaults work well for getting started — tune these when you need more control.

## Endpoint selection

The tunnel client chooses which Apoxy edge endpoint to connect to. Two strategies are available:

```bash
apoxy tunnel run my-tunnel --endpoint-selection latency
apoxy tunnel run my-tunnel --endpoint-selection random
```

- **`latency`** (default) — picks the endpoint with the lowest measured latency. Best for most workloads.
- **`random`** — picks a random endpoint. Useful when you want to spread load or debug path diversity.

Start with `latency`. Switch to `random` only if you're investigating routing asymmetry or need to verify multiple edge paths.

## Connection pooling

By default, the tunnel keeps one connection alive to the edge. Increase this for better resilience or higher throughput:

```bash
apoxy tunnel run my-tunnel --min-conns 3
```

More connections means:
- Faster failover if one connection drops.
- Higher aggregate throughput for parallel requests.
- More resources consumed on both ends.

For production workloads, `--min-conns 2` or `3` is a good starting point. For development or low-traffic scenarios, `1` is fine.

## Kernel vs user mode

The tunnel client supports two modes:

```bash
apoxy tunnel run my-tunnel --mode user    # default
apoxy tunnel run my-tunnel --mode kernel
```

- **`user`** mode runs entirely in userspace using a SOCKS proxy and DNS proxy. No special privileges needed.
- **`kernel`** mode creates a TUN device and routes traffic at the OS level. Requires `NET_ADMIN` capability and access to `/dev/net/tun`.

Use `user` mode unless you need transparent network-level tunneling (e.g., routing all traffic from a machine through the tunnel without application changes).

## DNS proxy

In user mode, the tunnel runs a DNS proxy that resolves tunnel-routed names:

```bash
apoxy tunnel run my-tunnel --dns-addr 127.0.0.1:8053
```

The default is `127.0.0.1:8053`. Make sure whatever consumes DNS in your setup (your application, a local resolver, or the backplane) points at this address.

## SOCKS proxy

The tunnel also exposes a SOCKS5 proxy for application-level routing:

```bash
apoxy tunnel run my-tunnel --socks-addr localhost:1080
```

Applications can use this to route specific traffic through the tunnel without kernel-level routing. The default is `localhost:1080`.

## Health and metrics

The tunnel exposes health and metrics endpoints by default on `:8080` and `:8081` respectively. Override them if those ports conflict with your application:

```bash
apoxy tunnel run my-tunnel \
  --health-addr :8080 \
  --metrics-addr :8081
```

These are useful for liveness probes in Kubernetes or monitoring in any environment.

## Non-interactive mode

When running in CI, containers, or systemd units, disable the TUI:

```bash
apoxy tunnel run my-tunnel --no-tui
```

The TUI is helpful for interactive debugging but unnecessary in automation.

## Skipping TLS verification

For development environments with self-signed certificates:

```bash
apoxy tunnel run my-tunnel --insecure-skip-verify
```

Never use this in production.

## Putting it together

A production-ready tunnel invocation might look like:

```bash
apoxy tunnel run my-tunnel \
  --mode user \
  --min-conns 2 \
  --endpoint-selection latency \
  --health-addr :8080 \
  --metrics-addr :8081 \
  --no-tui
```

For the full list of flags, see the [CLI reference](/docs/reference/cli.md).
