Setting up a (reasonably) secure home web-server with Raspberry Pi

DISCLAIMER: I am not an expert at Linux, web servers, or security. What follows is merely the process I went through to create what I believe to be a reasonably secure home web server with a Raspberry Pi. This post is the result of reading a fair few different sources online and in books, and is intended as a guide for myself so I can re-trace my steps if I ever need to. Follow this at your own risk. With that out of the way, I hope you find it useful…

Goal

This article is only concerned with setting up a secure Pi with a secure web-server on it – anything after that is up to you – by the end of the article you’ll have your own self-hosted web-server to do with as you please.

My personal goal is to have a Raspberry Pi in my house that, through a custom web-app, acts as a main controller as I experiment with bits and bobs that you could loosely call a ‘smart home’. And to have it accessible from outside the house itself, securely.

Requirements

  • Raspberry Pi, associated hardware and software
  • A USB memory stick or hard-drive (optional)
  • A network cable
  • A fixed IP address from your home ISP
  • A domain name you control
  • Your router’s documentation

Article breakdown

  • Setting up the Raspberry Pi
    • Initial Configuration
      • 1. Changing the Pi password
      • 2. Disabling “Boot to Desktop”
      • 3. Updating your Locale settings
      • 4. Setting your Hostname
      • 5. Setting the Memory Split
      • 6. Ensuring SSH is enabled
      • 7. Committing the changes and rebooting
    • Creating a new user
    • Deleting the default ‘pi’ user
    • Updating the operating system and software
    • Fixing your Pi’s internal IP address
    • Setting up your USB drive
      • A note on security
    • If you don’t want to set up a USB drive
  • Securing your Pi
    • Optional step: SSH Key-Pair Authentication
    • Optional step: Setting up a Firewall
    • Optional step: Setting up Fail2Ban
  • Going headless
  • Installing web-server software
    • Setting up nginx
    • Setting up PHP
    • Securing MySQL
  • Setting up your first website
    • Setting up a local address
    • Creating the directory for your website’s files
    • Configuring nginx to serve the website
      • Configuring nginx to use PHP
      • Testing your PHP configuration
    • Accessing your site via the internet
      • Setting up your domains A-record
      • Setting up your Router
  • Conclusion
  • Bonus Material: SSL/HTTPS and Subdomains

Setting up the Raspberry Pi

Remove the brand new Raspberry Pi from it’s wrapping, and follow the standard NOOBS steps to get Raspbian installed. I’m using Raspbian as I’m more sure of its continued support than with Arch Linux (the other option on NOOBS). Arch would in theory be better as it’s a much smaller distribution and faster booting, but it’s maintained by a smaller group of people so the chances of it being neglected at some point are higher.

With Raspbian on the Pi we’ll tweak it for better performance given it’s intended use as a headless server (i.e., it’ll run without a screen and we’ll do all our admin via an SSH connection from another computer in the building).

Initial Configuration

NOTE: Before turning the Pi on, make sure you do not have a network cable plugged in.

Enter raspi-config; it appears automatically when when you first boot the device or you can get to it at any time from a Bash prompt (by opening a Terminal from the desktop, if you’re in the desktop) and typing:

sudo raspi-config

The Raspi-Config utility changes its UI from time to time so not everything might be where I say, but the options will be there somewhere. Navigate the menu with the arrow keys, select things by pressing the enter key. Do the following:

1. Change the Pi password

We’ll be deleting the default “pi” user account later (for security) but right now, if you were connected to the internet your Pi would be susceptible to someone SSHing into it – because every Pi has the same default password. Better to change it now, before you’re connected, just in case.

2. Disable “Boot to Desktop”

Currently that means entering the “Enable boot to desktop” menu item and then selecting “no”. We won’t be using the desktop (we’re going to run headless), and disabling the boot to desktop option will free up some system resources so the Pi performs better.

3. Update your Locale settings

If you’re in the UK then it’s already set to use UK English in UTF8 – if not, pick the best choice for your location and if you can, a UTF-8 version of your locale. Also set your timezone (for me that’s Europe > London).

4. Set your Hostname

