These days there’s ads and trackers and malicious JS everywhere. It is almost what makes the internet tick at this point it would seem. Luckily for us we are not alone in the fight against intrusive ads and other unwanted data passing over our network. There are some incredibly smart people working very hard on our behalf to at least curb the worst of these offenders by way of various ad blocking technologies.

These tools have varying methods for blocking and in kind varying levels of efficiency and effectiveness. One of the most overlooked and most effective means of ad blocking is via a method knows as DNS filtering.

What Is DNS Filtering?

Ads and similar unwanted content can be blocked simply to using a DNS server configured to block access to as advertising domains or other hosts which are known to serve ads by spoofing or otherwise masking the address.

What We’re Doing

In this guide we will go over an extremely simple way to deploy your very own wireguard VPN complete with PI Hole to completely block out all of those ad-serving domains.

What You Need

What’s included with Oracle Cloud Free Tier


  • Your choice of Autonomous Transaction
  • Processing or Autonomous Data Warehouse. 2 databases total, each with 1 OCPU and 20 GB storage.


  • 2 virtual machines with 1/8 OCPU and 1 GB memory each.


  • 2 Block Volumes, 100 GB total.
  • 10 GB Object Storage.
  • 10 GB Archive Storage.

Additional Services

  • Load Balancer: 1 instance, 10 Mbps bandwidth.
  • Monitoring: 500 million ingestion datapoints, 1 billion retrieval datapoints.
  • Notifications: 1 million sent through https per month, 1,000 sent through email per month.
  • Outbound Data Transfer: 10 TB per month.

How it works

  • Use your Always Free resources as long as you want with no time constraints—subject only to the capacity limits noted.
  • When your 30-day trial period for the expanded set of services ends, you can continue using Always Free services with no interruption.
  • Always Free and Free Trial instances can be seamlessly upgraded to paid at any time.
  • Existing Oracle Cloud customers have access to Always Free services automatically—no new sign up required.

Signing up for Oracle Free Tier

Navigate to and input your information and click next.

Make sure to select “Ashburn” as your primary region.

💡 If you don’t want to use your card number for verification you can signup for free at and get $5 for free at the same time.


Finish the signup process (no more than 5 minutes) and you’re good to go.

Creating our Virtual Machine

Once we’re all logged in, on our dashboard, click “Create VM Instance”.

First we input a name for our instance and second select the compartment (the default is fine). Then we need to click “Change Image”. We need to select “Canonical Ubuntu 18.04”.

Make sure you have the “Always Free Eligible” VM type selected

Next we need to generate our SSH Keys. And finally we click Create.

Connecting to Your VM

On the next page, under “Instance Access” click “Show” next to “Pubic IP Address”. Copy this and SSH into your VM with the earlier utilized SSH keys.

Modify VNIC

After creating the virtual machine scroll down and click “VNIC” on the left in the side bar under Resources and edit your VNIC.

Check “Skip source/destination check”

Save changes.

Modify Firewall in Oracle

  1. When viewing your instance in the control panel, under “Primary VNIC” click “Public Subnet”
  2. Then click “Default Security List for vnc-0000000”
  3. Click “Add Ingress Rules”

Rule 1:

  1. Source Type: CIDR
  2. Souce CIDR:
  3. IP Protocol: UDP
  4. Destination Port: 51820
  5. Description: WireGuard UDP
  6. Click “Additional Ingress Rule”

Rule 2:

  1. Source Type: CIDR
  2. Souce CIDR:
  3. IP Protocol: UDP
  4. Destination Port: 51820
  5. Description: WireGuard UDP
  6. Click the blue “Add Ingress Rules” button.

Setting Up WireGuard

There are a lof of different configuration utility choices for deploying WireGuard these days, but none beat the simplicity provided by The PiVPN Project. What their project allows us to do is curl and pipe (or download and run) a single bash script and run through a short wizard to completely configure everything for us.

From the PiVPN Team:

  • Even though this installer makes everything so trivial, it doesn’t mean it gives you trivial security settings.
  • Everything has been upgraded right out of the box beyond the default settings to harden the security of the server and client. Starting with offering you the ability to enable unattended-upgrades which will automatically patch your server with security updates.
  • Next, the server configuration will only use the latest TLS protocol. Both the data and control channels use upgraded AES and SHA256 encryption and hash algorithms.
  • Options are pre-configured to verify your server certificate to battle MITM attack vectors. All this and more are configured out of the box by the pivpn installer.
  • This is a detailed level of hardening you’ll have a difficult time finding elsewhere.

Installing PiVPN

To install pivpn simply run the below commands

$ curl -L | bash

Modifying wg0.conf

$ sudo nano /etc/wireguard/wg0.conf

Paste the two PostUp and PostDown lines under [Interface] so the end result looks similar

