> ## Documentation Index
> Fetch the complete documentation index at: https://developers.telnyx.com/llms.txt
> Use this file to discover all available pages before exploring further.

# WireGuard Interfaces Quick Start

> Create a WireGuard Interface on a Network, register a host as its peer, and bring the tunnel up on the host.

## Prerequisites

* A host with WireGuard installed: [Linux](/docs/network/wireguard-peer-config/linux), [macOS](/docs/network/wireguard-peer-config/macos), or [Windows](/docs/network/wireguard-peer-config/windows).
* A region that offers WireGuard Interfaces. `GET /v2/network_coverage?filter[available_services][contains]=cloud_vpn` lists them. A location's `location.code`, such as `ashburn-va`, is the `region_code` to use.
* A Network. [`POST /v2/networks`](/api-reference/networks/create-a-network) with `{"name": "acme-prod"}` returns its `id`.

## Create the interface

Send [`POST /v2/wireguard_interfaces`](/api-reference/wireguard-interfaces/create-a-wireguard-interface):

```json theme={null}
{
  "network_id": "0de011ae-ee53-4df4-ba96-754728eb5aad",
  "name": "wg-ashburn",
  "region_code": "ashburn-va"
}
```

<Warning>
  An interface cannot move to another Network. Confirm `network_id` before sending the request.
</Warning>

The response returns `status: provisioning` and the values that peers need: `endpoint`, `public_key`, and `server_ip_address`.

```json theme={null}
{
  "data": {
    "name": "wg-ashburn",
    "status": "provisioning",
    "created_at": "2026-10-09T23:03:28.957851Z",
    "region_code": "ashburn-va",
    "enable_sip_trunking": false,
    "public_key": "dM4BrhaKqRVoq+mMD+4mmQ5KTFkcutiXnfN2Ztk+3Sw=",
    "id": "749de8c6-bbd0-42dd-9a16-770a519b565d",
    "updated_at": "2026-10-09T23:03:31.009085Z",
    "network_id": "0de011ae-ee53-4df4-ba96-754728eb5aad",
    "region": {
      "code": "ashburn-va",
      "name": "Ashburn VA, US",
      "record_type": "region"
    },
    "record_type": "cloud_vpn",
    "endpoint": "64.16.243.3:5134",
    "server_ip_address": "172.27.0.1/24"
  }
}
```

## Wait for provisioning

Poll [`GET /v2/wireguard_interfaces/{id}`](/api-reference/wireguard-interfaces/retrieve-a-wireguard-interfaces) until `status` is `provisioned`. This takes a few minutes. Peers can be added once it is provisioned.

## Create a peer

Register the host as a peer of the WireGuard Interface with [`POST /v2/wireguard_peers`](/api-reference/wireguard-interfaces/create-a-wireguard-peer):

```json theme={null}
{
  "name": "laptop",
  "wireguard_interface_id": "749de8c6-bbd0-42dd-9a16-770a519b565d"
}
```

Telnyx generates the host's key pair and returns its `private_key` once, in this response. Store it.

```json theme={null}
{
  "data": {
    "name": "laptop",
    "created_at": "2026-10-09T23:06:14.665447Z",
    "public_key": "mOlLNRWGCiSkXpBXKMeC6QvTNRTb7lVMaa/GrOIskm8=",
    "updated_at": "2026-10-09T23:06:15.052007Z",
    "last_seen": null,
    "wireguard_interface_id": "749de8c6-bbd0-42dd-9a16-770a519b565d",
    "id": "79701b5e-9d7f-4dd1-8b80-45bae4304856",
    "record_type": "wireguard_peer",
    "private_key": "<peer private key>"
  }
}
```

To keep the private key on the host instead, generate the key pair there and send only the public key as `public_key`. The response then has no `private_key`.

```bash theme={null}
umask 077
wg genkey | tee peer.key | wg pubkey
```

## Configure the host

[`GET /v2/wireguard_peers/{id}/config`](/api-reference/wireguard-interfaces/retrieve-wireguard-config-template-for-peer) returns a configuration template as plain text:

```ini theme={null}
# Telnyx CloudVPN config. Target OS: Linux

[Interface]
PrivateKey = <! INSERT PEER PRIVATE KEY HERE !>
Address = 172.27.0.2/32

[Peer]
PublicKey = dM4BrhaKqRVoq+mMD+4mmQ5KTFkcutiXnfN2Ztk+3Sw=
AllowedIPs = 172.27.0.0/24
Endpoint = 64.16.243.3:5134
PersistentKeepalive = 1
```

The file describes the tunnel from the host's side: `[Interface]` is the local host itself, and `[Peer]` is the WireGuard Interface in Telnyx.

| Section | Field | Value |
| - | - | - |
| `[Interface]` | `PrivateKey` | The host's private key, in place of the placeholder. |
| `[Interface]` | `Address` | The host's address on the WireGuard Interface's subnet. The first host gets the address after the WireGuard Interface. |
| `[Peer]` | `PublicKey` | The WireGuard Interface's `public_key`. |
| `[Peer]` | `AllowedIPs` | The prefixes that the host routes via the tunnel, starting with the WireGuard Interface's subnet. |
| `[Peer]` | `Endpoint` | The WireGuard Interface's `endpoint`. |
| `[Peer]` | `PersistentKeepalive` | How often, in seconds, the host sends a keepalive to the WireGuard Interface. |

Replace the placeholder with the host's private key and save the file as `/etc/wireguard/wg0.conf`. On Linux, bring the tunnel up:

```bash theme={null}
sudo wg-quick up wg0
```

## Verify

`sudo wg show` lists the local host as `interface` and the WireGuard Interface in Telnyx as `peer`, with a recent handshake:

```text theme={null}
interface: wg0
  public key: mOlLNRWGCiSkXpBXKMeC6QvTNRTb7lVMaa/GrOIskm8=
  private key: (hidden)
  listening port: 48065

peer: dM4BrhaKqRVoq+mMD+4mmQ5KTFkcutiXnfN2Ztk+3Sw=
  endpoint: 64.16.243.3:5134
  allowed ips: 172.27.0.0/24
  latest handshake: 1 second ago
  transfer: 124 B received, 180 B sent
  persistent keepalive: every 1 second
```

The WireGuard Interface answers on its address:

```bash theme={null}
ping -c 3 172.27.0.1
```

[`GET /v2/wireguard_peers/{id}`](/api-reference/wireguard-interfaces/retrieve-the-wireguard-peer) reports the peer's `last_seen` time.
