NoctisNode
← GuidesNetworking2026-10-238 min

WireGuard PersistentKeepalive 25 and PresharedKey on a VPS

PersistentKeepalive = 25 sends a keepalive every 25 s so NAT keeps the tunnel open; set it on the client behind NAT. PresharedKey adds a symmetric, post-quantum hedge.

Short answer: `PersistentKeepalive = 25` tells WireGuard to send a tiny authenticated packet to the peer every 25 seconds, which keeps NAT and stateful firewall mappings alive so the other side can still reach you. You normally set it only on the peer that sits behind NAT (a laptop, phone or home router), not on a VPS with a public IP. `PresharedKey` is an optional extra 256-bit symmetric secret per peer pair, generated with `wg genpsk`, that is mixed into the handshake as a hedge against future quantum attacks on Curve25519.

This guide explains both options and gives a working server and client config for a WireGuard VPS. For the full VPN setup with NAT and DNS, see the WireGuard VPN guide.

What PersistentKeepalive = 25 actually does

WireGuard is quiet by design: when no data flows, it sends nothing. That is good for privacy and battery, but routers doing NAT and connection tracking drop idle UDP mappings, often after 30 seconds and sometimes after a few minutes. Once the mapping is gone, packets from the server can no longer reach a client behind NAT until the client sends something again.

`PersistentKeepalive` is an interval in seconds. With `25`, the peer sends an empty, encrypted keepalive whenever it has not sent anything for 25 seconds. The value 25 is the one recommended in the WireGuard documentation because it stays safely under the shortest common UDP timeouts. The setting is off by default (`0`), and the overhead is a small packet roughly every 25 seconds per peer.

ValueEffectWhen to use
0 or unsetNo keepalives; tunnel is silent when idleBoth peers have public IPs, or the client only ever initiates traffic
25Keepalive every 25 s of idle timeClient behind NAT or CGNAT that must stay reachable
15–20More frequent keepalivesNetworks with unusually aggressive UDP timeouts
60+Fewer packets, more risk of mapping lossRarely useful; most NAT devices time out sooner

Which side needs PersistentKeepalive

Set the keepalive on the peer that cannot be reached directly, which is the one behind NAT. That peer sends the packets outward, refreshing its own NAT mapping. A VPS with a public IPv4 address has no NAT in front of it, so it does not need the option to stay reachable, and it cannot keep a remote NAT open by itself because it only learns the client endpoint from the client's packets.

If the client only browses through the tunnel, it reconnects instantly whenever it sends traffic, so a keepalive is optional. You need it when the server or other peers must initiate connections to the client, for example SSH into a home machine, monitoring, or a site-to-site link.

  • ▹Laptop or phone behind NAT to VPS: set `PersistentKeepalive = 25` on the client only.
  • ▹VPS to VPS, both with public IPs: usually leave it unset; see [the WireGuard mesh guide](/guides/wireguard-mesh-vps-cluster).
  • ▹Home server behind CGNAT exposed through a VPS: set it on the home server, otherwise the VPS loses the path within minutes.
  • ▹Mobile clients: a keepalive costs some battery; enable it only if the device must be reachable.

PresharedKey: the optional symmetric layer

WireGuard's handshake uses Curve25519 key exchange. A large enough quantum computer could, in theory, break that exchange, and an adversary could record traffic today and decrypt it later. `PresharedKey` mixes an additional 256-bit symmetric key into the handshake. Symmetric keys of that size are not considered practically breakable by known quantum algorithms, so if the PSK stays secret, recorded traffic stays protected even if the public-key part is broken.

The PSK is per peer pair, must be identical in both peers' `[Peer]` sections, and should be unique for every pair. It does not replace the private keys; it is an extra layer. If the PSKs do not match, the handshake silently fails and you see no `latest handshake` in `wg show`.

  • ▹Generate it with `wg genpsk`, which outputs a random base64-encoded 32-byte key.
  • ▹Transfer it over a channel you already trust, such as SSH, never in chat or email.
  • ▹Use one PSK per pair: in a mesh of five nodes, that is ten different PSKs.
  • ▹Rotate it like any other secret when a device is lost or retired.

