How to Install WireGuard and Set Up Client Connections
Summary: Explains how to install WireGuard VPN on a Linux server, covering key generation, firewall opening, and service registration. Includes Mac client conf setup and GUI connection verification steps to help you build a secure remote access environment.

Overview
WireGuard is a tool that lets you configure a peer-to-peer VPN with simple setup and lightweight performance.
This article covers the entire flow of installing WireGuard on a Linux server, configuring the server key, firewall, and service, and then connecting from a Mac client.
It goes through server key generation, wg0 configuration, opening UDP port 51820, client Peer registration, and connection verification in order, so you can follow the same steps to set it up.
Server Installation
Since it runs as a system service, proceed as root.
Basic Installation
1apt install wireguard
Verify installation
1wg --version
Generate Server Key
1mkdir -p /etc/wireguard
2wg genkey | tee /etc/wireguard/server.key | wg pubkey | tee /etc/wireguard/server.pub
3
4# Set permissions
5chmod 600 /etc/wireguard/server.key
Configuration
Create the configuration file in advance
1touch /etc/wireguard/wg0.conf
2chmod 600 /etc/wireguard/wg0.conf
Set up the interface in the configuration file
- Register the server key
- If SaveConfig is enabled, editing this file and then stopping the server will cause the server state to overwrite it
- If you use SaveConfig mode, you should control it via
wg setetc.
1# /etc/wireguard/wg0.conf
2[Interface]
3Address = 10.200.0.1/24
4ListenPort = 51820
5PrivateKey = {server key contents}
6SaveConfig = false
Inbound Configuration (Firewall Setup)
Even though it’s peer-to-peer, the UDP server port must be open for the initial handshake.
Additionally, if you use iptables, you also need to open the port.
1iptables -I INPUT 1 -p udp --dport 51820 -j ACCEPT
2
3# ubuntu 24
4# netfilter-persistent save
5
6# Result
7# run-parts: executing /usr/share/netfilter-persistent/plugins.d/15-ip4tables save
8# run-parts: executing /usr/share/netfilter-persistent/plugins.d/25-ip6tables save
Start the Server
Register and start the service
1systemctl enable wg-quick@wg0
2systemctl start wg-quick@wg0
Check wg
1wg
2
3# Result
4# interface: wg0
5# public key: Y9oH7jnQVVILuRnhekWDRh9s7gCOyOf2HerAfS5Iymw=
6# private key: (hidden)
Check the interface
1ip addr show wg0
2
3# Result
4# 3: wg0: <POINTOPOINT,NOARP,UP,LOWER_UP> mtu 8920 qdisc noqueue state UNKNOWN group default qlen 1000
5# link/none
6# inet 10.200.0.1/24 scope global wg0
7# valid_lft forever preferred_lft forever
Client Installation
Generate the User Client Key (local client work)
- The user’s private key can be generated on the server, but it must not be left on the server afterward
- The server only needs to know the public key text
- Delete the generated private key after moving it to the client
If installing locally on a Mac, you’ll need to install wg if it isn’t already present.
1brew install wireguard-tools
Generate Key
1# Create the directory and move into it
2mkdir -p ~/.wireguard
3cd ~/.wireguard
4
5# Generate key: wg genkey | tee {KeyName}.key | wg pubkey > {KeyName}.pub
6wg genkey | tee user.key | wg pubkey > user.pub
Important! Register the User Key on the Server
Register the peer information in the wg0.conf file
- Multiple Peers can be configured
- Requests sent to AllowedIPs are forwarded to that Peer
1# /etc/wireguard/wg0.conf append
2
3# plzhans
4[Peer]
5PublicKey = {public key contents}
6AllowedIPs = 10.200.0.2/32
Restart the server
1systemctl restart wg-quick@wg0
Client-Server Connection
Understand this as a characteristic of peer-to-peer communication, and simply reverse the server configuration.
Configuring the WireGuard Client
Verify installation
1wg --version
2wg-quick --version
User Client Connection (local client work)
- Endpoint: External public ip
- PersistentKeepalive: Keep alive time
1# ~/.wireguard/xx-server.conf
2
3[Interface]
4PrivateKey = {user private key contents}
5Address = 10.200.0.2/24
6
7[Peer]
8PublicKey = {server key contents}
9Endpoint = {server public IP}:51820
10AllowedIPs = 10.200.0.1/32
11PersistentKeepalive = 25
Run the Client
1sudo wg-quick up ~/.wireguard/xx-server.conf
2
3# stop
4sudo wg-quick down ~/.wireguard/xx-server.conf
Check Client Status
- If this line appears, the connection is finally established: latest handshake: 5 seconds ago
1wg
2
3# Result
4# interface: utun12
5# public key: b69QMnldUd60JLXEUc4j8QzKI/1su1h4e6scx/YgrHE=
6# private key: (hidden)
7# listening port: 64874
8
9# peer: Y9oH7jnQVVILuRnhekWDRh9s7gCOyOf2HerAfS5Iymw=
10# endpoint: 161.33.140.98:51820
11# allowed ips: 10.200.0.1/32
12# latest handshake: 5 seconds ago
13# transfer: 92 B received, 180 B sent
14# persistent keepalive: every 25 seconds
When Using a Client GUI Tool
Import the client conf file you created.
import

Verify the registration

Verify the connection

Verify Access to the Private Server
Verify SSH Access via VPN IP
1nc -vz 10.200.0.1 22
2Connection to 10.200.0.1 port 22 [tcp/ssh] succeeded!
IP Routing
Now you need to set up access to the internal network from the local client via the VPN server (using MASQUERADE).
Assume the following:
- Server’s private network: 10.200.0.0/24
- Server’s network interface: enp0s6
1# /etc/wireguard/wg0.conf append
2[Interface]
3...
4
5# IP FORWARD
6PostUp = sysctl -w net.ipv4.ip_forward=1
7PostUp = iptables -t nat -A POSTROUTING -s 10.200.0.0/24 -o enp0s6 -j MASQUERADE
8PostUp = iptables -I FORWARD 1 -i %i -j ACCEPT
9PostUp = iptables -I FORWARD 1 -o %i -j ACCEPT
10
11PostDown = iptables -t nat -D POSTROUTING -s 10.200.0.0/24 -o enp0s6 -j MASQUERADE
12PostDown = iptables -D FORWARD -i %i -j ACCEPT
13PostDown = iptables -D FORWARD -o %i -j ACCEPT
Conclusion
Once you’ve finished everything from server installation to client connection verification, you can access internal services such as SSH via the VPN IP.
When adding a Peer, you only need to register the public key and AllowedIPs on the server, and keep the private key only on the client.
If you use a GUI client, you can achieve the same connection simply by importing the conf file you created.
The SaveConfig option and the firewall’s UDP port are common sources of mistakes during operation, so it’s a good idea to double-check them before configuring.