# VPNs & Tailscale

## `[l3vpns]`

This section defines Layer 3 VPN interfaces. The key for each entry is a user-defined name for the interface.

### Common Fields

| Key | Type | Description | Required |
|---|---|---|---|
| `type` | String | Active types include `wireguard`, `amneziawg`, and experimental `tailscale`. `openvpn` is accepted by the schema but should not be treated as an implemented OpenVPN client. | Yes |
| `nickname` | String | A user-friendly name for the interface. | No |
| `enabled` | Boolean | Whether the interface is enabled. Defaults to `true`. | No |

### WireGuard Specific Fields (When `type=wireguard`)

| Key | Type | Description | Required |
|---|---|---|---|
| `private-key` | String | The private key for the interface. | Yes |
| `address` | CIDR | The internal IP address and subnet for the interface. | Yes |

### Tailscale fields (`type:tailscale`, experimental, Pro)

| Key | Meaning |
|---|---|
| `login-server` | HTTPS control server URL, normally `https://controlplane.tailscale.com`; no embedded credentials, query, or fragment. |
| `auth-key` | Optional bootstrap enrollment key. Prefer browser login or a one-time key submission to avoid saving secrets in the profile. |
| `exit-node-ip` | Optional preferred exit-node IPv4 address, without a CIDR or port. Applied on VPN restart and explicit login. The node must be available and advertise exit capability; otherwise inspect Tailscale status. Omit to use the device's saved preference. |
| `drive-dns` | Default `false`. Derive peer IPv4 DNS records through MintFlow DNS; this does not enable the Tailscale OS MagicDNS resolver. Requires Pro and the MintFlow DNS path. |
| `enabled` | Default `true`. Only one active Tailscale interface per profile. |

```ini
[l3vpns]
tailnet=type:tailscale,login-server:https://controlplane.tailscale.com,enabled:true

[routing]
CIDR,100.64.0.0/10,L3VPN,tailnet
DEFAULT,DIRECT
DNS-FALLBACK,DIRECT
```

Use with `[dns] app-routing-enabled=true` and suitable `direct-dns` upstreams. See the [complete login and routing guide](../howtos/tailscale.md). Machine identity and Accept Routes remain device-local. The optional `exit-node-ip` saves a preferred exit node in the profile and syncs with it; live overrides do not change the profile. Without this field, each device keeps its own exit-node preference. Losing Pro access excludes the interface during compilation and changes routes targeting it to REJECT.

### AmneziaWG Specific Fields (When `type=amneziawg`)

MintFlow 1.9.0 supports AmneziaWG 1.5 and 2.0 interface parameters. Peer fields are configured separately in `[amneziawg-peers]`.

| Key | Type | Description | Required |
|---|---|---|---|
| `private-key` | String | The private key for the interface. | Yes |
| `address` | CIDR | The internal IP address and subnet for the interface. | Yes |
| `jc` | Integer | Junk packet count parameter. | No |
| `jmin` | Integer | Minimum junk packet size. | No |
| `jmax` | Integer | Maximum junk packet size. | No |
| `s1` | Integer | AmneziaWG S1 parameter. | No |
| `s2` | Integer | AmneziaWG S2 parameter. | No |
| `s3` | Integer | AmneziaWG S3 parameter. | No |
| `s4` | Integer | AmneziaWG S4 parameter. | No |
| `h1` | Integer or range | H1 packet header value, for example `1` or `843739526-1233562642`. | No |
| `h2` | Integer or range | H2 packet header value, for example `2` or `1383464517-1389039856`. | No |
| `h3` | Integer or range | H3 packet header value, for example `3` or `1558777559-1611162592`. | No |
| `h4` | Integer or range | H4 packet header value, for example `4` or `1797613837-1977519157`. | No |
| `i1` ... `i5` | String | AmneziaWG 2.0 CPS instruction strings. Each field is limited to 255 UTF-8 bytes. Supported tags are `<b>`, `<r>`, `<rd>`, `<rc>`, and `<t>`. | No |

**Example:**
```ini
[l3vpns]
my-wireguard=type:wireguard,nickname:My WG,private-key:...,address:10.0.0.1/32
my-awg=type:amneziawg,nickname:My AWG,private-key:...,address:10.8.9.2/32,jc:4,jmin:40,jmax:70,s1:0,s2:0,s3:0,s4:0,h1:1,h2:2,h3:3,h4:4,i1:<r 33>
```

## `[wireguard-peers]`

This section defines peers for WireGuard interfaces. The key for each entry is a user-defined name for the peer.

| Key | Type | Description | Required |
|---|---|---|---|
| `interface` | String | The name of the `l3vpns` interface this peer belongs to. | Yes |
| `public-key` | String | The public key of the peer. | Yes |
| `preshared-key`| String | An optional pre-shared key. | No |
| `endpoint` | String | The public endpoint of the peer (e.g., `1.2.3.4:51820`). | Yes |
| `allowed-ips` | List of CIDRs | A list of IP addresses/ranges to be routed through this peer. | Yes |

**Example:**
```ini
[wireguard-peers]
my-peer=interface:my-wireguard,public-key:...,endpoint:1.2.3.4:51820,allowed-ips:0.0.0.0/0
```

## `[amneziawg-peers]`

This section defines peers for AmneziaWG interfaces. The key for each entry is a user-defined peer name. The fields match WireGuard peers, but `interface` must reference an `[l3vpns]` entry whose `type` is `amneziawg`.

| Key | Type | Description | Required |
|---|---|---|---|
| `interface` | String | The name of the `amneziawg` interface this peer belongs to. | Yes |
| `public-key` | String | The public key of the peer. | Yes |
| `preshared-key`| String | An optional pre-shared key. | No |
| `endpoint` | String | The public endpoint of the peer, for example `1.2.3.4:51820`. | Yes |
| `allowed-ips` | List of CIDRs | A list of IP addresses/ranges to be routed through this peer. | Yes |

**Example:**
```ini
[amneziawg-peers]
my-awg-peer=interface:my-awg,public-key:...,endpoint:1.2.3.4:51820,allowed-ips:0.0.0.0/0,::/0
```
