Self hosting with Pi
Tags: webdev, tutorial, nginx, raspberrypi
Published: 2021-05-18 20:09:33

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.

<p>&nbsp;</p>

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!

<p>&nbsp;</p><p>&nbsp;</p>

**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.

<p>&nbsp;</p>
<p>&nbsp;</p>

### 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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/do27v35uf4lhp2k0zvok.png)
 
<p>&nbsp;</p>
Once you successfully boot into Linux, its time to get your PI connected to the internet.

<p>&nbsp;</p>
<p>&nbsp;</p>
### 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
```

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
```

**Then Edit the Netplan configuration file with the wifi interface details**

```
sudo nano /etc/netplan/50-cloud-init.yaml
```

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"
```

Generate the configuration using this command:

```
sudo netplan generate
```

And now to apply it with:

```
sudo netplan apply
```

You should have network connected. 

If not, restarting Linux should do the trick.

<p>&nbsp;</p>
<p>&nbsp;</p>
### 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
```

<p>&nbsp;</p>
<p>&nbsp;</p>
### 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 
```
<p>&nbsp;</p>
<p>&nbsp;</p>

### 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](https://www.netspotapp.com/how-to-log-into-router.html)

<p>&nbsp;</p>
<p>&nbsp;</p>

### 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
```

 Tests if the current Nginx configuration is viable

```
nginx -T 
```

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;  
    }
}
```

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/*;
}
```

<p>&nbsp;</p>
<p>&nbsp;</p>

### 7. Registering your site through google domains

Log into/ register [domains.google.com](http://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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/iz6v1pyua0lxunq0zcus.png)
 

<p>&nbsp;</p>
<p>&nbsp;</p>
### 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

```

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](http://yourdomain.com) & [www.yourdomain.com](http://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
```

<p>&nbsp;</p>
<p>&nbsp;</p>
### 9. Installing Certbot for SSL

Follow the instructions that Certbot provides on there site

[https://certbot.eff.org/instructions](https://certbot.eff.org/instructions)

<p>&nbsp;</p>
<p>&nbsp;</p>
### 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
<p>&nbsp;</p><p>&nbsp;</p>

## CONGRATULATIONS!!!
<p>&nbsp;</p>

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.