How you can host websites from home
Tags: apache, server, ubuntu, website
Published: 2020-06-09 07:06:05

Have an old PC or laptop that you are not using anymore? Well, guess what? You can turn it into a web server and host your website from your home network to the whole world! If you happen to have a Raspberry Pi, that’s even better because Pi is silent and very low on power consumption. 
However, any computer that can run Ubuntu or similar OS will do just fine! 

We will talk about network setup, firewall, Apache, virtual hosts, dynamic IP problem and more. Go make yourself a cup of coffee and dive into building your own web server at home!

___

Requirements:
* PC/Laptop/Raspberry Pi with [Ubuntu](https://ubuntu.com/download)/[Ubuntu Server](https://ubuntu.com/download/server) OS installed
* Username and password for accessing router settings


We’ll talk about:
* [Port forwarding](#portFrowarding)
* [Initial server and firewall configuration](#serverConf)
* [Installing Apache web server on Ubuntu](#installApache)
* [Setting up Apache virtual hosts](#virtualHosts)
* [Useful commands](#commands)
* [Dynamic IP problem](#dyndns)
* [Conclusion](#conclusion)

For setting up web server I will use Raspberry Pi 3 with Ubuntu 18.04 LTS installed. Always look for LTS (Long Term Support) version of Ubuntu when downloading it from the official website. If you are confident with terminal, you can also use [Ubuntu Server](https://ubuntu.com/download/server). At the time of writing this blog, the latest Ubuntu LTS version is 20.04 and is supported until April 2025.


### Port forwarding <a name="portFrowarding"></a>
Once you have your Ubuntu up and running, the first thing I recommend doing is to configure port forwarding on your home network. We are doing this to enable access to our web server over the internet. You can do this using any computer that is connected to your home network. 

To access your router settings, you need default gateway IP address. To get it use Command Prompt/Terminal and enter one of three commands, depending on which OS you are currently using. Default gateway IP address is usually 192.168.1.1 or similar. 

```    
    ipconfig | findstr /i "Gateway"       // Windows - Command Prompt
    ip r | grep default                   // Ubuntu - Terminal
    route get default | grep gateway      // Mac OS
```
Once you find your default gateway IP address, enter it in your web browser. You will need to enter the username and password to log in and get access to router settings. Those credentials could often be found at the bottom of a router, usually on a small sticker. If not, you can look online to find out the default credentials for your router model. 

When you successfully log in, look for “Port forwarding” or “Virtual Servers Setup”. Different routers can name the same settings differently. You need to add two new entries to allow traffic through ports 22 for SSH and 80 for web server. 

To do that correctly, you need the local IP address of the computer which will be used as a web server. In my case it’s Raspberry Pi which is on Ubuntu so to get Raspberry Pi local IP address all I have to do is open Terminal and enter this command:

```
    hostname -I
    // 192.168.1.22
```
Raspberry Pi local IP address is similar but for sure different from default gateway IP address. We need to point incoming requests to our local server address and we’ll do that through ports 22 and 80, that’s why we need our local server IP address. 

So, in your router settings, you need to add those two ports to allow traffic through them to your local server IP address. When adding port 22 you can name it “SSH”, under “Server IP Address” enter your local server IP (in my case it’s 192.168.1.22) and under “External/Internal Port Start/End” enter “22”. Use TCP protocol. Do the same for port 80 and name it “Apache”. 

Ok, now you have these ports configured on the router side. Go to [canyouseeme.org](https://canyouseeme.org/) and check if ports 22 and 80 are opened. There are two fields, “Your IP” which shows you your public IP address and “Port to check”. Simply enter port number 22 or 80 and click “Check Port”. 

Don’t worry if you get an “Error: I could not see your service on your_ip on your_port”, that’s perfectly fine. That’s because the firewall on your server is doing a good job blocking all disallowed connections. We will get to that.

### Initial server and firewall configuration <a name="serverConf"></a>
On a freshly installed Ubuntu, it’s a good idea to do some basic server configuration so the server is ready for future use. To start configuring, open Terminal on your server (in my case Raspberry Pi) and follow along. 

First of all, we'll create a new user which we’ll use to log in into the server over SSH, both inside and outside of our home network (local and external). Also, we will set a new user as “superuser” which means it will have root privileges. 

This allows our new user to run commands with administrative privileges by putting the word “sudo” before each command. When creating a new user you will have to enter a password and some basic user info. 

```
    sudo adduser john                  // create new user john
    sudo usermod -aG sudo john         // add user john to sudo group
```
Our new Ubuntu user should now be ready, but before we can log in over SSH, we need to configure a firewall. We need to allow port 22 through the firewall so we can log in with our new user over SSH, both locally and externally. 

```
    sudo ufw status numbered          // check current firewall status
    sudo ufw allow OpenSSH            // allow port 22 through firewall
    sudo ufw enable                   // enable firewall
```
By enabling firewall and allowing port 22 through, now it’s possible to connect to our server using SSH. You should be able to connect to the server from any computer connected to your local network, and also if you have done port forwarding right you should be able to connect from anywhere in the world. 

To connect to your server simply use Command Prompt or Terminal and enter the command:

```
    ssh john@192.168.1.22             // local connection - use your local server IP
    ssh john@xxx.xxx.xxx.xxx          // external connection - use your public IP
```
If you want to connect externally, outside your local network, you can find your public IP at [canyouseeme.org](https://canyouseeme.org/) and also if you now check if port 22 is opened, you should get “Success: I can see your service on your_ip on port 22”. That means port forwarding and initial server setup are properly done. Good job!

### Install Apache web server on Ubuntu <a name="installApache"></a>
Apache web server is one of the most popular web servers and it’s fairly simple to install.  

```
    sudo apt-get update               // update available software list
    sudo apt install apache2          // install apache2 package
```
Apache is now installed and to make it work it’s necessary to modify firewall settings to allow external access to Apache web server. 

Earlier we opened port 22 for connecting over SSH, now we need to open port 80 for Apache. If you are planning to install an SSL certificate on your website I recommend using the “Apache Full” profile which opens both 80 and 443. For non-SSL website “Apache” profile which opens only port 80 will do just fine. 

```
    sudo ufw app list                 // list ufw application profiles
    // Available applications:
    //   Apache
    //   Apache Full
    //   Apache Secure
    //   OpenSSH

    sudo ufw allow 'Apache'           // opens port 80
    sudo ufw allow 'Apache Full'      // opens port 80 and 443
    sudo ufw allow 'Apache Secure'    // opens port 443 
```
If you check your current firewall status, you should get a similar output. A firewall is now allowing traffic through port 80 if you used the “Apache" profile, and also through port 443 if you used the “Apache Full” profile.

```
    sudo ufw status                   // current firewall status
    // Status: active

    // To                         Action      From
    // --                         ------      ----
    // Apache Full                ALLOW       Anywhere
    // OpenSSH                    ALLOW       Anywhere
    // Apache Full (v6)           ALLOW       Anywhere (v6)
    // OpenSSH (v6)               ALLOW       Anywhere (v6)
```
Go on [canyouseeme.org](https://canyouseeme.org/) and check if port 80 is opened. If you get “Success: I can see your service on your_ip on port 80” that means your server is accessible from the internet. Awesome!

### Setting up Apache virtual hosts <a name="virtualHosts"></a>
Before configuring Apache to serve your own website, if you check Apache status you should get “active (running)”. To check if your website works locally enter local IP server address in your internet browser (in my case that’s 192.168.1.22).

For checking if your website is available on the internet I suggest using your smartphone. Turn off your Wi-Fi and use the mobile internet (3G/4G). Open your internet browser and enter the public IP address of your home network. If you get to default Apache landing page you can be sure your server is up and running!

```
    sudo systemctl status apache2   // check apache status
    hostname -I                  // get local server IP address like 192.168.1.22
    curl -4 icanhazip.com        // get public IP address of your home network
```
Apache by default serves documents from the */var/www/html* directory. We’ll leave this directory as is and create our new directory which we’ll use to serve our website from. 

```
    sudo mkdir /var/www/mywebsite
    sudo nano /var/www/mywebsite/index.html
```
Inside “mywebsite” directory, we’ll create an “index.html” file and paste some basic HTML markup, save and close the file.

```html
    <html>
        <head>
            <title>Hello World!</title>
        </head>
        <body>
            <h1>My website is live!</h1>
        </body>
    </html>
```
In order for Apache to serve this website, it’s necessary to create a new virtual host (*.conf*) file. The default configuration file is located at */etc/apache2/sites-available/000-default.conf* and we’ll also leave this file as is and create our new *mywebsite.conf* file.

```
    sudo nano /etc/apache2/sites-available/mywebsite.conf
```
Inside *mywebsite.conf* file paste following configuration which is similar to the default one, but updated with your ServerAdmin, ServerName and DocumentRoot.

```
    <VirtualHost *:80>
        ServerAdmin your@email.com             // your email
        ServerName xxx.xxx.xxx.xxx             // your public IP address
        DocumentRoot /var/www/mywebsite        // document root of your website
        ErrorLog ${APACHE_LOG_DIR}/error.log
        CustomLog ${APACHE_LOG_DIR}/access.log combined
    </VirtualHost>
```
At this point, we need to enable created website using *a2ensite* command.

```
    sudo a2ensite mywebsite.conf         // enable mywebsite
```
Don’t forget to disable Apache default website using *a2dissite*.
```
    sudo a2dissite 000-default.conf      // disable default Apache website
```
Run test for configuration errors. You should get a “Syntax OK” message.

```
    sudo apache2ctl configtest
    // Syntax OK
```

Finally, restart the Apache server for the changes to take effect.
```
    sudo systemctl restart apache2
```

On your smartphone, open your web browser and type in your public IP address and hit enter. If you see “My website is live!” text, you have successfully configured your Apache web server, congratulations!

### Useful commands <a name="commands"></a>
Here are some commands that you might find useful while configuring your server.

```
    // UFW Firewall commands
    sudo ufw allow OpenSSH
    sudo ufw allow Apache
    sudo ufw status numbered
    sudo ufw delete X

    // SSH server commands
    sudo systemctl status ssh
    sudo systemctl stop ssh
    sudo systemctl start ssh
    sudo systemctl disable ssh
    sudo systemctl enable ssh

    // Apache server commands
    sudo systemctl start apache2
    sudo systemctl stop apache2
    sudo systemctl restart apache2
    sudo systemctl reload apache2
    sudo systemctl disable apache2
    sudo systemctl enable apache2
```

### Dynamic IP problem <a name="dyndns"></a>
In most cases for home networks, the public IP address changes every 24 hours. Also if your router gets disconnected from the internet you will automatically get a new IP address when reconnected.

That’s a problem because every time your IP changes, to access your website you need to use the current public IP address of your network and also you need to update Apache config file. If you have a static public IP address then you are fine. Usually, ISP charges extra for static IPs. 

There is a solution for this without having to pay for static IP. You can use free dynamic DNS service like [no-ip.com](http://no-ip.com/) where you can choose a free domain name and point it to your public IP address. You also need to add that domain name and your no-ip.com account credentials in your dynamic DNS router settings.

After you do that, your router and dynamic DNS service will work together and update your public IP address as it changes. This way, to access your website, you can always use the same domain name chosen on your dynamic DNS service as it always points to your current, up to date public IP address.

### Conclusion <a name="conclusion"></a>
You should now have a basic understanding of how the web server works. Setting up your own web server at home is a good way to train your server administration skills. Having knowledge of setting up a server at home, you shouldn’t have problems administrating one on AWS, DigitalOcean or similar services. 

Where to go from here? Well, you could buy your own domain name like *mydomain.com* and point it to your server IP address. After that, you can create any number of subdomains like *subdomain.mydomain.com* and host multiple different sites, all from one Apache instance. Also, it’s a good idea to install an SSL certificate on your website. But more on that later, I need to leave some content for my next blog. 😉