Generate keys and a PresharedKey

Install the tools on Debian 12/13 or Ubuntu 24.04 with `apt install wireguard`, then generate keys on the machine where each private key will live. The PSK can be generated on either side and copied to the other. `umask 077` makes sure the files are readable only by root.

umask 077
cd /etc/wireguard

# on the VPS
wg genkey | tee server.key | wg pubkey > server.pub

# on the client
wg genkey | tee client.key | wg pubkey > client.pub

# once, on either side; copy to the other over SSH
wg genpsk > client.psk

Server config on the VPS: /etc/wireguard/wg0.conf

The server has a fixed listen port and no keepalive and no `Endpoint` for the client, because it learns the client's current address from authenticated packets.

[Interface]
Address = 10.8.0.1/24, fd08::1/64
ListenPort = 51820
PrivateKey = <contents of server.key>

[Peer]
# laptop
PublicKey = <contents of client.pub>
PresharedKey = <contents of client.psk>
AllowedIPs = 10.8.0.2/32, fd08::2/128

Note · Open UDP 51820 in the VPS firewall and start the tunnel with `systemctl enable --now wg-quick@wg0`. Lock down SSH as described in the SSH hardening guide, and check key permissions with the StrictModes guide, before exposing anything else.

Client config behind NAT

The client points at the VPS public address and carries the keepalive. Use `AllowedIPs = 10.8.0.0/24, fd08::/64` for a private tunnel only, or `0.0.0.0/0, ::/0` to send all traffic through the VPS.

[Interface]
Address = 10.8.0.2/32, fd08::2/128
PrivateKey = <contents of client.key>

[Peer]
PublicKey = <contents of server.pub>
PresharedKey = <contents of client.psk>
Endpoint = 203.0.113.10:51820
AllowedIPs = 10.8.0.0/24, fd08::/64
PersistentKeepalive = 25

Note · A NoctisNode Wisp VPS (1 vCPU, 1 GB RAM, $6 per 28-day cycle) with a dedicated IPv4 is enough for a personal WireGuard endpoint, and it can be paid in Monero or other crypto with only an email and password at signup.

Verify and troubleshoot

Run `wg show` on both sides. A healthy client shows a recent `latest handshake`, `persistent keepalive: every 25 seconds`, and `preshared key: (hidden)` for the peer.

  1. 01.No handshake at all: check that UDP 51820 is open on the VPS and that `Endpoint` uses the right IP and port.
  2. 02.Handshake works without PSK but not with it: the PresharedKey differs between the two configs; copy it again.
  3. 03.Tunnel works, then the server cannot reach the client after a minute: add `PersistentKeepalive = 25` on the client.
  4. 04.Change the keepalive without restarting: `wg set wg0 peer <server-public-key> persistent-keepalive 25`.
  5. 05.Add a PSK from a file at runtime: `wg set wg0 peer <public-key> preshared-key /etc/wireguard/client.psk`.

FAQ

QWhat does PersistentKeepalive 25 mean in WireGuard?

AIt makes the peer send an encrypted keepalive packet after 25 seconds without other traffic. This keeps NAT and firewall mappings open so the tunnel stays reachable from the other side.

QShould PersistentKeepalive be on the server or the client?

AOn the peer behind NAT, which is almost always the client. A VPS with a public IP does not need it and cannot keep the client's NAT mapping open by itself.

QIs a WireGuard PresharedKey required?

ANo, it is optional. It adds a symmetric secret to the handshake as a hedge against future quantum attacks on Curve25519, so it is a good default for long-lived tunnels.

QHow do I generate a WireGuard PresharedKey?

ARun `wg genpsk > peer.psk` and put the same value in the `PresharedKey` line of both peers' `[Peer]` sections. Use a different PSK for every peer pair.

QDoes PersistentKeepalive use a lot of bandwidth?

ANo. It sends one small packet roughly every 25 seconds of idle time, which is negligible on a VPS, though it can slightly reduce battery life on phones.

WireGuard PersistentKeepalive 25 and PresharedKey on a VPS · NoctisNode