Raspberry Pi Webserver

This site has been great fun, but it has run its course, and it is time to move on. Please get what you want from the site before January 1, 2020. Some pages will move to another site but most will go away.

A webserver that serves static pages is of limited usefulness these days. Most websites, and all web services, require programmed responses to queries from visitors. That means you need to have a programming language such as PHP, python, Java, or Javascript. In this example, we will make a webserver that runs Apache and PHP. PHP is the current standard for web site programming.

There are a couple of ways it can be done, but the one I've chosen is to have a single 1TB external drive partitioned into two approximately 500GB partitions, putting the database on one and the web site on the other. You could just as easily use two drives. Actually it is easier, but it is more compact with a single drive, although one could argue that my 3.5 inch drive is not very compact.

Boot Disk

Start with a full install of Raspian on an SD card.

Install the Software

Installing the software is the easiest part of this process. Do things in the order shown and it will just work. Then we'll do a little bit of customization.

sudo apt-get install apache2
sudo apt-get install mysql-server
sudo apt-get install php5
sudo apt-get install php5-mysql

At this point, you can test the install by pointing your browser to "http://localhost/". You should get an html page showing the server is up. To test the PHP install, delete the html file and create a php file in the "/var/www/html" directory.

sudo su
rm /var/www/html/index.html
nano /var/www/html/index.php

Enter this one line:

<?php phpinfo(); ?>

Save the file and refresh your browser. You should get a page of configuration data for PHP. If so, the php installation worked. Copy the file to the user directory:

cp /var/www/html/index.php /home/pi

Prepare the External Drive

We need to unmount the external drive volumes. Rasbian automounts external drives. To find the volumes, use the following command:

mount |grep media

It will show all mounted volumes, similar to this:

/dev/sda2 on /media/pi/2bce3e4c-cac7-4336-9128-d5ed47191d95 type ext3 (rw,nosuid,nodev,relatime,data=ordered,uhelper=udisks2)
/dev/sda1 on /media/pi/c8c7af08-dcbd-4d44-a7bb-8f4a8260d121 type ext3 (rw,nosuid,nodev,relatime,data=ordered,uhelper=udisks2)

Now we can unmount the volume(s).

umount /dev/sda1
umount /dev/sda2

