DEV Community

Cover image for Self hosting with Pi
Mark
Mark

Posted on

Self hosting with Pi

Self Hosting!

(cough cough, this might take a while... it did for me)

If your looking for the end all be all self hosting guide this is not it, but it will at least give you a good idea of how to do it for your own situation you got going on. Through this guide you'll probably have a better understanding of how hosting works.
Also, I used a Raspberry PI 4 model B for this project.

 

Here is the short version.

TLDR:

  1. Install Linux

  2. Enabling Wifi

  3. Install Nginx and Node.js

  4. Configure UFW

  5. Configure the router

  6. Configuring Nginx config files to listen in on specified ports and folders

  7. Register your site through google domains

  8. Point google domains at your device

  9. Installing Certbot for SSL

  10. Serve to the WEB!

 

 

NOTE:

Most of this tutorial is done from the Linux terminal and is under the assumption of using VS Code with SSH enabled or have access to an SSH client. So if your not already familiar with the terminal or SSH this will be a good place to start.

 

 

1. Installing Linux

Install Linux Server /Ubuntu 20.04 UTS using Raspberry Pi Imager.

You will have to download the Ubuntu 20.04 UTS image separately.
For this I recommend using at least a 32 GB SD card.

Alt Text

 

Once you successfully boot into Linux, its time to get your PI connected to the internet.

 

 

2. Enabling wifi

How to Connect to WiFi from the Terminal in Ubuntu Linux

Identify your wireless network interface name:

There are several ways to identify your network interface name. You can use the ip command, the deprecated ipconfig command or check this file:

ls /sys/class/net
Enter fullscreen mode Exit fullscreen mode

This should give you all the available networking interface (Ethernet, wifi and loopback). The wireless network interface name starts with ‘w’ and it is usually named similar to wlan0.

:~$ ls /sys/class/net
eth0 lo wlan0
Enter fullscreen mode Exit fullscreen mode

Then Edit the Netplan configuration file with the wifi interface details

sudo nano /etc/netplan/50-cloud-init.yaml
Enter fullscreen mode Exit fullscreen mode

YAML files are very sensitive about spaces, indention and alignment. DONT USE TAB KEY FOR SPACING, use 4 (or 2, whichever is already used in the YAML file) spaces instead where you see an indention.

network:

    ethernets:

        eth0:

            dhcp4: true

            optional: true

    version: 2

    wifis:

        wlan0:

            dhcp4: true

            optional: true

            access-points:

                "SSID_name":

password: "WiFi_password"
Enter fullscreen mode Exit fullscreen mode

Generate the configuration using this command:

sudo netplan generate
Enter fullscreen mode Exit fullscreen mode

And now to apply it with:

sudo netplan apply
Enter fullscreen mode Exit fullscreen mode

You should have network connected.

If not, restarting Linux should do the trick.

 

 

3. Installing Nginx and node

just run the commands below one after the other

sudo apt-get update
sudo apt-get install nginx
sudo apt-get install nodejs
Enter fullscreen mode Exit fullscreen mode

 

 

4. Configuring UFW

This enables UFW to run and allows the ports that we need to communicate

Once you have port 22 enable you'll be able to SSH into your PI remotely from any application of your choosing, I recommend VS code and setting up SSH keys as well.

sudo ufw enable

sudo ufw allow 443

sudo ufw allow ssh

sudo ufw allow from 0.0.0.0/24 to any port 22 
Enter fullscreen mode Exit fullscreen mode

 

 

5. Configuring the router

Log into your router and enable the IP address to communicate only on port 443 for https access and SSL certs later on.

Typically you will look for the IP of your PI and assign the port to 443, this will only allow https traffic from outside the network while still allowing you to use port 22 from within the network.

Here is a link for that if you need help as there are many types of routers.

https://www.netspotapp.com/how-to-log-into-router.html

 

 

6. Configuring Nginx config files to listen in on specified ports and folders

Useful commands for managing Nginx and apply updates

To restart and apply changes made

sudo systemctl restart nginx
Enter fullscreen mode Exit fullscreen mode

Tests if the current Nginx configuration is viable

nginx -T 
Enter fullscreen mode Exit fullscreen mode

Make sure to apply changes as you go.

Now go to file location: /etc/nginx/sites-available/default

