Skip to content

WireGuard Isn’t a VPN — It’s a Superpower

Control your home network from a cabin, coffee shop, or coworking space. No paid services, no sketchy workarounds.


Ever wish your home network followed you around? Not just some remote login or a janky web portal full of sketchy port forwards. I mean real access — like you never left home.

Ever wish all your servers were on the same local network? Even if they live on opposite sides of the planet?

Ever wish you could connect two remote Docker networks like they were on the same machine? You can.

That’s what WireGuard does — securely. It’s not about hiding your IP (though you can do that). It’s about creating a fast, simple, rock-solid tunnel between machines or networks you control.

If you’ve had those thoughts — you’re in the right place. We’re going to walk through how WireGuard works, how to set it up, and the game-changing things you can do with it.

WireGuard isn’t just another VPN tool. It’s kernel-level encryption and networking — fast, minimal, secure. But take a moment to appreciate what that means:

WireGuard is baked into the Linux kernel. It’s not a plugin or a package — it’s part of the OS. That means it runs as close to the metal as possible, with near-zero overhead.

By extension, it’s also part of Android. Microsoft added it to the Windows kernel starting in Windows 10 version 2004. Apple didn’t — on macOS and iOS, it runs in user space. Still fast, but not quite the same.

The point is: this thing is legit. Let’s dive in.

The Peer Concept

Before we go further, there’s one thing you should know: WireGuard isn’t your typical client-server setup.
All devices are peers.

You might say you’re “connecting to a server,” but in WireGuard terms, that “server” is just another peer. Why? Because any device can act as a server — including a device that’s technically a client. It all depends on how you route traffic.

A Raspberry Pi at home? It can be the central hub.
Your laptop? It can be both a client and a relay to something else.

You’ll see what I mean the moment you configure your first connection:
There’s no special “client” or “server” software.
The config files look the same on both sides.
That tripped me up at first — but it’s part of what makes WireGuard so flexible.

And to be clear: WireGuard isn’t about hiding your IP or spoofing your location.
That said… you can use it like a traditional VPN. Many commercial VPNs give you WireGuard config files — and you can roll your own, too, by generating your own keys, setting up peer endpoints, and defining how traffic should be routed.

The key takeaway?
Once you’ve set up one WireGuard connection, you’ve basically learned them all.


Quick Concepts

WireGuard doesn’t use a traditional client-server model. Every device is a peer. But what makes a peer a “server” or a “client” depends entirely on which direction traffic flows — and who initiates it.

So before we move on, here’s a mental model that helps:

  • All peers are equal — but some listen for connections, others initiate
  • Configs are symmetrical in structure, but differ in values
  • Peers can route traffic to each other or through each other

You’ll see this come up again when we get to [Interface] vs [Peer] blocks.

Also: WireGuard isn’t just encryption — it’s networking too. Let’s explore how that works.

WireGuard Is Both Encryption and Networking

Part of learning WireGuard is learning Linux networking principles — because WireGuard doesn’t reinvent networking for itself. It builds on what’s already there.

It’s a VPN, sure. But it’s also a network interface. You bring up a WireGuard tunnel the same way you bring up any other network interface, and your system can route packets through it just like a regular NIC. The only difference? Those packets get wrapped — like a dark-tinted van, encrypted and unreadable from the outside.

Network interface? NIC?
These are what you see when you run ip link show, or when you look at your network settings. They include WiFi, Ethernet, LTE, bridges (e.g., Docker networks), and more.

In most WireGuard examples, the go-to interface name is wg0 — but you can name it whatever you want. When decision fatigue hits, you’ll default to wg0, wg1, and so on.

So before we go deeper, let’s take a peek at the parts that make up a WireGuard config.

ATTENTION
The key thing about WireGuard is that not all fields are used.
I should probably type that twice.

ATTENTION
Depending on the peer’s role — like client or server — and whether you’re routing internet traffic or just linking two networks, different fields apply. There’s no one-size-fits-all recipe. But don’t worry — I’ll give you the pointers you need to feel confident in most real-world setups.

Interface

This is the section WireGuard uses to create the network interface
(e.g. wg0).

