JavaScript is required to view this page.
Skip to content
Home Assistant Voice Bundle Deals!
Home Assistant Voice Bundle Deals!
How To: ODROID-C4 VPN Server

How To: ODROID-C4 VPN Server

Find our ODROID-C4 VPN Server kit here.

ODROID C4 VPN Server Setup Guide

Think of a VPN, which stands for "Virtual Private Network," like a secure, encrypted tunnel through the internet. You can use your own personal VPN server to connect remotely to your home network from anywhere with internet access. Once connected, you can access local resources such as file shares, printers, or even remote into your home computers as if you were there connected to your home network. A VPN can also be used to protect your web browsing while connected to public Wi-Fi by passing all your internet traffic through the VPN to your home. That way, no one else on the public Wi-Fi can see what you’re doing on the web.

Prerequisites

  • A computer running Windows/macOS/Linux
  • ODROID C4
  • 8GB or larger eMMC Module
  • eMMC to microSD Adapter
  • microSD Card Reader
  • Latest DietPi image for the ODROID C4
  • Latest version of balenaEtcher


1. Flashing DietPi to the eMMC Module

DietPi is a slim, no-fluff distro of Debian made to run ultra fast on single board computers like the ODROID C4. We’ll be using it here as the base operating system for the VPN server. DietPi is quick and easy to install, boots in just a few seconds, and is very light on resources.

Begin by downloading the C4 DietPi image as well as installing balenaEtcher on your computer. Etcher provides a simple method of writing images to removable media. We will use this to flash DietPi onto the eMMC module for the C4.

Before opening Etcher, make sure to connect your eMMC module to the microSD adapter, and insert the adapter into the microSD card reader on your computer. Then, with Etcher open, click Flash from file. Browse to where you’ve downloaded the DietPi image and select it. Next, click Select target and choose the eMMC module. Note that the selected drive/module will be completely erased, so make sure to choose the correct one. Lastly, click Flash! to begin writing the image to the eMMC module. Etcher will need administrator privileges to do this, so depending on your computer you may need to allow the app to make changes or enter an admin password. Once the process is complete, we can close Etcher, eject the eMMC module, and move over to the C4 to prepare for the first boot.


2. First Boot

Begin by connecting the eMMC module to the underside of the C4. Next, connect an ethernet cable and monitor to the C4. Lastly, connect power, but before you do, it’s important to note that DietPi does not “install” the way traditional operating systems do. Rather, the image flashed to eMMC is already complete and ready to boot. However, upon first boot, DietPi will expand its filesystem to take up the full size of the eMMC module. Sometimes, as this is happening, nothing will appear on screen for a minute or two. Wait for it to finish and do not unplug power from the C4, or you will likely leave DietPi unbootable and have to flash the image over again.

Once finished and fully booted, DietPi should come to a login prompt. Above that prompt should be the IP address that the C4 was assigned by your router. Write down the IP address as it will be used in the following steps to connect remotely to the C4.


3. Initial Login

The rest of the setup can now be done remotely from another computer far easier than on the C4 itself. From here on, we will connect and control the C4 from another computer using a protocol called SSH. If you’re using Windows, click the Start button, type Windows PowerShell, and open it. If using a Mac, press the Command key and the Spacebar together on your keyboard to bring up Spotlight, type terminal, and open it. In the new window, type the following command, substituting the actual IP address of the C4 for ipaddress:

ssh root@ipaddress

For example, if the IP address of your C4 is 192.168.1.57, you would type:

ssh root@192.168.1.57

and then press enter on the keyboard. If this is the first time you’re connecting to the C4 over SSH, you will be asked if you’re sure you want to connect. Type yes and press enter again. Lastly, you’ll be asked to type the password for root. For DietPi, the default password for the root account is dietpi. Type the password and press enter, but note that you will not see any characters on screen as you type the password, so take your time and make sure to type it correctly.

Upon first login to the root account, DietPi will begin checking for and installing updates. This process can take several minutes to finish. Once complete, you should come back to a prompt similar to this:

root@dietpi:~$

Since DietPi likely installed several updates, the next step is to reboot the system to finish installing any updates that may need a restart. To do this, simply type the following command and press enter:

reboot


4. Creating New Admin User