(Advanced > Hostname). Your ‘hostname’ is simply the name of the Pi itself, you can choose anything but don’t use special characters or spaces. So, for example, ‘webserver1′ might be good for you.

5. Set the Memory Split

(Advanced > Memory Split). The Pi’s GPU and CPU both share the same RAM modules (512Mb of it in current Pi models). As we won’t be running a desktop we don’t need the GPU to have much memory, so we can set it to 16 – leaving the rest of the RAM free for the system to use.

6. Ensure SSH is enabled

(Advanced > SSH). SSH is the protocol we will be using to access and control the Pi from another computer. It must be enabled for us to do that.

7. Commit the changes and reboot

Select ‘Finish’ – if it asks, yes you want to reboot. If it doesn’t ask to reboot then force a reboot so the new hostname and other changes take effect; type:

sudo reboot

Once it’s rebooted you’ll be prompted for the username/password. Use ‘pi’ and the password you just set up.

Creating a new user

As mentioned, it’s a good idea to get rid of the default ‘pi’ user just to make it harder for anyone who might try to hack you (and there are automated methods that might find you and try it, especially as the Pi itself becomes more popular and the default account details remain the same for each one).

Going into detail on how Linux controls access rights and permissions for users is beyond the scope of this article, but suffice to say it has a concept of “users” and “groups” – users can belong to any number of groups, and groups are used to control permissions and access to files, directories, etc. It’s through this system that Linux machines are administered.

We want to get a list of groups that the default Pi user belongs to, so that we can create a new user which belongs to all the same groups – and therefor can do everything that the default Pi user can do. Belonging to all the same groups as the ‘pi’ user is not strictly necessary (and can be a bad idea if you’re determined to be as secure as possible), but it can be useful if you want do other stuff with your Pi later. It also keeps this post simpler because being more restrictive would require more knowledge of Linux administration. You can figure that out later if you feel you want to.

In the Bash prompt type:

groups

You will see a list output similar to the one below – yours may be different to mine (this article will become old and out of date) so pay attention to your list and not mine!

pi adm dialout cdrom sudo audio video plugdev games users netdev input

Now we can create a new user. Type the following into the command prompt but remember to use your list of groups (minus the first ‘pi’ item) and replace USERNAME with the username you want to create. Make sure you type it all on one line (if you’re seeing the line wrap here that’s just the WordPress theme being stupid and re-formatting ‘preformatted’ text – which it shouldn’t do).

sudo useradd -m -G adm,dialout,cdrom,sudo,audio,video,plugdev,games,users,netdev,input USERNAME

Next we set a password for the new user:

sudo passwd USERNAME

Complete the prompts as they appear. Now shutdown the Pi:

sudo shutdown -h now

The Pi will turn itself off.

Un-plug the power, plug in the network cable, then plug the power back in.

The Pi will boot up and leave you in a Bash shell asking for a login name: Log-in with your newly created user’s details (i.e., don’t log in as ‘pi’).

Deleting the default ‘pi’ user

Type:

sudo deluser --remove-all-files pi

This will take a little while and spit out a lot of lines of text – eventually it will say ‘Done’. The ‘pi’ user and it’s associated files are now removed from the system.

Updating the operating system and software

With the network cable plugged in you should have a network connection automatically configured and ready to use (if not, you’re going to have to Google how to manually set-up networking on a Pi). To update the system type:

sudo apt-get update

Wait for this to complete; it’s just got a list of all the potential updates and new bits of software you could install. To upgrade all of the currently installed software type:

sudo apt-get upgrade

Wait for that to complete, answer any prompts with ‘y’ + Enter. Your system is now up-to-date.

Fixing your Pi’s internal IP address

This is more for convenience than a necessity; if you don’t do this then chances are good that if you ever reboot the Pi or the Router (or both) then your Pi’s IP address will change and you’ll have problems connecting to it over the network. If we fix the IP address of the Pi on your internal network then you avoid that problem, and every time you reboot the router or Pi it’ll come back on the same IP address and avoid any issues with network addressing.