IMPORTANT
The Interface section on a “client” corresponds to a Peer section on the “server”.

  • Private Key – required; your secret; don’t share it

  • Public Key – required; derived from your private key; this is what other peers need

  • Address – required; the internal IP(s) this peer will use, like 10.0.0.2/24

    Although it looks singular, this is actually a comma-separated list of static IP addresses — there’s no DHCP in WireGuard land.
    Why multiple IPs? You can assign both IPv4 and IPv6.
    Also, your IP must match an entry in the server’s AllowedIPs, or the connection won’t work.

  • Listen Port – optional; the UDP port WireGuard listens on (commonly 51820)

    “Clients” don’t listen. Leave this empty unless this peer is expecting incoming connections.

  • DNS – optional; mostly used on clients to set DNS servers; only IP addresses allowed

    This can be the IP of a WireGuard peer — but make sure that peer is reachable via AllowedIPs, and that it can resolve names itself.
    If it can’t reach public DNS or resolve private hosts, your whole setup might break. Use with care.

Peers

This is who you talk to. You can have one, or you can have a whole list.

From the perspective of a “client”
you can route different IP ranges to different peers — maybe one peer handles internet traffic, another handles your home network, and so on.

From the perspective of a “server”
the peer list is like a user list — it authenticates who’s allowed in and what network resources they can access.

Each peer has these fields:

  • Public Key – their public identity; used to encrypt traffic sent to them

    Usually, you’ll set up the “server” first and generate its private-public key pair.
    Then you generate a private-public key pair for each peer.
    You’ll need to securely distribute the peer’s key pair (for use in their Interface section)
    and the server’s public key (for use in their Peer section).

  • Preshared Key – optional; adds an extra layer of encryption

  • Endpoint – IP and port of the peer (e.g. 1.2.3.4:51820)

    Usually a public internet IP. That port must be open and reachable — often needs a firewall rule.

  • Allowed IPs – required; single IPs or entire IP ranges

    This sets up routing rules. Think of it like herding groups of sheep — but they’re packets.
    This is where split tunneling happens.
    If you don’t include all IPs (e.g. 0.0.0.0/0), any not listed here will be routed outside the tunnel.

  • Persistent Keepalive – optional; helps with NAT traversal (commonly set to 25 seconds)

    ⚠️ Warning

    You’ll often see this suggested for phones — don’t do it.

    Unless your phone needs to be reachable at all times, this setting will keep it awake and drain battery. Battery-saving restrictions might prevent — but some apps will “suggest” disabling them.


Once you see this format, it clicks:
Each device configures itself, lists its peers, and that’s it.

You’re now doing secure, peer-to-peer encrypted networking.

Advanced Fields: PostUp and PostDown

If you’re using wg-quick to manage your interface, you get two powerful helpers: PostUp and PostDown.

These are shell commands that run after the interface is brought up (PostUp) and before it’s taken down (PostDown).

They’re often used to:

  • Add firewall rules (iptables or nftables)
  • Enable IP forwarding for routing traffic
  • Set up NAT for internet sharing
  • Add custom routes or DNS tweaks

Example:

[Interface]
PostUp = iptables -A FORWARD -i %i -j ACCEPT
PostDown = iptables -D FORWARD -i %i -j ACCEPT

%i is a placeholder for the interface name (like wg0).

You don’t need these for simple setups, but once you start doing things like routing all traffic through WireGuard or linking networks, PostUp and PostDown are essential.

So What Can You Do With WireGuard?

VPN stands for Virtual Private Network — but it’s not just about hiding your IP.

A VPN is any secure connection between two points. That’s it. Once that’s in place, what you do with it is up to you.

WireGuard is one way to do it — and a very good one — but it’s not the only tool. Open-source alternatives include IPSec, SSH tunneling, OpenVPN, and SoftEther. All of them can securely connect two devices, or even two entire networks.

There’s no hard limit. You can get as creative as you want.
Once you understand the basics, you can repeat the setup wherever and whenever you need it.

I’ll give you a few practical examples to get the ideas flowing.

Cloudflare Tunnel — Argo Tunnel

It used to be called Argo Tunnel, but now it’s just Cloudflare Tunnel. You’ll find it packaged as cloudflared in most Linux distros — the “d” stands for daemon, since it typically runs as a systemd service.

This isn’t a WireGuard example per se — but it’s the same pattern. And you could absolutely build something like this yourself using WireGuard — see below.