The drive will need to be partitioned. It is necessary to delete any existing partitions before making new ones. The external drive on the Raspberry Pi is /dev/sda. We want to verify that using fdisk to get the USB device name. You should still be superuser (# prompt).

fdisk -l |grep "^Disk /" |grep -ve ram

That command yields these results on the Raspberry Pi 3B:

root@raspberrypi-web: # fdisk -l |grep "^Disk "
Disk /dev/mmcblk0: 14.9 GiB, 15931539456 bytes, 31116288 sectors
Disk /dev/sda: 931.5 GiB, 1000204886016 bytes, 1953525168 sectors

We're only interested in that "/dev/sda" line. It might be "/dev/sdb" if there is another drive attached. Now we run fdisk on that specific drive.

fdisk /dev/sda

If you want to familiarize yourself with fdisk commands, type m for help. fdisk does not write anything to the drive until you type the w command. At that point, all changes are written to the disk, and your drive configuration is changed. It is irreversible. The first thing to do is delete any existing partitions. This is done with the d command. It will prompt you for the partition to delete. It defaults to the highest partition number. If that number is higher than one, there are multiple partitions on the drive, and they will all have to be deleted. Use the d command once for each partition.

After deleting the partitions, it is time to add new partitions. Two of them, each approximately half the size of the disk. To do that, use the n command. It will ask for the starting sector. Take the default. Then it will ask for the ending sector. For a 1TB drive, enter +500G and it will allocate 500GB to the partition. If you are using an 80GB drive, then allocate +40G to the first partition. When you are back at the command prompt, enter the n command again, and this time take all of the defaults. It will allocate the rest of the disk to the second partition.

Until now, all commands have operated on an in-memory copy of the disk's partition table. Enter the w command and flush all changes to the drive.

Now you need to format the partitions. This is done with the ext2fs utility:

mkfs.ext3 /dev/sda1

If it says the drive contains an existing filesystem, tell it to proceed anyway. This takes a few minutes on a 500GB partition. When it is done, do the other partition:

mkfs.ext3 /dev/sda2

Again, it takes a few minutes. When it is done, you have two 500GB volumes that can be mounted wherever you want in the file system.

Using the New Volumes

We will mount them to two different places in the filesystem. One will go to "/var/www" and will be for the Apache web server to use. The other will go to a new root directory called "/data" and will be for MySQL to use. First, you have to make a place in the filesystem to mount to. There is already a "/var/www". We know that because the web server worked. There is not a "/data", so we have to create that one. Still as the superuser (# prompt), type:

mkdir /data

Now change the filesystem table "/etc/fstab" to mount our new volumes on the two mount points.

nano /etc/fstab

Your fstab should look like this:

proc            /proc           proc    defaults          0       0
/dev/mmcblk0p1  /boot           vfat    defaults          0       2
/dev/mmcblk0p2  /               ext4    defaults,noatime  0       1
# a swapfile is not a swap partition, no line here
#   use  dphys-swapfile swap[on|off]  for that

We're just going to add two lines at the end to put the new volumes where we want them:

/dev/sda1	/data		ext3	defaults	1	2
/dev/sda2	/var/www	ext3	defaults	1	2

Now, we can mount the volumes by running the mount command:

mount -a

That command will attempt to mount all volumes in the fstab to their respective mount points. Proof that it worked will be that the web server no longer shows you the status page, but gives you a 404 error page. Refresh your browser and see if you get the error. You can also run the following command to get the volumes and mount points:

root@raspberrypi-web:/var/www/html# df -h
Filesystem      Size  Used Avail Use% Mounted on
/dev/root        15G  3.5G   11G  25% /
devtmpfs        459M     0  459M   0% /dev
tmpfs           463M     0  463M   0% /dev/shm
tmpfs           463M  6.4M  457M   2% /run
tmpfs           5.0M  4.0K  5.0M   1% /run/lock
tmpfs           463M     0  463M   0% /sys/fs/cgroup
/dev/mmcblk0p1   63M   21M   43M  33% /boot
/dev/sda2       425G   71M  403G   1% /var/www
/dev/sda1       493G  100M  467G   1% /data
tmpfs            93M  4.0K   93M   1% /run/user/1000

Database Configuration

The database is currently writing data files to the /var/lib/mysql/mysql directory. We want to change it to write to /data/mysql. To do that, we have to edit the MySQL config file and copy the existing data to the new directory.

nano /etc/mysql/my.cnf

The area we are interested in looks like this:

# * Basic Settings
user            = mysql
pid-file        = /var/run/mysqld/mysqld.pid
socket          = /var/run/mysqld/mysqld.sock
port            = 3306
basedir         = /usr
datadir         = /var/lib/mysql
tmpdir          = /tmp
lc-messages-dir = /usr/share/mysql

The line we want is the "datadir" line. Change it to:

datadir         = /data

That tells MySQL where to look, but it already built the files in /var/lib/mysql, so we have to copy the MySQL data to the new location:

cp -r /var/lib/mysql/* /data

And while we are copying:

mkdir /var/www/html
cp /home/pi/index.php /var/www/html

One more thing. Permissions. The new volumes have either pi or root owners.

chown -R mysql:mysql /data
chown -R www-data:www-data /var/www

Now for a final reboot. You should test the web server again to see that you get your php status page.

As an Amazon Associate I earn from qualifying purchases.
Arduino Board Logo


Arduino-Board is the go-to source for information on many available Arduino and Arduino-like boards, tutorials and projects.

Help and Support


Stay updated

Sign up if you would like to receive our once monthly newsletter.