The C4 should reboot in just a few seconds, but to be safe, wait about a minute, then try to reconnect to it via SSH following the previous instructions using the root account. DietPi comes with two built-in user accounts. The root account, which in Linux is also known as the superuser, has unrestricted access to change or delete virtually anything on the system. This makes it very dangerous and insecure to use as an admin account. The other built-in user account is simply called dietpi. This is a restricted user, but the username and default password is public knowledge to anyone familiar with the DietPi operating system. So, for better security, we will be creating a new admin user with a unique username and password to administrate the server. We will also be disabling the ability to login with either the root or dietpi accounts because, as stated before, those usernames are public knowledge.

The new admin user should have a unique username that is harder for anyone to simply guess. You should avoid usernames like ‘admin’ as this is also widely used and well known. In this example, we’re going to use ameridroid as our new admin username. Substitute ameridroid in the following command with your desired username and press enter:

adduser ameridroid

You will be prompted to enter a new password for the user. Remember that the password will not show on screen as you’re typing it. Just type carefully and press enter when done. Type the password a second time, pressing enter again when finished. Next, you’ll be prompted to enter full name, room number, work phone, home phone, and other. Just leave each blank and press enter. Lastly, you’ll be asked to confirm if the info is correct. Type y and press enter.

The new user should now be created. In order to make the user an admin, we’ll need to add it to the sudo user group. This will allow the account to run commands with root privileges when needed by typing sudo in front of the command. To add the user to the sudo group, type the following command and press enter. Remember to substitute ameridroid with your chosen username:

sudo usermod -aG sudo ameridroid

With the new user added to the sudo group, we need to log out of the root account and log in to the new admin user. You can either close the PowerShell/terminal window or just type exit and press enter to end the SSH session. Reopen the PowerShell/terminal window and log back into the C4 via SSH, only this time use the new admin username instead of root. Don’t forget to substitute your username for ameridroid and the actual IP address of the C4 for ipaddress:

ssh ameridroid@ipaddress


5. Disabling Root and Dietpi Account Login

As stated previously, it’s not a good idea to use the root account directly for server administration. On most modern Linux systems login to the root account is disabled by default. We’re going to do the same here for root and the dietpi user. While the dietpi user is restricted, its username is public knowledge, so we’ll be disabling its login as well. It’s important to note that we’re just disabling login to these accounts. They’ll still exist on the system, but no one will be able to login to them directly. To do so, type or copy the following commands one at a time, pressing enter after both. Note that the first time you invoke sudo you will be asked to enter the password for your admin account.

sudo passwd -dl root
sudo passwd -dl dietpi


6. Installing Docker

Docker serves as the backbone that the VPN software will run on, so that needs to be installed first. We’ll begin by adding the key to Docker’s repository on the system with the following commands:

sudo apt update
sudo apt install ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/debian/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc

With the key added, we can now add the repository itself to the system with the following commands:

echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/debian $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

Finally, with the repository added we can install Docker with the following commands:

sudo apt update
sudo apt install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

The following command will add the ameridroid user to the newly created docker group on the server so we do not have to use sudo every time we run a command with Docker:

sudo usermod -aG docker ameridroid

After running that command we need to logout and log back in for it to take effect. To logout, simply type exit and press enter. Reconnect to the server via SSH.


7. Installing Dockge

Next we’ll install Dockge. Docker is the platform that lets us run containerized apps, but using Docker alone can be difficult for the average user. Dockge is a simple web interface that will allow us to easily deploy, manage, and update Docker containers from a web browser.

Dockge itself is a Docker container, so deploying it should be simple now that Docker is installed. The following commands will create the necessary folders, download the compose file for Dockge, and then deploy Dockge:

sudo mkdir -p /opt/stacks /opt/dockge


cd /opt/dockge


sudo curl https://raw.githubusercontent.com/louislam/dockge/master/compose.yaml --output compose.yaml


docker compose up -d

Once Dockge finishes deploying, open a web browser and navigate to http://ipaddress:5001. The first time logging into Dockge you should be prompted to create a username and password for Dockge. Once that is done the main Dockge window should load. You can leave that window open for now, as we have more setup to do before we deploy any other containers with Dockge.


8. Registering Domain and Configuring DDNS (OPTIONAL)

Note: If you already have your own domain, or a static IP address you can skip this step. It’s meant for users with dynamic IP addresses from their ISP.