A Cloudflare Tunnel creates a secure connection between any device you own and the Cloudflare network. More specifically, it connects to a Cloudflare reverse proxy — a server that handles incoming HTTP requests on ports 80 and 443.


Cloudflare Proxy Example
Let’s say you run a WordPress site. You point your domain to your server’s IP in the Cloudflare dashboard and flip the Proxy switch. Now Cloudflare acts as a middleman: it receives requests from the internet, fetches pages from your server, and delivers them to visitors.


What’s the advantage?

  • Cloudflare caches your assets at the edge (CDN)
  • Your origin server is protected and hidden
  • You benefit from Cloudflare’s built-in security features

But what about Cloudflare Tunnel?
A tunnel does the same job — but flips the flow.
Instead of Cloudflare pulling content from your server, your server pushes a secure connection up to Cloudflare.

Requests hit Cloudflare → get routed through the tunnel → reach your local app → response goes back the same way.


You could replicate this whole pattern with WireGuard:

  • Create a secure tunnel to a VPS or proxy
  • Route inbound requests over WireGuard
  • Hide your true origin
  • Keep your services private and secure

In fact, why don’t we do that now?

Your Own Tunnel with a Proxy

Let’s say you’ve got a home server — just a basic PC running a web server for Wordpress.

You set up a WireGuard connection to a free VPS (yes, they exist — search around).
You configure the corresponding peer on the VPS.

Now that VPS can reverse proxy your home server.
Clean, private, and entirely under your control.

I have left out the actual conf because we focus on that below.


This might be a little outside the scope of this article, but here’s what it could look like:

  • Your home server runs WordPress in a Docker container
  • The container exposes port 8080 to the host
  • Your VPS runs Nginx
  • Nginx uses proxy_pass to route traffic to the WireGuard IP of your home server on port 8080

Believe it or not — that’s it.


I know, I know — you probably want all the config examples, step-by-step guides, and systemd service files. That’s fair. But here’s the move:

Get the WireGuard connection working first.
Don’t overwhelm yourself by cramming everything in at once.

The first time you set up WireGuard will take a bit more head-scratching than the second time. But once it clicks, you’ll be reusing the pattern everywhere.

And yeah, I’m adding context here — because understanding how this fits into the bigger picture makes everything less abstract. But the nitty-gritty? Save it for when you’re actually implementing it.

Your Very Own Hide-My-IP VPN

I don’t recommend this for a few reasons — but who cares.
What we care about right now is understanding how WireGuard works.

Here’s why I wouldn’t recommend it:

  • Data transfer costs money — and commercial VPNs are cheaper.
  • Commercial VPNs usually have servers in more countries.
  • You’re better hidden in a crowd (anonymity loves company).

But let’s implement it anyway — for the sake of learning.


Take the same free VPS from earlier and the same peer-to-peer WireGuard config.
This time, on your home PC, you tweak the config to route internet traffic through the VPS.

How?

By adding a specific IP range to AllowedIPs:

AllowedIPs = 0.0.0.0/0, ::/0
  • 0.0.0.0/0 = all IPv4 traffic
  • ::/0 = all IPv6 traffic
  • Separate them with a comma

With that in place, your home PC will route all outbound traffic through the WireGuard tunnel to the VPS.

On the VPS side, as long as IP forwarding is enabled and no firewall is blocking traffic, it will forward your packets to the internet as if they originated from the VPS itself.

You’ve effectively hidden your IP.

Congratulations — you’ve just built your own VPN exit node.

Lazy Phone VPN — With Added Benefits

I’m still on the fence about naming this section Lazy Phone VPN — but now that I have, here we are.
The real point is: being permanently connected to home.

Install the official WireGuard app on your smartphone — it’s available on both Android and iOS. The icon looks like a dragon wrapped into a figure 8. There are other good apps too, but the official one works well.

The goal: as soon as you leave the house, your phone connects back home.

If you’ve got WireGuard running on your router or a home server, your phone can tunnel straight into your LAN.

But listen up — there’s more.
If your home network itself connects to the internet through a VPN (like Mullvad or Proton), then your phone will not only get access to your LAN, but also inherit your home’s VPN connection:

Phone via LTE → Home → VPN → Internet

