# Setting up a PiVPN on Raspberry

{% hint style="danger" %} <sub><mark style="color:red;">Disclaimer — Educational Use Only and Liability Limits<mark style="color:red;"></sub>

<sub><mark style="color:red;">The procedures and information described in this article are provided for<mark style="color:red;"></sub> <sub><mark style="color:red;"> </sub><sub><mark style="color:red;">**educational and personal research purposes only**<mark style="color:red;"></sub><sub><mark style="color:red;">.<mark style="color:red;"></sub>\ <sub><mark style="color:red;">They are intended to help readers understand, configure, and manage a secure VPN using PiVPN in a controlled, private environment.<mark style="color:red;"></sub>\ <sub><mark style="color:red;">Improper network or firewall configuration may lead to connectivity loss or exposure of private data.<mark style="color:red;"></sub>\ <sub><mark style="color:red;">The author does not accept responsibility for any direct or indirect damage, data loss, or service interruption resulting from the use of this guide.<mark style="color:red;"></sub>
{% endhint %}

PiVPN is a simple installer that configures WireGuard or OpenVPN on a Raspberry Pi.In this guide, we will use PiVPN, a lightweight, fast, to enable encrypted connections from outside your home network.&#x20;

{% hint style="info" %} <mark style="color:$info;">With this method, we’ll configure a VPN</mark> <mark style="color:$info;"></mark><mark style="color:$info;">**quickly and easily**</mark> <mark style="color:$info;"></mark><mark style="color:$info;">on a Raspberry Pi — a solution that</mark> <mark style="color:$info;"></mark><mark style="color:$info;">**anyone can replicate**</mark> <mark style="color:$info;"></mark><mark style="color:$info;">without advanced networking skills.</mark>\ <mark style="color:$info;">On the next page, we’ll explore how to configure WireGuard or OpenVPN</mark> <mark style="color:$info;"></mark><mark style="color:$info;">**manually**</mark><mark style="color:$info;">, without relying on PiVPN.</mark>
{% endhint %}

<mark style="color:blue;">**Prerequisites and Hardware**</mark>

To implement PiVPN, we would need:

* A Raspberry Pi with the Raspberry Pi operating system installed (the Lite version is recommended).
* A reliable Internet connection (preferably Ethernet).
* Administrative access to the router (We will use these later for port forwarding).
* A device for VPN access (phone or computer).

<mark style="color:blue;">**Installing PiVPN**</mark>

We will start by installing the Raspberry Pi Imager tool.

<figure><img src="https://2833470610-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FxEQmpwmdm3I8FZ925fn8%2Fuploads%2FfHFvYdOVulcm1C71OLcq%2Fimage.png?alt=media&#x26;token=8073c8e1-8e6c-404b-9785-0b855d8975c8" alt=""><figcaption></figcaption></figure>

After installing it, we need to:

1. Select the operating system for our Raspberry model. After selecting the operating system and SD card, we need to set up:
   * Set a hostname (e.g., `pihole`).
   * **Enable SSH** for remote administration.
   * Configure Wi-Fi credentials (if not using Ethernet).
   * Set a username and password.

<figure><img src="https://2833470610-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FxEQmpwmdm3I8FZ925fn8%2Fuploads%2FMcx9ikDewsTi0DHSBCpy%2Fimage.png?alt=media&#x26;token=3afff360-0213-4a98-993e-bf06b80b52bc" alt=""><figcaption></figcaption></figure>

After that, we will wait for the process to finish and then we can turn on our Raspberry.&#x20;

Our newly turned on Raspberry will be in **DHCP mode**, meaning that it will take an IP assigned by the router for a time-lease (i.e. a variable period of time) and this means that it will change in the future. **How can we prevent this value from changing?** There are two options (in both cases, we will assign a static IP):

1. In the **first case**, we would set a static IP outside the DHCP Range Pool, i.e. the range in which the router automatically assigns IPs.
2. In the **second case**, we would set a Reservation inside the DHCP Range Pool, making sure that the DHCP will never assign the IP that we have excluded with the Reservation.

<sub>`(To make these changes, you will need to connect to the router with administrative permissions to view the DHCP address pool and make the reservation, while the static IP address must be assigned by the Raspberry once chosen).`</sub>

Now the question is, **what is the difference between the two**?&#x20;

The difference is that a **reservation** maintains the entire network configuration managed by the router, avoiding possible IP conflicts. By reserving an IP, the router always assigns the same address to the Raspberry based on its MAC address, ensuring stability while continuing to use DHCP.&#x20;

Setting a **static IP** outside the pool, on the other hand, depends entirely on manual configuration and can cause conflicts if the network configuration changes or if another device accidentally uses the same address. For this reason, reservation is usually the safest and most reliable option.

