Don't Panic: An Absolute Beginner's Guide to Building a Map Server

There are a lot of great mapping applications out there that run on a server. They can be intimidating to install and configure so I thought I would document my steps so everything would be in one place. This a a guide for the absolute beginner so if you have some command-line experience, I promise I'm not being condescending. Future posts will cover how we're actually using these tools to build our maps.

This tutorial should take you from absolutely nothing to a fully-functional web server containing:

  • PostGIS: A PostgreSQL database optimize to store spatial information. It can easily import shapefiles and OSM data using command line tools as well as connect to mapping services like QGIS and Mapnik.
  • Mapnik: A very powerful tool for automatically generating maps from geographic data with lots of control over cartographic display and rendering.
  • TileStache: A simple way to efficiently serve geographic data to mapping applications. It can send tiled vector or raster data and will speed up any application that needs to load lots of data.

Basic Setup

I'm going to be using a Rackspace Cloud Server for this example. It's a cheap way to get a server up and running and I've found them to be great with support. They automatically build your server and install the operating system. You just need to select 3 things:

  1. Operating System: Ubuntu 11.10 (Oneric Ocelot)
  2. Server Name: tiles
  3. Server Size: 1024 MB of RAM and 40GB of disk

The RAM and disk space are the bare minimum requirements. Fortunately, Rackspace let's you upgrade your server at any time so it's easy to configure it small as a sandbox and then beef it up if you decide to put it into production later on.

Once you click "Create server" you'll see your new root password. Copy it to the clipboard but don't worry about keeping it super-safe. We'll change it as soon as we log in for the first time (they also email it to you). Setup will take about 5 minutes to complete and they'll email you when it's finished.

Terminal and Remote Access

Since this server is in the cloud (ooooooh), the only way to access it is remotely through SSH. Open any SSH client you like (Terminal is already installed on OSX) and get comfortable. First thing we need to do is to log on to our remote server. Make sure you have that email with your root password and IP address and type into the terminal window:

ssh root@(your ip-address)

That command tells the terminal to start an SSH session, logging in as root to the server at the specified IP address. The root username is the default admin of the server. We'll do most of this setup as root since it has full control over the system.

When it asks, just paste your root password from the email and you should be logged in and should see something like this:

root@tiles:~#

The # tells you the system is ready to receive commands. Let's now change the root password into something we'll remember. Type:

passwd

and hit enter and follow the prompts.

Now we want to do a quick software update to make sure everything is secure. Run both of these commands:

sudo aptitude update
sudo aptitude upgrade

We'll use the sudo command often. It tells the server to perform the task as a super-user which gives you extra permissions to modify the system. Here's another top-tip: At the command prompt, you can hit the up arrow on your keyboard to cycle through your previous commands.

Installing the Web Server Bits

This part of the tutorial is taken from symana.labs

The next step is to install the LAMP stack. LAMP stands for (Linux, Apache, MySQL, PHP) and has all the basics to turn your server into a web server. It can be installed with a single command:

sudo tasksel install lamp-server

and follow the prompts. To secure the MySQL server from common database attacks, run:

mysql_secure_installation

Enter the password you set in the previous step and then enter "n" to keep it. Enter "Y" for the rest of the questions.

If you think you are going to be using MySQL for other applications on the server, you can install phpmyadmin to give you a graphical way to interact with the DB by running:

sudo apt-get install phpmyadmin

When the install completes, we need to modify the Apache2 config file to include information about phpmyadmin:

sudo nano /etc/apache2/apache2.conf

Use Ctrl-V to scroll down to the bottom of the file and add:

# Include phpmyadmin configuration:
Include /etc/phpmyadmin/apache.conf

Press Ctrl-O to save (write out) the file and press Enter to save it in its current location. Then press Ctrl-X to exit editing the file.
When you're done configuring everything, restart apache with:

/etc/init.d/apache2 restart

To configure a fully qualified domain name for apache type:

echo "ServerName localhost" | sudo tee /etc/apache2/conf.d/fqdn