You don’t need an extra VPN app on your phone. You can:

  • Access your home services
  • Browse the web via your home connection
  • And — yes — cut the kids’ WiFi from the North Pole

I personally discovered another benefit:
My mobile carrier didn’t offer IPv6, but my home VPN provider did.
So by routing traffic through home, my phone got IPv6 too.
Sure, global IPv6 rollout has been slow — but it felt great dunking on my carrier.


If you want to route all phone traffic through WireGuard, use this in your config:

AllowedIPs = 0.0.0.0/0, ::/0

This captures everything: IPv4 and IPv6.

But if you only want LAN access and want the rest to go out over your phone’s LTE? Split the traffic:

AllowedIPs = 10.0.0.0/24, 192.168.0.0/24, fd00::/64

Assumptions:

  • Your WireGuard subnet is 10.0.0.0/24
  • Your LAN is 192.168.0.0/24
  • Your LAN uses IPv6 via fd00::/64

Anything else — websites, cloud apps, etc. — goes out your normal mobile connection.

Yes, this may raise more questions than it answers. CIDR notation can be a rabbit hole. But here’s a quick primer:

  • 10.0.0.0/24 = all IPs from 10.0.0.1 to 10.0.0.254
  • 10.0.0.0/16 = all IPs from 10.0.0.1 to 10.0.255.254
  • 0.0.0.0/0 = all IPv4 addresses
  • ::/0 = all IPv6 addresses

You can even get clever and split traffic between two peers — half to one, half to the other.

I’ll be honest:
I’m resisting the urge to keep going down the CIDR path, because it’s a whole topic on its own. But know this:

CIDR notation is a more compact version of the subnet mask format you might’ve seen before.
192.168.0.1/24 is the same as 192.168.0.1 with subnet mask 255.255.255.0.

Oh, and why not add that 192.168.0.1/32 refers to that single IP address.

I’m confident some of you are starting to piece it together.
There’s still so much more about CIDR — but we march forward, friends.

Actual Config Examples — Finally

You might be wondering why I didn’t drop these earlier.
The answer is simple: we shouldn’t get bogged down by implementation details before we understand what we’re doing.

That said — you might still feel like there’s more to it. And… you’re both right and wrong.


Why that’s false
Because the config fields we covered earlier are really all you need to set up a working WireGuard connection.
It’s that simple.

Why that’s true
Because the “more to it” parts come from Linux networking, not WireGuard itself.

WireGuard is relatively simple.
But if you want to do clever things — like selective routing, traffic segmentation, or multihop VPN — then concepts like CIDR, routing tables, and nftables start to matter.

Also, while you probably know what a firewall is, be aware that cloud providers, home routers, and VPS dashboards don’t always call it that.

Instead, you’ll see terms like:

  • Port forwarding
  • NFT rulesets
  • Security groups
  • Traffic rules

They’re all doing the same thing: controlling what traffic gets through.


The good news?

You generally just need to forward UDP port 51820 to your WireGuard server.
Once that’s done, all tunnel traffic is allowed — one config to rule them all.

WireGuard doesn’t complicate networking — it simplifies it.

Linux Networking Primer

Didn’t I say we’d do examples now?
Um, sorry?

Before we dive into more configs, we need to peek under the hood — just a little.

To get started with Linux networking, try the ip route command. It shows how Linux routes traffic.


Start by noticing the default via line.
This is your system’s fallback — when no other route matches, packets go there.
That usually means: “send it to the internet.”


Now, after you bring up a WireGuard interface, run ip route again.
You’ll see a new line for your WireGuard subnet — like 10.0.0.0/24, if you’ve followed the earlier examples.

What does that mean?
It means: “if a packet’s destination IP falls in this range, send it through this interface.”

If that interface is a WireGuard tunnel, then the packet gets encrypted — the payload is scrambled using your private key.
The result isn’t an IP packet anymore — it’s wrapped inside a UDP packet that acts as a sealed envelope.


Where does that UDP packet go?
It’s sent to the Endpoint of the first peer that matches — based on the AllowedIPs.

AllowedIPs can overlap between peers, so order matters.
It’s up to you to keep routing clean and predictable.

When the peer receives that UDP packet, it decrypts it, extracts the original packet, and routes it to its original destination.