Now, to find the Raspberry, I scan my local network to see what is assigned to the Raspberry.

<mark style="color:$info;">**`Tip`**</mark><mark style="color:$info;">`: You can use tools like nmap, Fing, or Advanced IP Scanner to quickly identify devices connected to your LAN. Or simply connect to tour router, where you can usually view this information.`</mark>&#x20;

<figure><img src="https://2833470610-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FxEQmpwmdm3I8FZ925fn8%2Fuploads%2FHUU8ZwPIlm07L6AdlNpp%2Fimage.png?alt=media&#x26;token=5836d8ee-5227-442d-a8aa-538edeccf87a" alt=""><figcaption></figcaption></figure>

Now we need to connect via SSH. To connect via SSH, we can use the prompt (or PowerShell if we want to use autocompletion), or we can use PuTTY.

<figure><img src="https://2833470610-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FxEQmpwmdm3I8FZ925fn8%2Fuploads%2FtaWPfgXPEEhzx75PJHZD%2Fimage.png?alt=media&#x26;token=4ee381d8-309b-4cca-a09c-96350aa11640" alt=""><figcaption></figcaption></figure>

But before installing PiVPN, update your Raspberry Pi:

```bash
sudo apt update && sudo apt upgrade -y
```

<figure><img src="https://2833470610-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FxEQmpwmdm3I8FZ925fn8%2Fuploads%2FVXkcdBVlB8V8XKzI3J4H%2Fimage.png?alt=media&#x26;token=0e88fd58-c675-4c35-a928-e4473ef9bd8f" alt=""><figcaption></figcaption></figure>

After that, we can proceed with the installation:

```bash
curl -L https://install.pivpn.io | bash
```

<figure><img src="https://2833470610-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FxEQmpwmdm3I8FZ925fn8%2Fuploads%2FEFvcXVqDMg5B87PNIUqX%2Fimage.png?alt=media&#x26;token=c702d86d-9410-4cc7-bbb3-4729fe7511ce" alt=""><figcaption></figcaption></figure>

Once the installation program has started, a series of configuration screens will appear asking you to:

* Accept the terms and conditions
* Configure a **static IP** (via DHCP reservation or manual assignment)
* Select the user account that PiVPN will use, in this case the administrator account created previously

In addition, there will be a series of pages where you will only be asked to select ‘**OK**’, so they have not been included as they are standard configurations and cannot be customised.

<figure><img src="https://2833470610-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FxEQmpwmdm3I8FZ925fn8%2Fuploads%2FVHbryTuSUz6NezTh6emt%2Fimage.png?alt=media&#x26;token=35849305-fcc9-4e7b-90ac-60744ec62b18" alt=""><figcaption></figcaption></figure>

Depending on your needs, you can choose to use **WireGuard** or **OpenVPN**. (In my case, I set up the VPN using WireGuard.)

But why choose one over the other? **WireGuard** is preferable when speed and simple configuration are required: its lightweight code ensures high performance even on hardware such as the Raspberry Pi. **OpenVPN**, on the other hand, is a better choice when flexibility and the ability to operate even in restrictive networks are required, thanks to TCP support and port 443.

In practice, WireGuard is ideal for modern, high-performance use, while OpenVPN is more suitable for complex scenarios or older devices.

<figure><img src="https://2833470610-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FxEQmpwmdm3I8FZ925fn8%2Fuploads%2FcIrLWdTibN0suItoew75%2Fimage.png?alt=media&#x26;token=b0b40287-4cba-4c49-8d58-118be7a956f2" alt=""><figcaption></figcaption></figure>

When prompted for the **VPN port**, leave the default `51820` or select a different one if needed.

<figure><img src="https://2833470610-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FxEQmpwmdm3I8FZ925fn8%2Fuploads%2F2WJTN7Ur8WBT79ia4Ibe%2Fimage.png?alt=media&#x26;token=9b672592-9669-4807-8819-340fdc4436c9" alt=""><figcaption></figcaption></figure>

Next, we need to select our preferred DNS provider: in this example, I have chosen **Quad9**, but you can use any reputable provider.

<figure><img src="https://2833470610-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FxEQmpwmdm3I8FZ925fn8%2Fuploads%2FcGLReaG1lWt92ECvIgdo%2Fimage.png?alt=media&#x26;token=05100de4-b915-4f9f-a2c2-2cb224cbf5c8" alt=""><figcaption></figcaption></figure>

If your ISP provides a **dynamic public IP**, you can set up a dynamic DNS service (e.g., DuckDNS, No-IP) to keep your VPN accessible from outside your network.\
If you have a **static public IP**, simply enter it when prompted.