The best way I’ve found to do this is through the Router itself, rather than the Pi. If you do it on the router you’ll find it easier to manage in future if you add more devices to your network: the settings for all your devices will be in one place and you’re not going to get accidental conflicts as you might if you tried to make the Pi itself demand a specific IP address (Doing this on a Pi would mean there’s nothing stopping you accidentally setting two Pi’s up to try and use the same IP; at which point things will break).

You’ll need to consult your router’s documentation but the steps should essentially be:

  1. Find the MAC address of the Pi
  2. Set the router to always assign the same IP to any device with that MAC address

A MAC address is essentially a unique identifier – any and all devices attached to your network have their own unique MAC address – think of it like a serial number; no other Pi (or other device) shares the same MAC address as yours. To find your Pi’s MAC address type:

ifconfig

A bunch of stuff will appear documenting the various network properties of your Pi. Amongst the output text will be something labeled “HWaddr” – short for Hardware Address, which is what the MAC code really is. Make a note of that code; it will look something like a3:e3:2d:33…

On the same results you will also see your Pi’s current IP address under “inet addr” which will look something like 192.168.0.something – make a note of that too.

The rest is up to you; use your router’s documentation and/or Google to figure out how to set fixed IP addresses for unique devices. Use those two codes.

Setting up your USB drive

This step is optional; you don’t need a USB drive but it’s nice to have. The idea is that the USB drive will hold all of your websites files. The Pi runs off an SD card, and they tend to have small storage capacities and be slow. Best to leave that for the Operating System, and put all of your website files on a USB drive. That should work out more convenient, better performing, and cheaper than trying to get a big enough SD card to do all the work. I use a 32Gb USB flash drive at the moment as that’s physically small, fast, cheap, and doesn’t require an external power source (or powered USB hub). If I was to need to store a lot of data I could just swap to a more traditional USB HDD. Be aware if you want to do that; the Pi can only supply so much power over USB and a USB powered hard-disk isn’t likely to work plugged into the Pi itself; you’d likely need a powered USB hub to supply enough juice to run the drive.

Plug your drive into the Pi, then type:

sudo fdisk -l

You’ll see a list of storage devices attached to the Pi; one is the SD card, the other is the drive you just plugged in.

The SD card will be the one identified as /dev/mmcblk0 and will likely have a number of ‘partitions’ listed under it. We are interested in the other one; for me that is /dev/sda, and it has one partition ‘/dev/sda1′ yours will likely be the same, but check, and use your value in the following commands rather than mine.

We’re going to format the partition on the USB drive so Linux has a clean slate to use – this will erase any data on the card. Remember to use the value you got for your USB drive if it’s different to mine:

sudo mkfs.ext4 /dev/sda1

The USB drive is now blank and in a Linux native filesystem format. Now we need to mount it (i.e., let Linux actually use it). First we create a mount point (a directory name we will access the drive from):

sudo mkdir /websites

and then we actually mount the drive onto that mount point:

sudo mount /dev/sda1 /websites

The drive is now available to the root user… but no one else has permission to access it. We can change that as follows:

sudo chgrp -R users /websites

Now any user belonging to the ‘users’ group can access the drive. But they can’t write to it yet:

sudo chmod -R g+w /websites

Now they can.

The last job is to set up auto-mounting. Right now, if you rebooted the Pi then the /websites directory would be inaccessible because the drive would need to be re-mounted. That’s annoying, so we’ll automate that:

sudo nano /etc/fstab

You’ll see a somewhat complicated looking file. We just need to add a new line to it at the bottom and separate each item on the line with a tab – be sure to press the tab key where you see [tab] instead of writing the phrase [tab]

/dev/sda1 [tab] /websites [tab] ext4 [tab] defaults [tab] 0 [tab] 2

Press Ctrl+X to exit, Y then Enter to save.

Done.

A note on security

As set up above, any user you create and assign to the ‘users’ group will have full read/write access to the USB drive. That’s usually fine, but if someone were to hack the Pi and gain access to any user account they’d then have full access to the USB drive. The reason I say it’s ‘usually fine’ is that for me there’s only ever one user on the system anyway.