Yes, it sounds like magic. But it’s just solid networking, wrapped in crypto, wrapped in UDP.

The WireGuard Config — Starter

Finally — take two.

Let’s walk through the basics.
We’ll cover how to generate those private and public keys in the next section.

# example.conf

[Interface]
PrivateKey = gLGoLUmtdK7iYu+TBVmwKCIgupdu8bA9F30ETa/1Kks=
Address = 10.0.0.2/32
DNS = 10.0.0.1

[Peer]
PublicKey = gMu/QIGmYeoKlSvjgX8qy1g7YcSCjNHKiI6MfDhFkB4=
AllowedIPs = 0.0.0.0/0
Endpoint = 119.225.114.28:51820

The file above can be used in mobile apps, desktop clients, or directly from the command line. We’ll focus on the command line.

When used, this config will create a new network interface and set up IP routes automatically.

sudo wg-quick up example.conf
ip address show wg0
ip route
wg show
  • wg-quick up creates and activates the interface
  • ip address show wg0 shows the assigned IP address on the WireGuard interface
  • ip route shows how traffic will be routed (look for 0.0.0.0/0)
  • wg show shows the current WireGuard state

A note about wg show: If there’s no active WireGuard peer listening at the configured Endpoint, or the keys don’t match, then wg show will indicate that the connection hasn’t been established (e.g., latest handshake: never).

wg show is your go-to command to confirm whether things are working or not.

A Complete P2P Example

We begin by creating the keys.

The following must be done on both peers.
Then you exchange public keys.

umask 077
wg genkey | tee privatekey | wg pubkey > publickey
  • umask 077 sets restrictive permissions on any files created during this session — readable only by you.
    You can exit or run umask 022 afterward to go back to default.
    (Alternative: run chmod 600 privatekey manually after creation.)
  • wg genkey generates a private key
  • tee privatekey writes the private key to a file while also piping it forward
  • wg pubkey uses the private key to generate a corresponding public key
    (> publickey saves it to a file)

You can run these commands as many times as you want — the keys are throwaway unless used.
Just make sure the private and public keys you actually use match up.


Next, decide which peer will be the “server”.

  • One peer listens
  • The other initiates the connection

On the “server”:

  • It listens for incoming connections
  • Its [Peer] entries define which public keys can connect
  • The AllowedIPs must match the client’s Address
# server-example.conf

[Interface]
PrivateKey = gLGoLUmtdK7iYu+TBVmwKCIgupdu8bA9F30ETa/1Kks=
Address = 10.0.0.1/32
ListenPort = 51820

[Peer]
PublicKey = gMu/QIGmYeoKlSvjgX8qy1g7YcSCjNHKiI6MfDhFkB4=
AllowedIPs = 10.0.0.2/32

On the “client”:

  • Address is the client’s static IP inside the tunnel — must match an entry in the server’s AllowedIPs
  • AllowedIPs tells the client what traffic to send to the peer — see it as a routing rule
  • Endpoint is where to find the server (IP and port)
# client-example.conf

[Interface]
PrivateKey = ABDTf9fhUJjJh/LEHDujtCveNvTTo1hJi+6dpfn9LHw=
Address = 10.0.0.2/32

[Peer]
PublicKey = W9x4MU3bWPOsB1TRj8CfOZ9V9E0M8aMy7aqkIQNgaFU=
AllowedIPs = 0.0.0.0/0
# AllowedIPs = 10.0.0.0/24
Endpoint = 119.225.114.28:51820

The client’s AllowedIPs = 0.0.0.0/0 means:
“send all traffic through this peer” — making this a hide-your-IP style connection.
For LAN-only access, you’d just list the internal subnet (e.g., 10.0.0.0/24).

“Client” and “Server” Mindset

When you’re tuning those config files, try shifting your perspective:
Position yourself as either the client or the server.
Even though WireGuard treats all devices as peers, the way you fill out the config gives each one a role.

  • Leaving fields out means something
  • Including them means something else
  • And the values inside those fields? They shape how the peer behaves

In a “server” config:

  • Each [Peer] is like a user — someone you’re allowing to connect
  • AllowedIPs defines which IPs that client is allowed to use inside the tunnel
    (Think: static IP assignment)