Now we have to configure the server's hostname so we can contact it via a URL instead of the IP address. If you enter:

hostname -f

you should see the server name you entered when you setup the server. We want to turn that into a subdomain for our primary domain (for me it will be tiles.axismaps.com) but you can skip this if you don't have your own domain (you'll just keep using your IP address to connect to the server). To tell the server what the rest of the domain is, we'll need to edit a few text files using nano, the built-in terminal text editor.

sudo nano /etc/hostname

Will show you something like:

tiles

You'll want to change that to:

tiles.(primary domain name).com

We are using tiles.axismaps.com for ours. When you've edited the file, hit Ctrl-X (not command if you're on a Mac) then enter Y to save changes and hit Enter to overwrite the file. Do the same thing and add your domain to the second entry in:

sudo nano /etc/hosts

To make the changes stick, reboot your server with:

sudo reboot

The final step is to add a DNS record with your web host that points back to the server. From your server management page in Rackspace, click the DNS tab then click your domain name. Click "Add" to enter a new record with values:

  • Type: A
  • Name: tiles.(primary domain name).com
  • Content: (server ip-address)

By this point, the server will have rebooted so you can log in again with:

ssh root@(your ip-address)

To allow established connections to continue to function:

iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

To allow SSH traffic:

iptables -A INPUT -p tcp --dport 22 -j ACCEPT

To allow HTTP traffic:

iptables -A INPUT -p tcp --dport 80 -j ACCEPT

To allow HTTPS traffic:

iptables -A INPUT -p tcp --dport 443 -j ACCEPT

To allow remote database connections:

iptables -A INPUT -p tcp --dport 5432 -j ACCEPT

Drop all remaining traffic:

iptables -A INPUT -j DROP

Save all the rules to a file:

sudo iptables-save > /etc/iptables.rules

To enable the firewall, we need to add the rules to the network adapter by editing the interfaces file:

sudo nano /etc/network/interfaces

and add the line:

pre-up iptables-restore < /etc/iptables.rules

just after iface eth0 inet static and make sure it is indented like the other lines. Save and exit the file then reboot the server.

This is a good time to create a server backup. In Rackspace, click on "Images" then click "New On-Demand Image" to create a backup of your server. This way, if something goes wrong, you can be up and running again quickly.

Installing PostGIS

Some parts of this tutorial is taken from OpenStreetMap Wiki

To give us access to all the software we'll need, we need to add an additional software repository. First, enter:

sudo apt-get install python-software-properties

to install the command that will allow us to add new repositories. Then we can add a GIS-specific software repository by doing:

sudo add-apt-repository ppa:ubuntugis/ubuntugis-unstable

Now we need to update the system to allow it to pull down the available software from the new repository:

sudo aptitude update

We should be ready to install all of the PostGIS packages with:

sudo apt-get install postgresql-9.1-postgis postgresql-contrib-9.1

Now we need to setup PostGIS to make the newly installed database ready for GIS. Swtich to the database user:

sudo -u postgres -iH

Now we will create a user within the database that can access your maps:

createuser -SdRP gisuser

Enter a password for connecting to the database (it should be different from your root password).

Now we will create and configure a database to hold your spatial data:

createdb -E UTF8 -O gisuser gis
psql -d gis -f /usr/share/postgresql/9.1/contrib/postgis-1.5/postgis.sql
psql -d gis -f /usr/share/postgresql/9.1/contrib/postgis-1.5/spatial_ref_sys.sql
psql gis -c "ALTER TABLE geometry_columns OWNER TO gisuser"
psql gis -c "ALTER TABLE spatial_ref_sys OWNER TO gisuser"
exit

Now we need to configure access to our database first by editing the access file:

sudo nano /etc/postgresql/9.1/main/pg_hba.conf

Scroll down to the bottom of the file and change the words ident and md5 to "trust" (there should be 3). If you want to connect to this database remotely (to view your data in an external manager or view it in QGIS) you should add the line:

# Enable remote connections:
host    all         all         0.0.0.0/0             md5

