Raspberry Pi 4 VPN, DNS, and Web Servers

First Time Setup

  1. Format micro SD Card (SD Memory Card Formatter)
  2. Download Raspbian Buster Lite ISO
  3. Burn the ISO on to the micro SD Card(Etcher)
  4. Create an empty file called ssh with no extension in the boot drive of the SD Card to enable SSH
  5. Add your WiFi Network
    • Create a file called: wpa_supplicant.conf in the boot drive
    • Replace NETWORK-NAME with the Network Name
    • Replace NETWORK-PASSWORD with the Network Password
      • country=US
        ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
  6. Eject micro SD Card and Boot from the micro SD Card
  7.  SSH into the Pi with username: pi,  password: raspberry, port: 22, and IP: RASPBERRY_DHCP_IP.
  8. Change the password from the default: sudo raspi-config

Installing Pi-Hole

curl -sSL https://install.pi-hole.net | bash

Force the Raspberry Pi to have a static IP and point the default DNS Server in your router to the static IP. Now scour the webs for block list that you’d like, ex: Introducing the Amazing/Sensational/Remarkable/Revolutionary; #1 Blocklist 🙂

Installing PiVPN

curl -L https://install.pivpn.io | bash – Will work when Raspbian Buster Lite is supported (Few more weeks)
curl -L 
 | TESTING= bash – For now use the test repository.

Set up Port Forwarding in your router. Create a new ovpn file using pivpn add and set Interface listening behavior to Listen on all interfaces in the “http://RASPBERRY_DHCP_IP/admin/settings.php?tab=dns” page.

Installing NGINX

There are many ways of running NGINX and lighttpd together, like binding two IPs, using a reverse proxy, or using different ports. Having separate IPs may be the most versatile and reverse proxying the most elegant, but using two ports is the simplest solution. We’ll keep our public web servers on 80 (so users don’t have to manually specify a port) and our private lighthttpd Pi-Hole on an obscure random port.

Add  server.port := RANDOM_PORT1 in  /etc/lighttpd/external.conf to override Pi-Hole from using port 80. Stop lighthttpd and install NGINX. Edit the listening port from 80 to a random number in /etc/nginx/sites-enabled/default because Pi-Hole will lock it, unless you directly change the “lighttpd.conf” file which is bad practice and reset on updates. The solution we implement works without crons jobs and is simple. Change root /var/www2/html; to root /var/www2/html;because we are want to isolate our public web server and Pi Hole’s server as much as possible. Create this directory and now restart nginx and lighthttpd.

sudo nano /etc/lighttpd/external.conf

server.port := 8001

sudo systemctl stop lighttpd
sudo apt install -y -t buster nginx
sudo nano /etc/nginx/sites-enabled/default
 listen 8002 default_server;
listen [::]:8002 default_server;

root /var/www2/html;
cd /var/
sudo mkdir www2
cd www2
sudo mkdir html
sudo service nginx restart
sudo systemctl restart lighttpd

Verify that you can access both servers by going to “http://RASPBERRY_DHCP_IP:RANDOM_PORT1/admin/” and “http://RASPBERRY_DHCP_IP:RANDOM_PORT2/”. Now create a test PHP file in /var/www2/html.

sudo nano /var/www2/html/index.php

The test file won’t work until we install and configure PHP. Let’s install 7.3 as that’s currently the latest version. Run the following:

sudo apt install -y -t buster php7.3-fpm php7.3-curl php7.3-gd php7.3-intl php7.3-mbstring php7.3-mysql php7.3-imap php7.3-opcache php7.3-sqlite3 php7.3-xml php7.3-xmlrpc php7.3-zip php7.3-bcmath php-apcu  mariadb-server

Now find where you see location ~ \.php$ { in /etc/nginx/sites-enabled/default and uncomment the lines inside except for the php_cgi option. 

location ~ \.php$ {
include snippets/fastcgi-php.conf;
# With php-fpm (or other unix sockets):
fastcgi_pass unix:/run/php/php7.3-fpm.sock;
# With php-cgi (or other tcp sockets):
# fastcgi_pass;
fastcgi_intercept_errors on;
fastcgi_buffers 16 16k;
fastcgi_buffer_size 32k;

Great now we have a web server. Now, we can add some max-execution-times for the Pi if we want. Also, use SSH Keys and disable password logins(Quick Video).

Scroll to top