You could, if you wanted, secure that a little more by being more specific. You could for example create a new user called ‘webserver’, a new group also called ‘webserver’, assign your webserver user to the webserver group, and then change the permissions as above but using ‘webserver’ instead of ‘users’. Now, to access the drive, they’d have to hack a specific user (‘webserver’) rather than just any user.

If you don’t want to set up a USB drive

Then just create a directory called ‘websites’ at the root of the SD card – that way you can follow all the steps remaining without any issue; the only difference is that your /websites directory will physically be stored on the SD card instead of a USB drive.

To be clear, do the following step only if you don’t want to set up a USB drive and have not completed the previous steps from this section of the article:

sudo mkdir /websites

Securing your Pi

Optional step: SSH Key-Pair Authentication

This isn’t required and isn’t always suitable – it depends on your own circumstances if you want to do this. Using SSH key-pair authentication is more secure than typing a password to authenticate your user (i.e., to log-in to your Pi), but it ties your ability to log-in over SSH to a physical machine; if the machine is stolen, breaks, is re-formatted, or simply not with you when you need it; you’re not going to be able to log into your Pi remotely. You’d have to plug it into a TV to access it, then authenticate a new computer to restore your ability to administer the Pi remotely.

You can see why it’s more secure – you need that one physical computer and it’s associated key to log into the Pi! (though you can authenticate more than one computer at a time if you want).

If you do want to set up SSH Key Pair Authentication and disable SSH Password Authentication, there is a great tutorial by Linode that you can follow: Using SSH Key Pair Authentication. Just replace “your linode” with “your Pi”.

Optional step: Setting up a Firewall

Again, this isn’t strictly needed but it’s another step along the security path, and it’s easy enough to set up. Again, Linode have a great tutorial which you can follow – substituting “your Linode” for “your Pi” as you go. Linode: Creating a firewall.

Optional step: Setting up Fail2Ban

This application helps to prevent hacking attempts by detecting log-in attempts that use a dictionary attack and banning the offending IP address for a short while.

NOTE: If you’re using SSH Key Pairs and have disabled SSH Password Authentication then you may not want to bother with this as no-one can hack their way in via a dictionary attack anyway.

sudo apt-get install fail2ban

Wait for this to complete; it should be fine running the default set up so you can stop there, or learn more about customising fail2ban.

Going headless

You could do all of the steps in this article directly on the Pi attached to a TV, but at some point you’ll need to disconnect the screen and access the Pi from another computer, so we’re going to do this now. Make sure you know your Pi’s IP address (you should have fixed that earlier on).

On a different computer, connected to the same home network, open a terminal (if you’re on a Windows machine you don’t have a Terminal but you can download and use puTTY instead). Type:

 ssh USERNAME@IPADDRESS

So, for example, ssh myuser@192.168.0.100.

Supply your password if asked (if you’re using SSH Key Pair Authentication and disabled Password Authentication, you won’t be asked). You’re now logged into your Pi, as USERNAME, from your other computer. Your TV is now free to be used as a TV.

Install web-server software

I’m going to use nginx rather than the more traditional Apache2, because it is more efficient and on a low-power device like the Pi that’s going to be important. I’m also going to install PHP5 (with PHP APC to make it faster than normal) and MySQL as these are pretty common technologies I’m likely to use (I may later play with nodejs and other databases, but for now a standard PHP/MySQL set up is fine). Type (all on one line):

sudo apt-get install nginx php5-fpm php5-curl php5-gd php5-cli php5-mcrypt php5-mysql php-apc mysql-server

Wait while all of these are set up. Follow any prompts that appear – yes you do want to set a password for the MySQL root user, choose one and remember it.

Setting up nginx

First off lets tweak the nginx default configuration:

sudo nano /etc/nginx/nginx.conf

We need to make some changes; the Pi has ‘only’ a dual-core processor so near the top of the file we want to change the worker_processes value from 4 to 2.

Inside the http { … } block we want to un-comment the ‘server_tokens off’ line; enabling this line stops nginx from reporting which version it is to browsers; which helps to stop people from learning your nginx version and then Googling for exploits they might be able to use to hack you.

