DEV Community

Yongkang Cheng
Yongkang Cheng

Posted on • Edited on

How to Build Your Own Website with a Raspberry Pi: An Entertaining Guide

Table of Contents

  1. Introduction
  2. Preparation
  3. Setting Up the Raspberry Pi
  4. Installing the Nginx Web Server
  5. Configuring the Firewall (UFW)
  6. Setting Up Dynamic DNS (DDNS)
  7. Configuring Port Forwarding on Your Router
  8. Deploying Your Static Website
  9. Installing Certbot and Setting Up HTTPS Certificates
  10. Testing and Troubleshooting
  11. Conclusion

1. Introduction

So, you've decided to host your own website from your basement using a Raspberry Pi? Excellent choice! Not only will you save money on hosting fees, but you'll also become the tech wizard among your friends. In this guide, we'll walk you through every step—from setting up your Raspberry Pi to having a shiny, secure website that says "Hello, I'm Ken/Jacky/Allie..." to the world.

Image of a Raspberry Pi waving hello

Note: While I personally love using the React framework for building websites, we'll keep things simple here with a basic static HTML page. Trust me, your Pi will thank you.


2. Preparation

What You'll Need:

  • A Raspberry Pi (preferably a Raspberry Pi 4 for extra oomph)
  • A microSD card (at least 16GB)
  • Network connection (Ethernet or Wi-Fi)
  • A computer (to prepare the SD card and remotely control the Pi)
  • A domain name (so people can find your masterpiece)

Software You'll Need:

  • Raspberry Pi Imager (the official tool for burning the OS)
  • SSH client (like PuTTY for Windows or Terminal for macOS/Linux)

3. Setting Up the Raspberry Pi

3.1 Installing the Operating System

Step 1: Download Raspberry Pi Imager

Downloading Raspberry Pi Imager

Step 2: Install Raspberry Pi Imager

  • Run the installer and follow the on-screen instructions.

Step 3: Prepare the microSD Card

  • Insert the microSD card into your computer's card reader.

Step 4: Burn the OS to the SD Card

  • Open Raspberry Pi Imager.
  • Click on "Choose OS" and select "Raspberry Pi OS Lite (32-bit)" under "Raspberry Pi OS (other)". This version skips the desktop environment.

Selecting Raspberry Pi OS Lite

  • Click on "Choose Storage" and select your microSD card.

Optional but Highly Recommended: Enable SSH and Set Wi-Fi

  • Click on the Custom Settings to access advanced settings.
  • Set a username and password (make sure to remember them).
  • If you're using Wi-Fi, enter your SSID and password.
  • Enable SSH by checking the box "Enable SSH".

General settings

Enabling SSH

Step 5: Write the OS

  • Click on "Write" and confirm that you want to erase the card.
  • Wait patiently as the OS is written to the card.

Writing progress

Step 6: Safely Eject the SD Card

  • Once the process is complete, eject the card from your computer.

3.2 Updating and Upgrading the System

Step 1: Power Up Your Pi

  • Insert the microSD card into your Raspberry Pi.
  • Connect the Pi to your router via Ethernet for a stable connection.
  • Plug in the power supply.

Step 2: Find Your Pi's IP Address

  • Access your router's admin page (usually at 192.168.x.1).
  • Look for connected devices and find raspberrypi. Note its IP address (e.g., 192.168.68.130).

Router admin page

Finding Your Router's IP Address

If you're unsure of your router's IP address, you can find it using the command line:

  • Windows:
  ipconfig
Enter fullscreen mode Exit fullscreen mode

Look for the "Default Gateway" under your network adapter.

  • macOS/Linux:
  route -n
Enter fullscreen mode Exit fullscreen mode

or

  netstat -nr
Enter fullscreen mode Exit fullscreen mode

Find the default gateway address.

Step 3: Connect via SSH

  • Open your SSH client.
  • For Windows (PuTTY or Terminal):
    • Host Name: your_username@your_pi_ip_address (e.g., ken@192.168.68.130)
    • Port: 22
  • For macOS/Linux (Terminal):
  ssh your_username@your_pi_ip_address