# Copy these two lines into wg0.conf
# PostUp   = iptables -A FORWARD -i %i -j ACCEPT; iptables -A FORWARD -o %i -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
# PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -D FORWARD -o %i -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE

# Example File Structure:

# [Interface]
# Address =
# ListenPort = XXXX
# PostUp   = iptables -A FORWARD -i %i -j ACCEPT; iptables -A FORWARD -o %i -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
# PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -D FORWARD -o %i -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE

#AllowedIPs = XXX.XXX.XXX.XXX/32

Save the config file by pressing Control+X and then Y then [ENTER]

Now just restart WireGuard like so

$ sudo wg-quick down wg0
$ sudo wg-quick up wg0

Structure of the wg0.conf Configuration File

Address defines the internal IP address of your wireguard server. It should be in the same subnet as client IP’s.

PrivateKey is your server’s private key.

ListenPort defines the port you will use to connect to your wireguard server. You’ll need to make it accessible from the outside through your firewall (sudo ufw allow 1194/any).

PostUp and PostDown specify commands that are executed every time wireguard starts or stops on your server. The iptables command allows your clients to connect to the internet.

The [Peer] part defines information about a client. We’re now preparing a [Peer] block for connecting our first client.

PublicKey is our server’s public key

AllowedIPs: Defines the internal IP address that client will be assigned upon connection. Just change the last digit for every client (10.6.0.XX/32). Remember not to assign (server IP) and stay below For our example, we’ll assume that our client will get the IP address

Make Sure WireGuard Starts on Boot

$ sudo systemctl enable wg-quick@wg0.service
$ sudo systemctl restart wg-quick@wg0.service

Adding a Client Configuration

$ pivpn add

This will ask you to name the client. Specify any name you like, such as “phone”

Then, if using a mobile device you can view the QR code by running the below command and selecting the proper client configuration from the prompt.

$ pivpn -qr

Mobile Phone (optional)

If you are using a mobile device, you can now open WireGuard, click Add, click QR Code, and scan the QR code shown on the screen in your terminal. Name your profile and enable the tunnel.

Ensure Connectivity

Make sure your Wireguard client configuration has a DNS set to the IP of your wireguard adapter (i.e. - This makes sure we use PiHole as the DNS resolver.

Once connected to WireGuard make sure you can goto

Ensure you have connectivity.

Once verified disconnect from the tunnel and go back to your terminal session.

Installing Pihole

For ease of administration and for being able to run other services on the server I’m running Pi-Hole in a docker container using the official docker image. Installing docker is well covered for most OS’s, so I’ll skip it here.

If your wireguard IP is not then modify it in the below script before running


docker run -d \
    --name pihole \
    -p -p \
    -p \
    -p \
    -e TZ="America/Chicago" \
    -v "$(pwd)/etc-pihole/:/etc/pihole/" \
    -v "$(pwd)/etc-dnsmasq.d/:/etc/dnsmasq.d/" \
    --dns= --dns= \
    --restart=unless-stopped \

printf 'Starting up pihole container '
for i in $(seq 1 20); do
    if [ "$(docker inspect -f "{{.State.Health.Status}}" pihole)" == "healthy" ] ; then
        printf ' OK'
        echo -e "\n$(docker logs pihole 2> /dev/null | grep 'password:') for your pi-hole: https://${IP}/admin/"
        exit 0
        sleep 3
        printf '.'

    if [ $i -eq 20 ] ; then
        echo -e "\nTimed out waiting for Pi-hole start start, consult check your container logs for more info (\`docker logs pihole\`)"
        exit 1

Save and exit the file. Let’s call it

Make it executable by chmod +x

and finally run it with ./

Troubleshooting Docker

IF your get a permission denied message you need to be added to the docker group.

$ sudo usermod -aG docker $USER
$ newgrp docker

Verify it works before continuing like so

$ docker run hello-world

Still having problems?

If you initially ran Docker CLI commands using sudo before adding your user to the docker group, you may see the following error, which indicates that your ~/.docker/ directory was created with incorrect permissions due to the sudo commands.

WARNING: Error loading config file: /home/user/.docker/config.json -
stat /home/user/.docker/config.json: permission denied

To fix this problem, either remove the ~/.docker/ directory (it is recreated automatically, but any custom settings are lost), or change its ownership and permissions using the following commands:

$ sudo chown "$USER":"$USER" /home/"$USER"/.docker -R
$ sudo chmod g+rwx "$HOME/.docker" -R

All Done - Pi Hole Access

Enter pihole -a -p to reset the pihole admin password. Then you should now be able to access your pihole admin UI while connected to the WireGuard VPN by going to

Have issues? Let me know!

I can help! @DevinStokes on Twitter.