In order to connect to your VPN server while away, you’ll need to use the public IP address of your home network. The main problem with this is most home users do not have what’s called a static IP address. Meaning your public IP address always stays the same. Instead, your internet provider assigns you an address dynamically, which can change over time. To get around this limitation, we’ll be setting up the VPN server to use DDNS. This allows us to create a domain name, for example ameridroid.duckdns.com, that we can use to connect to the VPN server instead of directly using its public IP address, which changes over time.

There are a number of DDNS providers, some paid, some free. For this guide we’ll be using Duck DNS as it’s free and doesn’t require monthly logins to keep it active. To register a domain with Duck DNS visit their website at www.duckdns.org. The simplest way to create an account with them is to sign in with your Google account. Duck DNS is free and to save costs they rely on Google to authenticate accounts. Just click the ‘Sign in with Google’ button at the top of the page to create an account with Duck DNS.

Once signed in you should be able to see your token for Duck DNS. Copy or write this down as you’ll need it when setting up the DDNS container. The token is how Duck DNS verifies your account when the server updates your IP address. In the middle of the page there should be a black and white box that says ‘sub domain .duckdns.org’. This is where you’ll pick what you want the name of your domain to be. For example, ameridroid.duckdns.org. Type in your desired domain name and click the green add domain button. The name you pick should not have spaces in it.

With the domain now registered, move back to the SSH session. We need to create the folder path and config file that DDNS-Updater will use. To do this run the following commands:

sudo mkdir -p /containers/ddns-updater/data


sudo nano /containers/ddns-updater/data/config.json

The second command will open nano, a command line text editor, to create the config.json file that DDNS-Updater uses. This file is how we’ll configure it to update the public IP address of our Duck DNS domain. Copy and paste the following into Notepad on Windows, or TextEdit on Mac:

{
  "settings": [
    {
      "provider": "duckdns",
      "domain": "mydomain.duckdns.org",
      "token": "paste_token_here",
      "ip_version": "ipv4",
      "ipv6_suffix": ""
    }
  ]
}

We need to edit two lines before saving to the server. The first is the domain. Delete the ‘mydomain’ from in front of .duckdns.org and replace it with your own Duck DNS domain. The second thing we need to change is the token. Replace the words paste_token_here with your Duck DNS token from the previous step. If you do not have your token go back to www.duckdns.org, sign in with the same account as before, and copy it from there.

Once done, select all and copy the newly edited template. Move back to the SSH window and paste the text in the open nano window. Press Ctrl+X to save the file. Nano will ask to save modified buffer, press the Y key on your keyboard for yes. Next, nano will ask which file name to write, which should be ‘/containers/ddns-updater/data/config.json’. If so, just press enter on your keyboard to save.

Next we need to make sure the user we’ll be running the container as has ownership and permissions to these folders. Do that with the following commands:

sudo chown -R 1000:1000 /containers/ddns-updater


sudo chmod -R 755 /containers/ddns-updater


Now that we’ve created the necessary config for DDNS-Updater, we can deploy the actual image from Dockge. Move back to Dockge in your web browser and sign back in if necessary. If you closed your browser you can always open the web UI by navigating to http://ipaddress:5001.

From the Dockge homepage click the Compose button. Under Stack Name type ddns-updater. To the right of Stack Name should be a box of colorized text with numbered rows. Select everything in that box and delete it. Copy and paste the following in that box:

services:
  ddns-updater:
    image: qmcgaw/ddns-updater:latest
    container_name: ddns-updater
    network_mode: bridge
    ports:
      - 8000:8000/tcp
    volumes:
      - /containers/ddns-updater/data:/updater/data
    environment:
      - PUID=1000
      - PGID=1000
      - TZ=America/Los_Angeles
      - CONFIG=
      - PERIOD=10m
      - UPDATE_COOLDOWN_PERIOD=10m
      - PUBLICIP_FETCHERS=all
      - PUBLICIP_HTTP_PROVIDERS=all
      - PUBLICIPV4_HTTP_PROVIDERS=all
      - PUBLICIPV6_HTTP_PROVIDERS=all
      - PUBLICIP_DNS_PROVIDERS=all
      - PUBLICIP_DNS_TIMEOUT=3s
      - HTTP_TIMEOUT=10s
      - LISTENING_ADDRESS=:8000
      - ROOT_URL=/
      - BACKUP_PERIOD=0 # 0 to disable
      - BACKUP_DIRECTORY=/updater/data
      - LOG_LEVEL=info
      - LOG_CALLER=hidden
      - SHOUTRRR_ADDRESSES=
    restart: always