We’re also going to add some lines under the Gzip section. Gzip compresses the files before they are sent over the network; which means a faster transfer. Gzipping them does take a bit of time as the Pi will have to zip them all before it sends them. Usually it’s a good trade off and ends up with a faster responding website. You can experiment with this on and off to see which is better for you.

You want that section to look like this:

##
# Gzip Settings
##

gzip on;
gzip_disable "msie6";

gzip_min_length   1100;
gzip_vary         on;
gzip_proxied      any;
gzip_buffers      16 8k;
gzip_comp_level   6;
gzip_http_version 1.1;
gzip_types        text/plain text/css applciation/json application/x-javascript text/xml application/xml application/rss+xml text/javascript images/svg+xml application/x-font-ttf font/opentype application/vnd.ms-fontobject;

We’re telling nginx to only Gzip files above a certain size, setting some buffers, and telling it which filetypes to Gzip. We’re also setting how compressed to be in gzip_comp_level. It accepts values from 1 to 9; 1 is the least compressed but fastest to compute. 9 is the most compressed but slowest to compute. With the Pi being a low power CPU I’ve chosen a middle-ground value of 6.

We’ll also harden nginx against DDOS attacks a little bit by setting some more values. Add these somewhere inside the http block:

client_header_timeout 10;
client_body_timeout   10;
keepalive_timeout     10 10;
send_timeout          10;

All we’re doing here is limiting the amount of time nginx will wait for client connections. Keeping these short means that it’s a bit harder to flood nginx into a state of unresponsiveness.

Hit Ctrl + X to exit, save your changes.

We also need to set a few sane defaults for nginx when we want to use PHP with it. Enabling PHP support is not a global change, instead we can enable nginx to use PHP for specific virtual hosts, or even for specific directories within a specific virtual host.

To set up some nice defaults we can import into virtual hosts as we go, type:

sudo nano /etc/nginx/fastcgi_params

Now, make sure your block looks just like the one below (which is taken directly from the official nginx wiki article)

fastcgi_param   QUERY_STRING            $query_string;
fastcgi_param   REQUEST_METHOD          $request_method;
fastcgi_param   CONTENT_TYPE            $content_type;
fastcgi_param   CONTENT_LENGTH          $content_length;

fastcgi_param   SCRIPT_FILENAME         $document_root$fastcgi_script_name;
fastcgi_param   SCRIPT_NAME             $fastcgi_script_name;
fastcgi_param   PATH_INFO               $fastcgi_path_info;
fastcgi_param   REQUEST_URI             $request_uri;
fastcgi_param   DOCUMENT_URI            $document_uri;
fastcgi_param   DOCUMENT_ROOT           $document_root;
fastcgi_param   SERVER_PROTOCOL         $server_protocol;

fastcgi_param   GATEWAY_INTERFACE       CGI/1.1;
fastcgi_param   SERVER_SOFTWARE         nginx/$nginx_version;

fastcgi_param   REMOTE_ADDR             $remote_addr;
fastcgi_param   REMOTE_PORT             $remote_port;
fastcgi_param   SERVER_ADDR             $server_addr;
fastcgi_param   SERVER_PORT             $server_port;
fastcgi_param   SERVER_NAME             $server_name;

fastcgi_param   HTTPS                   $https;

# PHP only, required if PHP was built with --enable-force-cgi-redirect
fastcgi_param   REDIRECT_STATUS         200;

Setting up PHP

The default settings for PHP will work fine and it’s already pretty well optimised (it even uses Unix sockets rather than TCP to communicate with nginx), but from a security standpoint we can ensure that PHP’s FPM module will only listen to nginx (and therefore is less likely to be hacked) by typing:

sudo nano /etc/php5/fpm/pool.d/www.conf

And un-commenting the lines listen.owner and listen.group. Save and exit the file.

Securing MySQL

MySQL ships with a few conveniences that are supposed to be removed when put on a real server, to do that type:

sudo mysql_secure_installation

Carefully read all the prompts and answer them.

