How To Build a Home Internet Server Part 1

Aim

This howto will explain how to build and configure a home web server behind a DSL firewall.

Find the Hardware

We need a computer. I pulled a pentium 3 with a 30 GB hard drive from a local dumpster. Someone gave me an old monitor which is fine since our server will operate in text mode. I had a keyboard leftover from an earlier project. Make sure the computer has an ethernet card installed! Since this is a server you don't need a mouse and 256 MB of RAM is more than enough. No windows overhead to worry about!

Install Ubuntu

I downloaded Ubuntu 7.10 server i386 from the ubuntu website. Burned it to a CD and installed it using the minimal default configuration. The installer took about 30 minutes and used about 550MB of hard drive space. The running barebones system only used about 50MB of RAM.

Fix the /etc/apt/sources.list file

Next step is to fix the sources.list file. Specifically, remove the cdrom source and make sure the muliverse and universe repositories are included. I also remove the comment bloat that comes with the default ubuntu sources.list. Here is my copy:

owner@myserver:~$ less /etc/apt/sources.list
# newer versions of the distribution.

deb http://ca.archive.ubuntu.com/ubuntu/ gutsy main restricted
deb-src http://ca.archive.ubuntu.com/ubuntu/ gutsy main restricted

deb http://ca.archive.ubuntu.com/ubuntu/ gutsy-updates main restricted
deb-src http://ca.archive.ubuntu.com/ubuntu/ gutsy-updates main restricted

deb http://ca.archive.ubuntu.com/ubuntu/ gutsy universe
deb-src http://ca.archive.ubuntu.com/ubuntu/ gutsy universe
deb http://ca.archive.ubuntu.com/ubuntu/ gutsy-updates universe
deb-src http://ca.archive.ubuntu.com/ubuntu/ gutsy-updates universe

deb http://ca.archive.ubuntu.com/ubuntu/ gutsy multiverse
deb-src http://ca.archive.ubuntu.com/ubuntu/ gutsy multiverse
deb http://ca.archive.ubuntu.com/ubuntu/ gutsy-updates multiverse
deb-src http://ca.archive.ubuntu.com/ubuntu/ gutsy-updates multiverse

# deb http://ca.archive.ubuntu.com/ubuntu/ gutsy-backports main restricted universe multiverse
# deb-src http://ca.archive.ubuntu.com/ubuntu/ gutsy-backports main restricted universe multiverse

# deb http://archive.canonical.com/ubuntu gutsy partner
# deb-src http://archive.canonical.com/ubuntu gutsy partner

deb http://security.ubuntu.com/ubuntu gutsy-security main restricted
deb-src http://security.ubuntu.com/ubuntu gutsy-security main restricted
deb http://security.ubuntu.com/ubuntu gutsy-security universe
deb-src http://security.ubuntu.com/ubuntu gutsy-security universe
deb http://security.ubuntu.com/ubuntu gutsy-security multiverse
deb-src http://security.ubuntu.com/ubuntu gutsy-security multiverse

And, of course, follow up with apt-get update

bash# apt-get update
    ... deletia ...

Install Tiny httpd

If you have never run your own server, then I suggest you start with tiny httpd because it is VERY easy to configure.

root@myserver:~# apt-get install thttpd
Reading package lists... Done
Building dependency tree       
Reading state information... Done
Suggested packages:
  thttpd-util
The following NEW packages will be installed:
  thttpd
0 upgraded, 1 newly installed, 0 to remove and 27 not upgraded.
Need to get 0B/54.4kB of archives.
After unpacking 217kB of additional disk space will be used.
Selecting previously deselected package thttpd.
(Reading database ... 15289 files and directories currently installed.)
Unpacking thttpd (from .../thttpd_2.23beta1-7_i386.deb) ...
Setting up thttpd (2.23beta1-7) ...
Starting thttpd: web server.

Notice that it already started the web server. If you look in /etc/rc2.d you will find a link to start the thttpd daemon every time you boot the server.

Now here's what I really like about the thttpd daemon: it's config file. Here is the config file:

root@myserver:~# cat /etc/thttpd/thttpd.conf 
# /etc/thttpd/thttpd.conf

# Port: portnum
# Sets the port number which will be listened by thttpd.
# Default: 80
port=80

# chroot/nochroot
# Sets whether thttpd will chroot after starting.
# Default: nochroot
chroot

