Affiliate disclosure - This post contains Contabo affiliate links. If you grab a VPS through them, we earn a commission at no extra cost to you.
You set up WireGuard on a laptop, it works, and copying that same config to a phone takes ten seconds. Both connect. For a while nothing looks wrong.
Then both are connected at once, and one of them stops receiving traffic. Not with an error, not consistently, and usually while you are trying to do something else.
What the server sees
WireGuard identifies a peer by its public key. Not by IP, not by device, not by name. Two devices carrying the same private key are, to the server, one peer that keeps moving.
Every handshake updates the endpoint recorded for that peer, the address and port the server sends replies to. The phone handshakes, replies go to the phone. The laptop handshakes, replies go to the laptop. The one that did not handshake most recently keeps sending packets that arrive fine, and stops receiving anything back.
That is the whole mechanism, and it explains the symptom exactly: connectivity that flips between two devices at intervals nobody controls, because the handshake interval is not something you schedule.
The three consequences, in order of how much they will cost you
You cannot tell them apart. wg show lists one peer, one handshake time, one transfer counter. Traffic from the phone and the laptop is summed. If you ever need to know which device did something, that information does not exist.
You cannot revoke one. Removing the key from the server removes access for every device holding it. A lost phone means cutting the laptop too, then reissuing to both.
AllowedIPs becomes ambiguous. On the server, AllowedIPs is how a packet is matched to a peer. Two devices behind one peer entry share one tunnel address, so anything that routes to that address reaches whichever device is currently holding the endpoint.

The fix: one key and one address per device
On the client, or on the server if you are generating for someone else:
wg genkey | tee phone.key | wg pubkey > phone.pub
On the server, add a peer block per device, each with its own address:
[Peer]
# laptop
PublicKey = <laptop.pub>
AllowedIPs = 10.10.0.2/32
[Peer]
# phone
PublicKey = <phone.pub>
AllowedIPs = 10.10.0.3/32
Add it live, without disconnecting anyone:
wg set wg0 peer <phone.pub> allowed-ips 10.10.0.3/32
⛔ Then write it into the config file too. wg set changes the running interface and nothing on disk; a reboot loses it. That trap, and the rest of the peer lifecycle, is covered in adding a WireGuard peer.
Removing one device later is then a single command, and it touches nothing else:
wg set wg0 peer <phone.pub> remove
The comment line is not decoration
Nothing in the protocol carries a device name, so a peer list of twelve public keys is unreadable six months later. A # phone comment above each block is the only label that will ever exist, and the day you need to revoke one in a hurry is the day you will want it.
Two adjacent cases that are not this
A preshared key is shared on purpose. PresharedKey is symmetric and must be identical on both ends of one peer pair. That is not key reuse across devices, and the two are easy to confuse: see the preshared key guide.
One device, several tunnels is fine too. A laptop can hold different keys for different servers with no conflict, because the identity is per tunnel rather than per machine.
If you are issuing configs to devices regularly, generating the QR code is the fast part, and it deserves the same discipline: the WireGuard QR code contains the private key in full, so one code per device and never a shared one.
★ Nuremberg GDPR datacenter · ✓ Dedicated IPv4 included · 200+ Mbps guaranteed
Self-host your VPN on your own VPS → ContaboFull root access · public IPv4 · pick your region→