NOTE: MySQL may not be the best choice for you – there are other options (I can highly recommend 7 Databases in 7 Weeks if you want to learn a lot more about that). But the great advantage of MySQL is that a heck of a lot of software is written to use it. And it works pretty nicely.

Setting up your first website

You can host as many websites as you like on one Pi/nginx install, but with the Pi being fairly lightweight, and with your uploads from it all going over your home internet connection it’s a good idea to not have too many.

Let’s say we’re going to create a website called “mysite”; we will want to be able to access it on the internal network from http://mysite.local and we’ll want to access it from the internet at http://mysite.com.

Setting up the mysite.local address

Being able to use http://mysite.local means your network traffic stays in your home network and doesn’t go out to the internet – which will make it a lot faster while you’re at home. Then you can use the http://mysite.com url to access it when you’re not at home.

The easiest way to get mysite.local working for you is to edit your computer’s hosts file (i.e., the computer you’ll access the Pi from, not the Pi’s hosts file).

If you’re on OSX or Linux just open a new Terminal and type:

sudo nano /etc/hosts

If you’re stuck on Windows; Google how to edit your hosts file.

In your hosts file add the following line:

YOUR-PI’S-IP-ADDRESS mysite.local

So, for example;

192.168.0.100 mysite.local

Save the file with Ctrl+X, save your changes. Now, whenever you type “http://mysite.local” into a browser on your computer, it will go straight to the Pi over your home network.

If you were on OSX/Linux close the Terminal and return to the one that’s SSH’d to the Pi…

Create the directory for your website’s files:

Back on the Pi now, type:

sudo mkdir -p /websites/mysite/www
sudo mkdir -p /websites/mysite/logs

All your PHP/HTML/CSS etc will live in /websites/mysite/www, and all of the access and error logs related to that site will go into /websites/mysite/logs. Just so we can test the site is working later, lets create a minimalist HTML file in /websites/mysite/www:

sudo nano /websites/mysite/www/index.html

Write a short message or bit of HTML. Quit and save changes.

Now we want to secure the /websites/mysite files and directories a little bit – they’re currently owned by root, and in order for nginx to have access they need to be owned by a special user and group called ‘www-data’.

sudo chown -R www-data:www-data /websites/mysite

This changes the mysite directory and all of its contents to have the www-data owner and group.

Configure nginx to serve the website

We’ll start by making a copy of the default website config that ships with nginx, then customising it. “Available” sites are all stored as individual configuration files inside the directory /etc/nginx/sites-available – we need to create a new one for ‘mysite.com’

cd /etc/nginx/sites-available
sudo cp default mysite

That’s made a site available (to nginx) but it is not yet enabled (i.e., it’s not yet used by nginx); to enable it we create a ‘symbolic link’ inside /etc/nginx/sites-enabled to the file we just created:

sudo ln -s /etc/nginx/sites-available/mysite /etc/nginx/sites-enabled/mysite

If we ever want to disable a website all we need to do is delete the symbolic link from the sites-enabled directory (which leaves the file in sites-available where it is). We’ll remove the default website while we’re here:

sudo rm /etc/nginx/sites-enabled/default

Now lets re-load nginx so our changes all take effect:

sudo /etc/init.d/nginx reload

With those re-loaded lets get the settings for ‘mysite’ correct:

sudo nano /etc/nginx/sites-available/mysite

This will be full of stuff; a copy of the default website configuration with lots of comments to help you out. We need to make some changes:

Inside the server { … } block, change the following lines (they won’t all be together, just look through and edit):

root /websites/mysite/www
index index.php index.html index.htm
server_name mysite.local mysite.com

We also want to add a few lines:

error_log /websites/mysite/logs/error.log error;
access_log /websites/mysite/logs/access.log;

Save your edits and quit by pressing Ctrl + X, Y, Enter. Now we can reload the configuration files so nginx uses the new values:

sudo /etc/init.d/nginx reload

Once that completes open a new browser window on your computer and try to access http://mysite.local – you should see the HTML file you created earlier. If so, congratulations, you’ve got a basic server working on your Pi!

Configure nginx to use PHP

Right now you’re stuck with serving flat HTML files, but supposing you want to use PHP we can set nginx up to do that as follows.