Enter fullscreen mode Exit fullscreen mode
  • Enter your password when prompted (the password won't be visible as you type).

Example using SSH on Windows Terminal:

Connecting via SSH

Step 4: Update the System

  • Run the following command to update and upgrade packages:
  sudo apt update && sudo apt upgrade -y
Enter fullscreen mode Exit fullscreen mode
  • This updates the package lists and upgrades installed packages.

Updating packages

Optional but Recommended: Set Up SSH Keys

Setting up SSH keys allows you to connect to your Pi without entering a password each time.

On your PC terminal:

ssh-keygen -t rsa
Enter fullscreen mode Exit fullscreen mode
  • Press Enter three times to accept the default settings.

Generating SSH keys

  • Locate the .ssh folder in your home directory (e.g., C:\Users\YourUsername\.ssh) and find the id_rsa.pub file.

Finding id_rsa.pub

  • Open id_rsa.pub with a text editor and copy its content.
  • On your Raspberry Pi terminal, create the .ssh directory and the authorized_keys file:
  mkdir ~/.ssh
  nano ~/.ssh/authorized_keys
Enter fullscreen mode Exit fullscreen mode
  • Paste the copied public key into the file.
  • Press Ctrl + X, then Y, then Enter to save and exit.

Editing authorized_keys

Now, you can connect to your Raspberry Pi via SSH without entering a password.


4. Installing the Nginx Web Server

Let's install Nginx so your Pi can serve web pages.

Step 1: Install Nginx

sudo apt install nginx -y
Enter fullscreen mode Exit fullscreen mode

Step 2: Start and Enable Nginx

  • Start Nginx:
  sudo systemctl start nginx
Enter fullscreen mode Exit fullscreen mode
  • Enable Nginx to start on boot:
  sudo systemctl enable nginx
Enter fullscreen mode Exit fullscreen mode

Step 3: Test Nginx

  • Open a web browser on your computer and enter your Pi's IP address.
  • You should see the default "Welcome to Nginx!" page.

Nginx default page


5. Configuring the Firewall (UFW)

Protect your Raspberry Pi from unauthorized access.

Step 1: Install UFW

sudo apt install ufw -y
Enter fullscreen mode Exit fullscreen mode

Step 2: Allow SSH and Web Traffic

  • Allow SSH:
  sudo ufw allow ssh
Enter fullscreen mode Exit fullscreen mode
  • Allow HTTP and HTTPS traffic:
  sudo ufw allow 'Nginx Full'
Enter fullscreen mode Exit fullscreen mode

Step 3: Set Default Rules and Enable the Firewall

  • Deny all incoming traffic (except allowed):
  sudo ufw default deny incoming
Enter fullscreen mode Exit fullscreen mode
  • Enable the firewall:
  sudo ufw enable
Enter fullscreen mode Exit fullscreen mode
  • Type y when prompted.

Step 4: Check the Status

sudo ufw status verbose
Enter fullscreen mode Exit fullscreen mode
  • You should see rules for OpenSSH and Nginx.

UFW status


6. Setting Up Dynamic DNS (DDNS)

Your ISP might change your public IP address periodically. Setting up DDNS ensures your domain always points to your Pi.

⚠️ Attention: This is the most challenging part of the guide. You may encounter various issues—perhaps difficulties using the Cloudflare API, trouble retrieving your public IP, firewall blocks, or even missed steps like configuring the optical modem. Please approach this with patience and persistence. If you run into any problems, try searching online or asking ChatGPT for assistance. Good luck!

Image of How the PC Finds the Raspberry Pi

Imagine you want to reach your Raspberry Pi at home from anywhere. Here’s how it works:

  1. Your PC asks the internet, “Where’s chengyongkang.me?”
  2. Cloudflare (your domain manager) and the DNS Server respond, saying, “Go to IP 123.123.123.1”—which is your Router’s public IP.
  3. Your Router gets the request, recognizes you want the Raspberry Pi, and forwards it through a “secret gate” to the Pi’s private IP inside your network.

And boom! You’re connected. Cloudflare keeps your domain linked to your router, even if the IP changes. It’s like a guided tour, directing your PC all the way to your Raspberry Pi!

6.1 Registering a Cloudflare Account and Adding Your Domain

Step 1: Sign Up for Cloudflare

Step 2: Add Your Domain

  • In the Account Home, click "Add site".
  • Enter your domain name (e.g., example.com).

Adding a site on Cloudflare

Step 3: Select a Plan

  • Choose the Free plan.

Selecting Free plan

Step 4: Update Your Nameservers

  • Cloudflare will provide nameservers (e.g., bob.ns.cloudflare.com and lisa.ns.cloudflare.com).
  • Log in to your domain registrar (where you bought the domain).
  • Replace the existing nameservers with the ones provided by Cloudflare.

Updating nameservers

Step 5: Wait for DNS Propagation

  • This can take up to 24 hours but usually is faster.
  • Use What's My DNS to check the status.

6.2 Obtaining an API Token and Zone ID

An API token allows your Pi to communicate with Cloudflare to update DNS records, and the Zone ID uniquely identifies your domain.

Step 1: Create an API Token

  • In Cloudflare, click on your profile icon and select "My Profile".

Accessing Cloudflare profile

  • Go to the "API Tokens" tab.
  • Click "Create Token".

Step 2: Configure the Token

  • Choose "Create Custom Token".

Creating custom API token

  • Token Name: DDNS Update Token
  • Permissions:
    • Zone - DNS - Edit
    • Zone - Zone - Read
  • Zone Resources: Include -> Specific Zone -> Your domain (e.g., example.com)

Step 3: Create and Copy the Token

  • Click "Continue to summary", then "Create Token".
  • Copy the token and store it securely.

Step 4: Obtain the Zone ID

  • In your Cloudflare Account Home, click on your domain name (e.g., example.com).
  • Scroll down; at the bottom right, you'll find your Zone ID.

Finding Zone ID


6.3 Adding a DNS Record

Click "Add Record", and then configure as below:

  • Type: A
  • Name: @ (for the root domain)
  • IPv4 Address, Proxy Status, and TTL: Enter any value for now; our script will update it later.

Adding DNS record settings


6.4 Writing a Script to Automatically Update Your IP

Let's automate the IP update process.

Step 1: Create a Directory for Your Script

mkdir ~/Documents/DDNS
cd ~/Documents/DDNS
nano update_dns.py
Enter fullscreen mode Exit fullscreen mode

Step 2: Write the Python Script

#!/usr/bin/env python3

import requests
import json
import os

# Cloudflare API credentials
auth_key = "your_api_token_here"   # Replace with your actual API token
record_name = "your_domain.com"    # Replace with your domain
zone_id = "your_zone_id_here"      # Replace with your Zone ID
ip_file = "ip.txt"

headers = {
    "Authorization": f"Bearer {auth_key}",
    "Content-Type": "application/json"
}

def get_record_id():
    url = f"https://api.cloudflare.com/client/v4/zones/{zone_id}/dns_records?name={record_name}"
    response = requests.get(url, headers=headers)
    response_data = response.json()

    if response_data.get("success"):
        return response_data["result"][0]["id"]
    else:
        print("Failed to fetch record ID")
        return None

def get_current_ip():
    response = requests.get("http://ipv4.icanhazip.com")
    return response.text.strip()

def update_dns_record(record_id, ip):
    url = f"https://api.cloudflare.com/client/v4/zones/{zone_id}/dns_records/{record_id}"
    data = {
        "type": "A",
        "name": record_name,
        "content": ip,
        "ttl": 120,
        "proxied": False
    }
    response = requests.put(url, headers=headers, json=data)
    return response.json()

def main():
    current_ip = get_current_ip()
    if os.path.exists(ip_file):
        with open(ip_file, "r") as file:
            last_ip = file.read().strip()
    else:
        last_ip = None

    if last_ip == current_ip:
        print("IP has not changed")
    else:
        print("IP has changed, updating DNS record...")
        record_id = get_record_id()
        if not record_id:
            print("Error: Could not retrieve the DNS record ID.")
            return

        result = update_dns_record(record_id, current_ip)
        if result.get("success"):
            print(f"DNS record updated successfully to IP: {current_ip}")
            with open(ip_file, "w") as file:
                file.write(current_ip)
        else:
            print("Failed to update DNS record")
            print(result)

if __name__ == "__main__":
    main()
Enter fullscreen mode Exit fullscreen mode
  • Replace:
    • auth_key with your API token.
    • record_name with your domain.
    • zone_id with your Zone ID.

Step 3: Save and Exit

  • Press Ctrl + O, then Enter to save.
  • Press Ctrl + X to exit.

Step 4: Make the Script Executable

chmod +x update_dns.py
Enter fullscreen mode Exit fullscreen mode

Step 5: Test the Script

./update_dns.py
Enter fullscreen mode Exit fullscreen mode
  • Check if the DNS record is updated on Cloudflare.

Script output

Step 6: Schedule the Script

If you're in a hurry, you can skip this step for now.

  • Open crontab:
crontab -e
Enter fullscreen mode Exit fullscreen mode
  • If prompted, select nano as the editor.
  • Add the following line at the end:
*/5 * * * * /home/pi/Documents/DDNS/update_dns.py >/dev/null 2>&1
Enter fullscreen mode Exit fullscreen mode
  • This schedules the script to run every 5 minutes.

Step 7: Save and Exit

  • Press Ctrl + O, then Enter to save.
  • Press Ctrl + X to exit.

7. Configuring Port Forwarding on Your Router

Set up port forwarding to allow external access to your Raspberry Pi.

Step 1: Access Your Router's Settings

  • Open a web browser and enter your router's IP address (e.g., 192.168.1.1).
  • Log in with your router's username and password.

Finding Your Router's IP Address

If you're unsure of your router's IP address, you can find it using the command line:

  • Windows:
  ipconfig
Enter fullscreen mode Exit fullscreen mode

Look for the "Default Gateway" under your network adapter.

  • macOS/Linux:
  route -n
Enter fullscreen mode Exit fullscreen mode

or

  netstat -nr
Enter fullscreen mode Exit fullscreen mode

Find the default gateway address.

Step 2: Reserve an IP Address for Your Raspberry Pi

  • Navigate to the "DHCP" or "LAN" settings.
  • Look for "Address Reservation" or "Static IP Assignment".
  • Assign a fixed IP address to your Raspberry Pi.

Reserving IP address

Step 3: Locate Port Forwarding Settings

  • Go to the "Port Forwarding", "NAT", or "Virtual Servers" section.

Port forwarding settings

Step 4: Set Up Port Forwarding Rules

  • Forward the necessary ports to your Raspberry Pi's IP address.
    • HTTP (Port 80)
    • HTTPS (Port 443)
  • Configure:
    • External Port: 80 and 443
    • Internal Port: 80 and 443
    • Internal IP: Your Raspberry Pi's fixed IP
    • Protocol: TCP

Step 5: Save and Reboot if Necessary

  • Save the changes.
  • Reboot the router if required.

Step 6: Verify Connectivity

  • Ping Your Raspberry Pi's Internal IP:
  ping 192.168.X.X
Enter fullscreen mode Exit fullscreen mode
  • Find Your Public IP Address:
    • Visit https://ipv4.icanhazip.com/.
  • Ping Your Public IP:
  ping your_public_ip_address
Enter fullscreen mode Exit fullscreen mode
  • Ping Your Domain:
  ping your_domain.com
Enter fullscreen mode Exit fullscreen mode
  • Access Your Domain in a Browser:
    • Navigate to http://your_domain.com.
    • You should see the Nginx default page.

Nginx default page

If everything works, congratulations! You've passed the hardest part.


8. Deploying Your Static Website

Let's replace the default Nginx page with your own content.

8.1 Creating a Simple HTML Page

Create a simple webpage that says "Hello, I'm Ken".

Step 1: Create an HTML File

  • Create a new directory:
sudo mkdir /var/www/ken
Enter fullscreen mode Exit fullscreen mode
  • Create the index.html file:
nano /var/www/ken/index.html
Enter fullscreen mode Exit fullscreen mode
  • Paste the following content:
<!DOCTYPE html>
<html>
<head>
    <title>Hello, I'm Ken</title>
</head>
<body>
    <h1>Hello, I'm Ken</h1>
    <p>Welcome to my awesome Raspberry Pi hosted website!</p>
</body>
</html>
Enter fullscreen mode Exit fullscreen mode

Step 2: Save and Exit

  • Press Ctrl + O, then Enter to save.
  • Press Ctrl + X to exit.

8.2 Configuring Nginx to Serve Your Website

Step 1: Create a New Nginx Server Block

  • Create a new configuration file:
sudo nano /etc/nginx/sites-available/ken
Enter fullscreen mode Exit fullscreen mode
  • Paste the following content (replace www.example.com with your domain):
server {
    listen 80;
    server_name www.example.com;

    root /var/www/ken;
    index index.html;

    location / {
        try_files $uri $uri/ =404;
    }
}
Enter fullscreen mode Exit fullscreen mode

Step 2: Enable the Server Block

  • Create a symbolic link to sites-enabled:
sudo ln -s /etc/nginx/sites-available/ken /etc/nginx/sites-enabled/
Enter fullscreen mode Exit fullscreen mode

Step 3: Test Nginx Configuration

  • Run:
sudo nginx -t
Enter fullscreen mode Exit fullscreen mode
  • Ensure there are no errors.

Step 4: Reload Nginx

  • Run:
sudo systemctl reload nginx
Enter fullscreen mode Exit fullscreen mode

Step 5: Test Your Website

  • Navigate to http://www.example.com in your browser.
  • You should see your "Hello, I'm Ken" page.

Image of the webpage showing


9. Installing Certbot and Setting Up HTTPS Certificates

Secure your website with HTTPS.

Step 1: Install Certbot

sudo apt install certbot python3-certbot-nginx -y
Enter fullscreen mode Exit fullscreen mode

Step 2: Obtain and Install the SSL Certificate

sudo certbot --nginx -d www.example.com
Enter fullscreen mode Exit fullscreen mode
  • Follow the prompts:
    • Enter your email address.
    • Agree to the terms of service.
    • Decide whether to share your email.
  • Certbot will obtain and install the certificate automatically.

Step 3: Test HTTPS Access

  • Navigate to https://www.example.com.
  • You should see a secure lock icon in your browser.

Step 4: Auto-Renewal

  • Certbot installs a cron job for automatic renewal.
  • Test the renewal process:
sudo certbot renew --dry-run
Enter fullscreen mode Exit fullscreen mode

10. Testing and Troubleshooting

Common Issues:

  • Can't Access the Website:

    • Ensure your domain points to your IP address.
    • Verify port forwarding settings.
    • Check that UFW allows HTTP and HTTPS traffic.
  • SSL Certificate Issues:

    • Make sure your domain is accessible over HTTP before running Certbot.
    • Double-check Nginx configurations for errors.
  • DDNS Not Updating:

    • Confirm that the API token has the correct permissions.
    • Manually run the update script to check for errors.

Useful Commands:

  • Monitor Nginx errors:
sudo tail -f /var/log/nginx/error.log
Enter fullscreen mode Exit fullscreen mode
  • Check firewall rules:
sudo ufw status verbose
Enter fullscreen mode Exit fullscreen mode

11. Conclusion

Congratulations! You've successfully transformed your Raspberry Pi into a web server hosting your very own website. Not only did you avoid hosting fees, but you've also earned some serious geek cred.

Say goodbye - cowsay

Next Steps:

  • Enhance Your Website: Add more content or explore frameworks like React.
  • Continue Learning: Dive deeper into Linux, Nginx, and web development.
  • Share Your Success: Tell your friends about your new website.

Disclaimer: No Raspberry Pis were harmed in the making of this guide. Remember to keep your Pi cool and well-ventilated.


If you have any questions or run into any issues, feel free to ask. Happy Pi hosting!

Top comments (0)