In a “client” config:

  • AllowedIPs controls what traffic is routed through the tunnel
  • You can route:
    • All traffic → hide-your-ip style
    • Only some traffic → LAN access only
    • Or mix and match, using multiple peers for different ranges

This “role mindset” helps when you’re troubleshooting or extending your setup.
Even though both sides are peers, thinking like a client or server keeps things sane.

The Hybrid Config

We haven’t talked yet about configs that act as both “client” and “server.”
I’m calling it a hybrid, but that’s not an official term.

If a config sets up both a listener and a connection initiator, it can act as a relay — a bridge between otherwise unreachable peers.


Why would you need this?
Because some network setups just won’t let two peers talk directly.
But if:

  • Peer A can reach Peer B
  • Peer B can reach Peer C
  • …and A and C can’t see each other

Then B can relay traffic between them.

WireGuard makes this not just possible — but simple.
You’re just adding peers and adjusting routing.


I’m not giving specific examples here because:

  • There are too many possible variations, and
  • You already have the building blocks to create whatever topology you need

Once you understand how roles, AllowedIPs, and routing work, you can build anything.

Extra Stuff You Might Need

Here are a few extras that didn’t quite fit earlier, but matter depending on what you’re building:


🔁 IP Forwarding + NAT

If your server acts as a gateway (e.g., AllowedIPs = 0.0.0.0/0 on the client), you’ll need to:

sysctl -w net.ipv4.ip_forward=1
iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE

Replace eth0 with your actual outbound interface.
Without this, traffic reaches the tunnel but dies on the way out.

🔐 Preshared Keys

For an extra layer of encryption:

wg genpsk > psk

Then add this to both [Peer] blocks:

PresharedKey = <contents of psk>

People
This is entirely optional — and most times completely unnecessary. WireGuard’s core cryptography (Curve25519, ChaCha20, Poly1305) is already top-tier and well-audited.
It comes down to:

Are you the kind of organization (or person) that gets targeted?

If the answer is “yes”, then use preshared keys.

🧩 Multiple Interfaces

You can have wg0, wg1, etc.
Use the ip rule and ip route commands to keep routing tables separate if needed. Does that open a can of worms again?

In fact,
you can leave the Name field out.
They will automatically get sequential wg names.

🔎 A Note About DNS

The DNS field in your WireGuard config is widely supported — mobile apps, desktop clients, and GUI tools usually respect it.

Do they use wg-quick under the hood? Or reimplement it?
Doesn’t really matter — the key thing is: it often works, but not always the same way.

DNS behavior can vary depending on:

  • Your DNS manager (systemd-resolved, resolvconf, NetworkManager, etc.)
  • Whether DNS entries are appended, prepended, or replace existing ones
  • Your WireGuard client (Linux CLI, Android, macOS, Windows, etc.)

If DNS breaks after the tunnel comes up, it might not be WireGuard — it might be your system’s DNS handling.

Some practical tips:

  • On Android, iOS, and Windows:
    If DNS doesn’t behave, try a different WireGuard client — yes, there are alternatives.

  • On Linux:
    If your distro uses systemd and you’re using wg-quick, you’re golden — DNS will likely Just Work™.

  • On KDE and GNOME:
    They have built-in WireGuard support that usually hooks into NetworkManager.
    If things get weird, falling back to wg-quick can help isolate the issue.


You Know More Than You Think

If you’ve made it this far, you’re no longer just kicking the tires — you’ve seen under the hood.
You’ve learned how WireGuard works, what config fields actually mean, how to route traffic, and how to use it for more than just hiding your IP.

But maybe more importantly:
You’ve seen how a simple, clean protocol like WireGuard can unlock massive flexibility — remote access, internal mesh networks, relays, reverse proxies, and secure tunnels that Just Work™.

You don’t need to memorize every command.
You just need to understand the mental model.
And now you do.

So take a break. Try a small setup. Break it. Fix it. Then build something a little bigger.
This is where self-hosting becomes self-empowering.

WireGuard isn’t just a VPN. It’s a lever.
You now know how to pull it.

Let’s go.


How am I doing?

I care about making these articles better. If something was unclear, helpful, surprising—or if you just want to say hi—you can leave a comment on the discussion thread below.

This happens on our forum (Discourse), so you may be asked to log in or create an account.