Raspberry Pi Webserver
In this Instructable you will learn how the world wide web works by creating your own web server. We will use a Raspberry Pi as the host computer and will run Apache on it. In the end, your Pi will be able to host html websites that can be accessed through a domain and changed from any PC in the same network through SSH.
Supplies
- Raspberry Pi (SD-card, monitore, keyboard, mouse and power)
- Lan cable
- Internet connection
Intro to the Internet:
The internet is basically a bunch of computers connected with wires. In our case some of these computers represent personal computers and some represent web servers that host websites. When you request a website, a bunch of routers in between your PC and the web servers redirect and forward your request to the correct server. To find the correct server, the routers use IP addresses.
Now, you don't serf the net using IP addresses, you use domains, something like "instructables.com". To have that human friendly experience, your requested URL gets actually looked up in a DNS (Domain Naming System) to find out, what the IP address of the web server is.
This will become clearer in the following, when we install a server ware on our Pi, connect it to the local network, analyzing IPs and add a domain to our web server.
Setting Up Raspberry Pi
We have a Raspberry Pi 2, but that doesn't matter. First step in the set up process is: we have to push an image(it's operating system) to our Pi, because at the moment it's only a piece of hardware. For that you need a computer with a SD-card reader. Go to the Official raspberry Pi site and download the Raspberry Pi OS. We used the Raspberry Pi OS with desktop version since it's faster to download.
Now you have the image but still need a program to get that image installed on your SD-card. We use balenaEtcher, but any other software will probably work. And you need a program to format your SD-card.
After you have done that, we need to format our SD-card. Open the installed SD Card Formatter and select your card and format it(All data gets lost!). Now open Etcher, select the downloaded image, the card and flash.
After you connected all hardware with your Pi, like the monitore, keyboard, mouse and Lan connection. You can put your SD-card into the Pi and go! After a long boot sequence you should be welcomed on your desktop.
Here is a good guide if this didn't help you.
Installation of Apache
Apache is the crucial software for a webserver, since it provides the content you will hopefully see in the end.
Installing Apache is easy. Open command terminal or `CLRL+ALT+T` on the Raspbian desktop (If you will ever find yourself trapped and can get out of the current output press `Q` or "Escape" + ":wq") and type `sudo apt update`. This is necessary to have latest packages installed, so hopefully nothing goes wrong. However if you have freshly installed Raspberry Pi OS, skip it!
You may have to accept some question in between, just do `y + ENTER`.
Now we will install apache2 package:
sudo apt-get install apache2 -y
Getting a status from apache works as following:
service apache2 status
It should show, that the Apache HTTP server has been started.
You can access the web page in your browser on the URL `http://localhost`. This shows a standard Apache page.
Now, we need the local IP-address of your Pi. For that type the following into the terminal:
hostname -I
The address is made up of four numbers divided by a '.'. With that, you can access the site on every other device in your network, every device that's plugged into the same router or locked in the same WiFi, by going on `http://192.168.32.10` (change the IP address to what your PI showed)
If you run into the problem that the web server stop working after restart or so, try:
sudo service apache2 restart
Changing Web Page
You probably want to change what it shows, right ?! But because the file is at root, you can't change it by navigating to `/var/www/html/`. We need the `sudo` command, to get permission of the root user.
First navigate to the folder using
cd /var/www/html
To edit the index.html file laying there, we will use mousepad, a source text editor already that comes with the Pi OS:
sudo mousepad index.html
Save your changes, and see in the refreshed browser what you did, good job!
Using SSH
Now, you probably don't want to lock into your Pi every time to make a change on the web page. The SSH (Secure Shell) server software enables you to connect to your server from another computer and make the changes over the terminal from there. You will be able to write in the terminal from your Raspberry Pi through something like a tunnel from another computer. As a result your Pi doesn't need the mouse, keyboard and screen anymore.
You should change your password for the Pi before enabling SSH to make it impossible for others to hack into your Pi(But don't forget it yourself). Do that with:
passwd
Open the raspi-config terminal by typing:
sudo raspi-config
Enter `Interface Options` and navigate to `SSH` and enable it. Last, we have to `sudo reboot` the Pi again.
Now, use your second computer for the SSH. In my case, this computer runs on Windows, so I open PowerShell and type
ssh myPiUsername@PiIPAddress
When using mac or Linux, just open the terminal and type in the same command.
You can see what username you have in the raspberry terminal at the beginning of every command and the IP address can be seen by `hostname -I` or a more detailed status by `ifconfig`.
After that, you will have to confirm the SSH connection attempt by typing `yes + ENTER`. Than you will be asked to confirm with your password.
When you're successful, you should see the same command-line beginning on your Windows as in your Pi Terminal. When ever you want to exit the ssh connection, type `exit`.
To shutdown your Pi via the ssh connection, type:
sudo shutdown now
Update Webpage Through SSH
Now, how can you use the SSH connection to update the content on your web server from a remote computer in the same network?
Before we do that, create an folder for transfer, by typing:
mkdir transfer
This will create a folder called transfer using the relative path in our `/home/user/transfer` directory.
First, we might want to get the file we want to show on our web server from our PC onto our Raspberry Pi. You can alternatively do that by using a USB-stick or so. Since we already have SSH enabled on our Pi, we can type the following into PowerShell or the terminal when working with Mac or Linux. But don't have a ssh tunnel activated! Use `exit` to end connection. Than:
scp [source files] [user]@host]:[path]
For example.
scp index.html gustav@192.168.178.200:transfer/
When given a relative path, pi will save in `/home/user/transfer`. Absolute paths can be defined like this: `[user]@[host]:/home/`.
Now we want to delete the old index.html, still in `/var/www/html`. To get to the folder hosting your website, go to:
cd /var/www/html
You can list, what's in there:
ls -al
To remove the index.html file use:
sudo rm index.html
You can see the differences by typing the `ls -al` again.
To copy the web page from our transfer file to the directory of the web server in `/var/www/html/` use:
sudo cp /home/user/transfer/index.html /var/www/html/.
You have to change the `user` to your Pi account name!
Now, open your web page through the IP-address and you will see your updates. If you can't connect, you may try `hostname -I`, to look if the IP address thy you're using is still active.
Using a Internal Static IP-address
Not necessary required -> First, we need to open the Raspberry Pi Software Configuration Tool, because we might want to change the host name if your Pi is not the only one in the network. For that type the following into the terminal.
sudo raspi-config
This should show you a interface. Select System Options and press Enter. Now navigate to Hostname and change it to a cool name. We called it 'server'. After that go to the start screen with 'ESC' and finish(you have to restart after that). Your Raspberry Pi is now shown as the name you have given him in your network.
Be aware that you have to speak to your Raspberry Pi in the terminal when needed with the given name instead of the standard raspberrypi.
Nevertheless, we need a static IP-address, because as you can think, moving and changing your address in real life makes it hard for corporations to send you letters about what you own them. And the Raspberry Pi does that every 24 hours or so. More exactly, the DHCP of your network automatically assigns those IP addresses to devices inside the network. These IP address can be found in a certain range for example 192.168.1.X and for DHCP, X <= 20 to X=> 90 are reserved. So first, we should find out that range, so we don't choose a static IP-address in that range.
If you don't know that range, try to choose one IP-address far from the known IP-addresses in your network. You can do that with such an advanced IP scanner, to find unused IP-addresses in your network. We ended up using something like 192.168.133.200. Another possibility would we using locking into your router, post forward has a guide specifically for every router, we will follow that one later on, when opening our network for external server requests.
If you can, use a DHCP reservation from your router for the PI to get a static internal IP. For that you should have to lock into your router, and under network, set to give the PI a static IP. Here is a helpful guide on DHCP reservations. If you can't do that use the following.
To define the static internal IP address over the PI, we first open the configuration panel:
sudo nano /etc/dhcpcd.conf
This will open an interface. Navigate down with you arrow keys till you reach the following, which is still commented, so remove # infront of:
interface eth0 static ip_address=192.168.133.200/24 static routers=192.168.133.1 static domain_name_servers=192.168.133.1
If you can't uncomment them, just add those lines.
Nevertheless, you should replace the IP-addresses with the ones of your network. The static one with something out of the DHCP range and the routers and DNS address should be the same as the IP from your router in your network.
Before we reboot again. Save the changes with STR + O and ENTER, than close the interface with 'STR + X'.
sudo reboot
After reboot, you might have to switch to you Raspberry Pi instead of using ssh. Or try to connect again with the following, but enter your newly chosen static IP address:
ssh myPiUsername@PiIPAddress
Now you can access the web server, from the same IP-address every time!
For a full in depth guide we recommend this site.
Going Global
Now we have a static internal IP address, that can be used to access the web server from within the network. But we still need something like an external IP-address so our web server can be accessed from around the globe or from the internet. So, we need to somehow expose the PI's IP to the external world.
Here is an overview of what we're going to do next:
- Determine your external IP
- Port forwarding
- Adding a domain
Typing `ipconfig` on your Windows PC into the command prompt, will show you your internal IP-address. Or `ifconfig` on Linux and Mac. Getting your external IP-address works a bit different. The external IP-address is the identification you use when surfing on the internet, so every server knows where to send the files of a website when you request an URL. Websites like ifconfig.me can expose the external IP you use when connecting with them. And just like your internal IP address they change through time, normally every 24 hours or on every restart of your device. Because the number of IPv4 addresses is limited and as a result will be resigned when not used. This is done by your Internet Service Provider (ISP) and they call the IP address they give you a dynamic IP. More specifically, they give it your router, because every device in the same network as you will have the same dynamic IP address. 87.187.194.64
But when people want to find our web page they would have to look up our external IP address every so now and then, so they can send a request to our server. We obviously want to solve that issue, which we will do later on.
First, we have to look into what an URL or web-domain is, so there won't be any confusions. Basically, domains are human friendly IP addresses, because you can use the internet with only IP-addresses. But this wouldn't be enjoyable, because you would have to remeber 4 multiple digit numbers(= 4 bytes, each number can be as big as 256) for every server you want to visit. For computers is just a set of instructions. They will tell the routers, who are basically the cross sections of the internet, which way to send you.
Domains are just something for humans, like a phone book. URLs have to be looked up in the Domain Name System (DNS) protocol to find the related IP.
One last note, because we are running out of IP addresses, IPv4 was expanded with IPv6, which basically has longer addresses. You can look up the addresses of websites you know in your command window with:
nslookup instructables.com
PORT Forwarding
Port forwarding means opening a port on your router to allow connections from outside through your firewall into your home network. Here a connection to our Pi. To open a port we have to configure the router. Since there are many different routers out there, [postforward](https://portforward.com/router.htm] gathers all different kinds of routers and shows you a specific guide for how to post-forwarding. Choose by your router manufacturer, select the right model and follow the guide to find where you can select port-forwarding for your PI. Be aware that you might already have done some of the first steps and won't need to do the last steps, since we only need to open a port for our PI.
To find out more about your router, you can search for its IP in your network. To find out what IP your router has:
In Windows open the command prompt and type ipconfig and look for IPv4 address at the Default Gateway. In Linux or Mac its ifconfig. Or you can scan your whole network with the advanced IP scanner again. (A more detailed guide)
Now just type in the IP-address of your router into the search-bar of your browser. And you will probably get a website, which enables you to change settings.
Open the firewall of your router for your Pi server and open a port for it. We chosed port 443.
When functioning you should be able to access the website with the external IP address. Before you could only reach your website with the internal IP and only from inside your network. If the external IP address of your router has changed or you forgot, just look it up here.
Make sure your ISP isn't behind a CGNAT or blocks incoming traffic on certain ports (port 80,443,25 are often blocked).
Still know the 'nslookup website-url' command. Yeah, it probably showed you multiple IP-addresses for one website. Why that, our's only got one?
This are actually multiple web-servers listening to the same domain. One reason is, to split incoming requests, balancing the server load. Second reason is for redundancy, to secure access to the web page if a server crashes. Lastly, situating multiple servers around the world cuts respond time. The other way around, one server, with one IP-address can also run multiple domains. But we will stay simple one domain to the one IP address of our Pi.
Nevertheless, if we wan't to access our web page through a domain, we need to own one in the first place. If you don't have one, there are many providers for that, choose one you prefer and purchase a domain, but be aware that you don't need any hosting services, only the domain.
Now, just add your IP address to your domain. You have to change the value of the A-record and the AAAA-record to your IP-address. So that in the Domain Name System your domain will be connected to the external IP-address of your PI. Preferable also the IPv4 address.
If you need a static external IP address for your Pi server and consequently for your network, check out the following tips:
- Ask your ISP, to change your external IP to a static one.
- Use services like cloudfare and cloudfare-ddns, which redirect traffic from static IPs to your dynamic IP address. For that get a domain on cloudfare and add it ti cloudfare-ddns. Alternatively you can use free services such as NO-IP to do that job.
Advancements
- create a QR-code for your website, especially when having no domain. It makes it much more easier to share it with friends.
- Take regular backups from your Raspberry Pi server. SD cards easily stop functioning.
- Use nginx-proxy-manager, its easier and more secure.