and change the contents to the following:

server {

    root /usr/share/nginx/html;

    listen [::]:443 ssl ipv6only=on;
    listen 443 ssl;

    location / {
            proxy_pass http://Your IP Address:port number;
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection 'upgrade';
            proxy_set_header Host $host;
            proxy_cache_bypass $http_upgrade;
    }   

}

server {

     if ($host = Yoursite.com) {
        return 301 https://$host$request_uri;
    } 

    listen 80 ;
    listen [::]:80 ;
    server_name Yoursite.com;
    return 404; 

    location / {  
            satisfy any;  
            allow 127.0.0.1;  
            deny all;  
            auth_basic "closed site";  
            auth_basic_user_file conf/htpasswd;  
    }
}
Enter fullscreen mode Exit fullscreen mode

Next go to file location /etc/nginx/nginx.conf

and change that file as well to look like below.

user www-data;
worker_processes auto;
pid /run/nginx.pid;
include /etc/nginx/modules-enabled/*.conf;

events {
    worker_connections 768;
    # multi_accept on;
}

http {

    server {
    listen 80;
    }

    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;
    keepalive_timeout 65;
    types_hash_max_size 2048;
    # server_tokens off;

    include /etc/nginx/mime.types;
    default_type application/octet-stream;

    ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3; # Dropping SSLv3, ref: POODLE
    ssl_prefer_server_ciphers on;

    access_log /var/log/nginx/access.log;
    error_log /var/log/nginx/error.log;

    gzip off;

    include /etc/nginx/conf.d/*.conf;
    include /etc/nginx/sites-enabled/*;
}
Enter fullscreen mode Exit fullscreen mode

 

 

7. Registering your site through google domains

Log into/ register domains.google.com and select Get a new domain, and continue through the process of obtaining your domain name.

Once you have obtained your domain name:

Go to google domains and log in → select your domain of choice → select DNS on the left side bar→ select Dynamic DNS under Synthetic records → select add → gather your Username and Password that google domains generates for your Dynamic DNS synthetic record

Alt Text

 

 

8. Point google domains at your device

a. Have google domains point to and update the reported IP every 30 min. for those of you with dynamic IP addresses

run this script from any directory of your choosing, it will run properly no matter where its stored

nano ~/dns_update_script.sh
    wget https://username:password@domains.google.com/nic/update?hostname=yourdomain.com -qO dns_update_results.txt
    wget https://username:password@domains.google.com/nic/update?hostname=www.yourdomain.com -qO- >> dns_update_results.txt
    echo " Last run: `date`" >> dns_update_results.txt
chmod +x ~/dns_update_script.sh

Enter fullscreen mode Exit fullscreen mode

The script downloads the web pages to the text file (the first wget creates the text file, the second wget appends to the text file) and then I also append the current date and time to the text file.

Remember to replace username:password with YOUR username and password that google domains provide when generating your DNS.

Also do not forget to change yourdomain.com & www.yourdomain.com to the domain name of your site.

b. Setup a cron job to run the script at the start of every hour:

crontab -e
    0 * * * * ~/dns_update_script.sh
Enter fullscreen mode Exit fullscreen mode

 

 

9. Installing Certbot for SSL

Follow the instructions that Certbot provides on there site

https://certbot.eff.org/instructions

 

 

10. Serving to the WEB!

serving your web app to the web with node.js and express or just a static site

The default location to store your site should be:

/usr/share/nginx/html

From that directory you will add your static site or applications that run from your self hosted site

 

 

CONGRATULATIONS!!!

 

At this point you should be able to go to your browser an type in "yourdomain.com"

and see your new website with HTTPS enabled and verified.

Top comments (5)

Collapse
 
thomasbnt profile image
Thomas Bnt ☕

Nice post about selfhosting, you can add #raspberrypi tag on your post if you want!

Collapse
 
markhelmsglitch profile image
Mark

Thanks for letting me know!

Collapse
 
baselakasha profile image
Basel Akasha

It's not recommend to open ports in your home wifi router. You will receive attacks every day. You better use something like cloudflare tunnels to access your self hosted apps externally

Collapse
 
markhelmsglitch profile image
Mark

You're not wrong.

Collapse
 
starbornprime profile image
Sean

this is actually really useful. thanks!