If you wish you can change the line TZ=America/Los_Angeles to match your local time zone.

After pasting the text in the box and editing the time zone press the Save button, followed by the Start button. Dockge should begin downloading the DDNS-Updater image and when finished and deployed should say “active”. We can verify that it’s working by visiting http://ipaddress:8000 in a web browser. There isn’t really anything to do from the webpage, it’s just meant to display the current public IP of your domain and let you know the last time it changed.


9. Configuring WireGuard

In this step we’ll configure and install WireGuard using the WG-Easy image. Setup is very similar to DDNS-Updater. The first thing we need to do is create the folder where WireGuard will store its config files. Do this with the following commands:

sudo mkdir -p /containers/wireguard


sudo chown -R 1000:1000 /containers/wireguard


sudo chmod -R 755 /containers/wireguard


After that go back into Dockge and click Compose. Under Stack Name type wg-easy, delete what’s in the box to the right of Stack Name, then copy and paste the following:

services:
  wg-easy:
    environment:
      - PUID=1000
      - PGID=1000
      - LANG=en
      - WG_HOST=mydomain.duckdns.org
      - PASSWORD_HASH=$$2a$$12$$jQaut1GGZVmO3Bdtjt2pcO1Cjgj7mXchB7G7p7sU/JqlvLjeRhWPu
      - PORT=51821
      - WG_PORT=51820
      - WG_DEFAULT_ADDRESS=10.8.0.x
      - WG_DEFAULT_DNS=8.8.8.8, 8.8.4.4
      - WG_ALLOWED_IPS=192.168.1.0/24, ::/1, 8000::/1
      - UI_TRAFFIC_STATS=true
      - UI_ENABLE_SORT_CLIENTS=true
    image: ghcr.io/wg-easy/wg-easy
    container_name: wg-easy
    volumes:
      - /containers/wireguard:/etc/wireguard
    ports:
      - 51820:51820/udp
      - 51821:51821/tcp
    restart: unless-stopped
    cap_add:
      - NET_ADMIN
      - SYS_MODULE
    sysctls:
      - net.ipv4.ip_forward=1
      - net.ipv4.conf.all.src_valid_mark=1

There’s only two parts of this config we need to edit. The first is WG_HOST=mydomain.duckdns.org. Change ‘mydomain’ to match your actual domain, just like with DDNS-Updater. The second thing we need to change is WG_ALLOWED_IPS=192.168.1.0/24, ::/1, 8000::/1. We have two options with this. We can configure it so that even when connected to the VPN, your computer/phone will only send traffic over the VPN if/when you’re communicating with a device on your home local network. For example, if we open a browser and go to google.com, it will bypass the VPN. But if we enter the IP address of a device on our local network at home it will send that through the VPN. Likewise, we can also configure it so that all traffic goes through the VPN regardless.

Both of these options are just the default config the server issues to clients. The config can also be changed from the client by editing from the WireGuard app.

Once done editing the server configuration press the Save button, followed by the Start button. Dockge should once again begin downloading the WG-Easy image and when finished should say “active”. We can access WireGuard’s web interface by navigating to http://ipaddress:51821 in a web browser. The password to login to the web interface should be “odroidc4” without the quotes.


10. Reserve IP and Forward Port

The final two steps to make sure the server works must be done from your home router. You will need to login to your router and reserve the IP of the VPN server so that your router always gives it the same IP address. This is necessary for the next step where you need to forward UDP port 51820 to the IP address of the VPN server (port forwarding). Port 51820 is the port that WireGuard uses to communicate with clients. If you don’t forward it to the server from your router your VPN clients won’t be able to connect.

Once IP reservation and port forwarding are configured on your router you should be able to connect to your VPN from anywhere, as long as you have a mobile or desktop WireGuard app installed.


11. Conclusion

Now that everything is configured, you have successfully set up a VPN server that you can access from anywhere using your mobile or desktop WireGuard app. This provides a secure, encrypted connection back to your home network when traveling or using public Wi-Fi.

Previous article Running Plex on Your ODROID H3+ and H4
Next article Offload Piper and Whisper from your Home Assistant!

Leave a comment

Comments must be approved before appearing

* Required fields

x