# user: userid
# Specified which user to switch after intialiazation when started as root.
# Default: www-data
user=www-data

# host: hostname
# Specifies a hostname to bind to.
# Default: Bind to all supported hostnames on the local machine.
# host=grugler

# Logfile: logfile path
# Specifies a file for logging.
# Default: Log via syslog()
logfile=/var/log/thttpd.log

# throttles: file
# Specifies a file of throttle settings.
# Default: /etc/thttpd/throttle.conf
throttles=/etc/thttpd/throttle.conf

# urlpat: pattern
# Specifies which URL can only be only be accessed from the local server.
# Default: None
# urlpat=*.mpeg|*.mp3|*.wav|*.gz|*.jpg|*.gif

# dir: directory
# Specifies a directory to chdir() to after thttpd starts.
# This directory will most likely be the directory you will be serving your
# clients from.
# Default: `cwd`
dir=/var/www

# cgipat: pattern
# Specifies which URL may contain executable CGI files.
# Default: None
cgipat=/cgi-bin/*

That's the entire config file! And it is very easy to read and understand (unlike some OTHER popular http daemons). Notice that you can change the port – that is handy if you want to run a semi-private server on an obscure port. Also note that the html files are stored in /var/www

Create an index.html

Check the local IP address of your server:

root@myserver:~# ifconfig eth0
eth0      Link encap:Ethernet  HWaddr 00:05:5D:07:B9:6D  
          inet addr:192.168.0.107  Bcast:192.168.0.255  Mask:255.255.255.0
          inet6 addr: fe80::205:5dff:fe07:b96d/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:2323 errors:0 dropped:0 overruns:0 frame:0
          TX packets:645 errors:0 dropped:0 overruns:0 carrier:642
          collisions:0 txqueuelen:1000 
          RX bytes:212368 (207.3 KB)  TX bytes:119491 (116.6 KB)
          Interrupt:11 Base address:0xec00 

My server's local IP address is 192.168.0.107. I will assume that you have another workstation running on your local network. Go to your workstation and aim the browser at http://192.168.0.107. You should see something like this:



The browser shows the contents of the http daemon's document root directory (/var/www) because there is no index.html file:

root@myserver:~# ls -lah /var/www
total 12K
drwxr-xr-x  3 root root 4.0K 2008-03-04 14:30 .
drwxr-xr-x 14 root root 4.0K 2008-03-04 14:30 ..
drwxr-xr-x  2 root root 4.0K 2007-04-30 15:16 users

So let's create a really simple index.html file. If you haven't already changed to root, do it now, then hange directory to /var/www and start vi:

owner@myserver:~$ sudo -i
[sudo] password for owner:
root@myserver:/var/www# cd
root@myserver:~# cd /var/www
root@myserver:/var/www# vi index.html

Enter and save the following text:

<html>
<h1>Under Construction!</h1>
</html>

Now go back to your workstation and hit the refresh button on your browser. You should see something like this:




Hooray! Your webserver is live! But you can only see it on the local network. The next step is to open it up to the internet

Configure Port Forwarding on Your Router/Firewall

Each router has a different management interface, but they all implement the same basic idea: any request to access port 80 on the router will be forwarded to the IP address of your server. This only makes sense if your server has a static IP address, so you should edit your /etc/network/interfaces file. First type the command

root@myserver:/etc/network# man interfaces

This will show you the manual page for your interfaces file. Which is very complicated. Fortunately what we want to do is very simple: here is an example of my interfaces file:

root@myserver:/etc/network# cat interfaces 
# This file describes the network interfaces available on your system
# and how to activate them. For more information, see interfaces(5).

# The loopback network interface
auto lo
iface lo inet loopback

# The primary network interface
auto eth0
iface eth0 inet static
   address 192.168.0.107
   netmask 255.255.255.0

It is a good idea to avoid IP address conflicts by selecting a static IP address which is outside the range used by the router's dhcp server.

Now we can set up port forwarding. My router is a Linksys WRT54GL running OpenWRT. Here's a screenshot of my port forwarding setup:




In my example I am forwarding port 80 to a server which has the static IP address 192.168.0.150.

Now you need to know your external IP address. This is the IP address that the rest of the world sees when it talks to your router. Go to your workstation and aim the browser at http://www.whatismyip.org. You should see something like this:




My external IP address is 99.251.110.40. So now, if I went to another person's house, or a public library, and typed in the URL http://99.251.110.40 then I would see my Under Construction web page. But here's a short cut. Instead of going to someone else's house, aim your web browser at http://www.proxyweb.net then enter http://99.251.110.40 (substitute your own IP address of course!) and you should see what your web page looks like to the outside world.

Getting A Name

No one likes to enter IP addresses in the URL. Most people prefer names to numbers. Also, if you are behind a DSL or cable modem then your IP address could change. Names are handy because you can publish your web page's name and just change the mapping between your IP address and name. So you need to purchase a domain name and pay for dynamic DNS service. There are many companies that provide this service. godaddy.com is probably the cheapest, but it doesn't support canadian .ca domain names. So I use easydns.com – it supports canadian TLD (top level domain) and is reasonably priced. Another place to consider is domainsatcost.ca, but as far as I know they don't provide dynamic DNS.

Here is a screenshot of the management pane of easydns.com.


It is pretty complicated. The important thing is the domain settings line. This example is for my bruceskiclub.ca website. Now click on the dns button to the right of the bruceskiclub.ca entry. The dns settings pane will appear. Scroll down to the hosts section, as shown in this screenshot:




This is where the DNS remembers what IP address belongs to this domain name. I also like to make an alias, because some people like to type in www.bruceskiclub.ca, while others prefer just bruceskiclub.ca. I can create the alias in the alias section:

When all the changes are made, click on the next button at the bottom of the page. Review the changes on the summary page. If you are happy with the changes click the done button. It takes about fifteen minutes for the changes to become effective. Then the world can see your webpage at your own domain name!

Setting up ddclient

Now the problem is that your ISP might change your external IP address. When that happens you must change your easydns configuration. Sound hard? No problem! There's a handy little linux utility called ddclient (dynamic DNS client) which will do the work automatically. First install ddclient:

root@myserver:/etc/network# apt-get install ddclient

A dpkg config screen will appear asking which dns service you are using. Answer the questions as accurately as you can. If you don't know the answers just put anything in and you can edit the config file manually with a text editor.

We want to run ddclient as a daemon, so we must edit the /etc/defaults/ddclient file and set run_daemon to true:

root@myserver:/etc/network# cat /etc/default/ddclient 
# Configuration for ddclient scripts 
# generated from debconf on Tue Mar  4 15:32:10 EST 2008
#
# /etc/default/ddclient

# Set to "true" if ddclient should be run every time a new ppp connection is 
# established. This might be useful, if you are using dial-on-demand
run_ipup="true"

# Set to "true" if ddclient should run in daemon mode
run_daemon="true"

# Set the time interval between the updates of the dynamic DNS name in seconds.
# This option only takes effect if the ddclient runs in daemon mode.
daemon_interval="300"

Also, note that the daemon interval is set to 300 seconds (5 minutes). That means that the ddclient process will check your IP address every five minutes and fix any changes that might have occured. Here's my /etc/ddclient.conf file. Yours might be different - seek help on the internet if you have trouble figuring out your exact config.

root@radagast:/etc# cat ddclient.conf 
daemon=300                              # check every 300 seconds
syslog=yes                              # log update msgs to syslog
mail=root                               # mail all msgs to root
mail-failure=root                       # mail failed update msgs to root
pid=/var/run/ddclient.pid               # record PID in file.
## To obtain an IP address from Web status page (using the proxy if defined)
use=web, web=checkip.dyndns.org/, web-skip='IP Address' # found after IP Address
#
#use=ip,                     ip=127.0.0.1       # via static IP's
#use=if,                     if=eth0            # via interfaces
use=web                                 # via web
#

##
## EasyDNS (easydns.com)
##
server=members.easydns.com,             \
protocol=easydns,                       \
login=andrew_howlett,           \
password=notmypassword      \
bruceskiclub.ca

Notice that you must include your account name and password in the ddclient.conf file. That makes me a bit nervous. Changing the file's permissions so that only root can read the file makes me feel better:

root@radagast:/etc# chmod 600 ddclient.conf 
root@radagast:/etc# ls -lah ddclient.conf 
-rw------- 1 root root 677 2008-03-04 15:33 ddclient.conf

Create some Content

Your server is up and running and the world can see it. But all they see is an Under Construction sign. You need to upload some content to your server. I would suggest installing the openssh-client and openssh-server packages so you can secure copy content from your workstation. In Part 2 we will set up rsync ...