<figure><img src="https://2833470610-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FxEQmpwmdm3I8FZ925fn8%2Fuploads%2FF0FwMvzk9KRXpCONKf72%2Fimage.png?alt=media&#x26;token=36b4778b-569f-42e8-8eb8-14a33e364372" alt=""><figcaption></figcaption></figure>

<figure><img src="https://2833470610-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FxEQmpwmdm3I8FZ925fn8%2Fuploads%2FgIAYrv5LgQ9HLaQtyyDY%2Fimage.png?alt=media&#x26;token=8cd61431-2d92-401c-b9c9-93e4f1a4b289" alt=""><figcaption></figcaption></figure>

<mark style="color:blue;">**Client Setup**</mark>

Once the installation is complete, we can create a client configuration:

```bash
pivpn add
```

You will be asked to enter a name (e.g., phone or laptop).\
PiVPN will generate both a **.conf file** and a **QR code** to facilitate configuration on mobile devices.

<figure><img src="https://2833470610-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FxEQmpwmdm3I8FZ925fn8%2Fuploads%2F0OUfBrj2Ldlph156NXmp%2Fimage.png?alt=media&#x26;token=5a2a2f55-936a-4aab-893b-9921b4dc31ee" alt=""><figcaption></figcaption></figure>

<figure><img src="https://2833470610-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FxEQmpwmdm3I8FZ925fn8%2Fuploads%2FF86QBPF8hef75QKONBlw%2Fimage.png?alt=media&#x26;token=1cee6faf-8d64-449a-a3ed-94b1731adabf" alt=""><figcaption></figcaption></figure>

To scan the QR code on your phone, install the WireGuard app (Android/iOS).\
In the app, select Add Tunnel → Scan from QR Code and scan the code displayed on the Raspberry Pi terminal.

If you’re setting up WireGuard on a **desktop**, import the `.conf` file instead:

* Connect to your Raspberry Pi using **SFTP** or **FTP** (e.g., WinSCP, FileZilla)
* Download the configuration file located in `/home/<user>/configs/`
* Import it into the WireGuard desktop app

<figure><img src="https://2833470610-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FxEQmpwmdm3I8FZ925fn8%2Fuploads%2FLsvPEOjCVWQH7YNExiZ3%2Fimage.png?alt=media&#x26;token=94bf4d72-f631-4ee8-8ec8-ddb562847446" alt=""><figcaption></figcaption></figure>

**Router Configuration**

To make your VPN accessible from outside, configure port forwarding on your router:

* **Port:** 51820 (In my case, I left the default one, but if you have changed it, you must enter the one you have set)
* **Protocol:** UDP

  ***But why do we choose UDP and not TCP?***&#x20;

  UDP is preferable because it offers lower latency and better performance, making the VPN connection faster and more responsive. Unlike TCP, UDP does not wait for confirmation packets, reducing overhead and improving speed, which makes it ideal for WireGuard and optimised OpenVPN configurations. TCP adds reliability features such as error correction and retransmission, but these slow down the VPN tunnel. For this reason, TCP is only used in restrictive networks, while UDP is the best choice under normal conditions.
* **Destination IP:** the static IP of your Raspberry Pi (e.g. `192.168.1.9`)

Make sure your firewall allows incoming connections on that port.

<mark style="color:blue;">**Using Your VPN**</mark>

Once everything is configured:

* The WireGuard app will show the connection status (connected/disconnected).
* When active, all your traffic is encrypted and routed through your home network.

<figure><img src="https://2833470610-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FxEQmpwmdm3I8FZ925fn8%2Fuploads%2F2eOiyXcammUARek5F8r9%2Fimage.png?alt=media&#x26;token=e1fd858d-d0b6-44f6-8ddf-5aee2be8735b" alt=""><figcaption></figcaption></figure>

<figure><img src="https://2833470610-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FxEQmpwmdm3I8FZ925fn8%2Fuploads%2F2PtIqQJINMrX5xbQNcy3%2Fimage.png?alt=media&#x26;token=37b4d3bf-7b2c-4ad9-93d3-8a57282c3cdd" alt=""><figcaption></figcaption></figure>

<figure><img src="https://2833470610-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FxEQmpwmdm3I8FZ925fn8%2Fuploads%2FlRDtrIgXQAlFb5fAZzs5%2Fimage.png?alt=media&#x26;token=ba95dab3-6622-4966-988c-e0350151f8e0" alt=""><figcaption></figcaption></figure>

<mark style="color:blue;">**Testing and Troubleshooting**</mark>

After connecting, you should be able to securely access your LAN and the Internet through your VPN.\
If, despite a correct configuration, you cannot reach LAN resources (for example, you cannot ping local devices), run:

```bash
pivpn -d
```

This diagnostic command will analyze the configuration and suggest solutions for the most common problems.