sudo nano /etc/nginx/sites-available/mysite

Now, as a separate location block inside the server { … } block, add:

location ~ [^/].php(/|$) {
    fastcgi_split_path_info ^(.+?.php)(/.*)$;

    if (!-f $document_root$fastcgi_script_name) {
        return 404;
    }

    fastcgi_pass unix:/var/run/php5-fpm.sock;
    fastcgi_index index.php;
    include fastcgi_params;
}

This is more secure than the default configuration included within the example file, and it uses unix sockets rather than TCP (which we need as we’ve set up everything to use those).

Testing your PHP configuration

sudo nano /websites/mysite/www/index.php

Then write:

<?php phpinfo(); ?>

Save and close. Now go visit http://mysite.local/index.php in your browser; you should see a pile of information about your PHP configuration – which means it’s working.

It would be a good idea to remove that index.php file before you allow the site to be visible to the world, as it obviously contains a lot of information a hacker might find useful.

Accessing your site via a real domain

This bit is pretty easy as far as the Pi is concerned – remember how you included two domain names in the nginx configuration file for ‘mysite’; mysite.local and mysite.com? That’s literally all there is to it as far as the Pi is concerned. There are just two other things you need to do:

Setting up your domains A-record

You need to log into your Domain Registra’s account and set the A-record for your domain (mysite.com) to point to your router’s public IP address. This process varies between registra’s so consult their documentation on how to do this.

To find your public IP address just type “what is my IP” into Google, it will tell you right at the top of the page. That’s the address you need to point your domain to. This is also why you must have a fixed IP address from your ISP – otherwise when you reboot your home connection your router’s IP will change and your domain name will be pointing at the old IP address… so it won’t work.

Setting up your Router

This is the final step: getting your Domain Name to point to your public IP is half the battle, but now you need to set your router up so that it can forward incoming requests for your website to your Raspberry Pi – otherwise requests for http://mysite.com will get as far as your router and stop there.

You’ll need to consult your router’s documentation again, but you’re looking for how to set up “port forwarding”. You want to set the http port (and https port if you’re instested in using https later…) to go to your Pi’s internal IP address. Likewise, you want to make sure your router will allow out-bound network traffic on those ports too.

Conclusion

You now have a secure, optimised and entirely self-hosted server set up that you can run MySQL and PHP applications on top of. It’s accessible from your local network and also from the world wide web. You can host any number of sites on it by repeating the “Setting up your first website” steps again (up until the Pi or your home internet connection run out of resources anyway).

Bonus Material: SSL and Subdomains

Ok, this is all good but there is one major flaw if you are intending (like me) to use the Pi as a controller for your home: there’s a possibility you’ll end up having some pretty sensitive information on the Pi (or available through it), and while it would be cool to have some public access for the curious, you’ll want many aspects of the system behind some form of authentication. You’ll want sensitive parts additionally secured in terms of file access on the Pi itself, and you will want the connection encrypted to stop any hackers that might be interested in gaining access to such a system.

Let’s pretend that we’ve set up mysite.com to show material we’re happy for the world to see; maybe showing off a few graphs and details of the home automation project – essentially a ‘read only’ website we’re happy to host for public consumption.

Now we want to set up a part only we have access to and which we can use to get additional information and/or control aspects of the automated home – i.e., log in and turn the central heating off because we think we left it on earlier. Or check the webcam to see if the dog is OK. Or to see if the postman has been and left a parcel we’re expecting. Or any of that cool stuff you might want a smart home to do… The best way seems to me to use a sub-domain for that (http://something.mydomain.com).

Setting up a sub-domain is easy; as far as nginx is concerned there’s no difference between a main domain and a sub domain; they’re treated identically. Just follow the steps above for setting up the main site but substitute your sub-domain as you go (where we used ‘mysite.com’ instead use ‘whatever.mysite.com’).

Then, to get a secure encrypted connection for that sub domain, you need to follow these instructions from HTTPS Everywhere at HasGeek.com. There’s no point in me regurgitating that post as this is an area where I know very little and so have little more that I could add. Good luck!