to the bottom of the file and then save and close. You'll also need to enable remote listening by editing the main configuration file here:

sudo nano /etc/postgresql/9.1/main/postgresql.conf

and change the line:

#listen_addresses = 'localhost'

to

listen_addresses = '*'

(don't forget to remove the "#" in front). Save and overwrite the file. To apply the changes, restart the database server:

sudo /etc/init.d/postgresql restart

To test if everything has been installed properly, log into the database as the new user we created.

psql gis gisuser

If you type \d you should be able to see all 3 tables. Then type \q to return.

Installing Mapnik2

Copied exactly from the Mapnik Wiki

To install Mapnik, enter:

sudo add-apt-repository ppa:mapnik/nightly-2.0
sudo apt-get update
sudo apt-get install libmapnik mapnik-utils python-mapnik

That's it!

Installing TileStache

Some parts of this tutorial is taken from TileStache on GitHub

The first step in installing TileStache is to install mod_python which is the interface TileStache will use to communicate with the web server. You can install it with:

sudo apt-get install libapache2-mod-python

Then restart your web server with:

sudo /etc/init.d/apache2 restart

Now we need to install some more packages that TileStache depends on. First we'll switch to the directory where we'll keep the new applications:

cd /etc

Install packages Curl and Git via aptitude to help with the install:

sudo apt-get install curl
sudo apt-get install git-core

Now install some python tools and libraries that are required:

sudo apt-get install python-setuptools
sudo aptitude install python-dev
sudo apt-get install libjpeg8 libjpeg62-dev libfreetype6 libfreetype6-dev

We'll grab and install PIP to easily install python modules:

curl -O https://raw.github.com/pypa/pip/master/contrib/get-pip.py
sudo python get-pip.py

Now install the required python modules

sudo pip install -U werkzeug
sudo pip install -U simplejson
sudo pip install -U modestmaps

The Python Image Library module has some quirks in Ubuntu 11.10 so we need to do some quick fixes:

sudo ln -s /usr/lib/x86_64-linux-gnu/libjpeg.so /usr/lib
sudo ln -s /usr/lib/x86_64-linux-gnu/libfreetype.so /usr/lib
sudo ln -s /usr/lib/x86_64-linux-gnu/libz.so /usr/lib

Before we can install it:

sudo pip install -U pil

Finally we'll download TileStache from GitHub:

git clone https://github.com/migurski/TileStache.git

And install it globally by running the install script:

cd TileStache/
python setup.py install

Finally, we'll have to add the mod_python configuration to tell our web server which URLs to have TileStache process. Start by editing the apache configuration file:

sudo nano /etc/apache2/httpd.conf

and add this:

<Directory /var/www/tiles>
  AddHandler mod_python .py
  PythonHandler TileStache::modpythonHandler
  PythonOption config /etc/TileStache/tilestache.cfg
</Directory>

This will direct any web traffic to the "tiles" folder containing the file extension ".py" to TileStache. We just need to add a tiles directory to the web directory so we don't get an error:

mkdir /var/www/tiles

Reboot your server to finish it off:

reboot

Testing Your Server

Once your server reboots, we can test to make sure TileStache is installed correctly and is running through mod_python and receiving maps from Mapnik.

In your browser, go to: http://tiles..com/tiles/tiles.py/osm/preview.html

You should see a OSM tiled map fullscreen, confirming TileStache is correctly installed and running. When you work with TileStache, you can always preview your tilesets at .../tiles/tiles.py//preview.html

Now go to: http://tiles..com/tiles/tiles.py/example/preview.html

You should see a simple gray country map which confirms that TileStache is talking to Mapnik, rendering a shapefile stored in the TileStache directory.

Finished

Now that everything is installed, you can go nuts with TileStache, Mapnik and PostGIS to render your own tiled maps. We'll come back to this point in the coming weeks to show examples of how you can actually use these tools to make some maps. Some sample topics might include:

  • Thematic cartography with TileStache and Mapnik
  • Combining raster and vector tiles to optimize mapping for iPad
  • Custom map tiles from OSM data