How to Set Up Tegola Vector Tile Server on Ubuntu 20.04 for OpenStreetMap
Tegola is an open-source vector tile server for OpenStreetMap. Previously we explained the process of setting up OSM tile server with mapnik and mod_tile, which is a raster-based tile server. This tutorial is going to show you how to set up Tegola vector tile server on Ubuntu 20.04.
Benefits of Vector Tiles
- Better display quality for high DPI devices (retina display)
- Small efficient format (No 512 * 512 images needed)
- Fast map rendering
- Clearer, more readable text
- On-the-fly labeling for heads up display
- Separate content and styling, which allows for creating multiple styles pointing to the same tile stack.
- Day and night mode
Vector Tile Formats
There are several formats for vector tiles.
- GeoJSON
- TopoJSON
- Mapbox Vector Tile (MVT)
- 05m
- OpenScienceMap binary
- Arc GeoServices JSON
Tegola uses the Mapbox vector tile format.
Prerequisites/Hardware Requirements
The required RAM and disk space depend on which country’s map you are going to use. For example,
- The UK map requires at least 12G RAM and 100GB disk space.
- The whole planet map requires at least 32G RAM and 1TB SSD (Solid State Drive). It’s not viable to use a spinning hard disk for the whole planet map.
It takes a long time to import large map data, like the whole planet, to PostgreSQL database. Consider adding more RAM and especially using SSD instead of spinning hard disk to speed up the import process.
If you are going to host the entire world map, I recommend you buy the extra-large VPS from Contabo, which boasts
- A 10 core CPU
- 60 GB RAM
- 1.6 TB Intel Optane SSD
It costs just 26.99 €/month.
Step 1: Upgrade Software
It’s always a good practice to update server software before doing any major work on your server. Log into your server via SSH and run the following command.
sudo apt update; sudo apt upgrade -y
Step 2: Install PostgreSQL Database Server and the PostGIS Extension
We will use PostgreSQL to store map data. The PostgreSQL team always strives to make performance improvements with every new version. Run the following 4 commands to install the latest version of PostgreSQL.
echo "deb [signed-by=/etc/apt/keyrings/postgresql.asc] http://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" | sudo tee /etc/apt/sources.list.d/pgdg.list sudo mkdir /etc/apt/keyrings/ wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo tee /etc/apt/keyrings/postgresql.asc sudo apt update sudo apt install -y postgresql postgresql-contrib postgresql-15 postgresql-client-15
Then install PostGIS, which is a geospatial extension to PostgreSQL.
sudo apt install postgis postgresql-15-postgis-3
PostgreSQL database server will automatically start and listens on 127.0.0.1:5432
. The postgres
user will be created on the OS during the installation process. It’s the super user for PostgreSQL database server. By default, this user has no password and there’s no need to set one because you can use sudo
to switch to the postgres
user and log into PostgreSQL server.
sudo -u postgres -i
Now you can create a PostgreSQL database user osm
.
createuser osm
Set a password for the osm user. The password should not contain a forward slash /
character.
psql -c "ALTER USER osm WITH PASSWORD 'secret_password';"
Then create a database named osm
and at the same time make osm
as the owner of the database. -E UTF8
specifies the character encoding scheme to be used in the database is UTF8.
createdb -E UTF8 -O osm osm
Next, create the postgis
and hstore
extension for the osm
database.
psql -c "CREATE EXTENSION postgis;" -d osm psql -c "CREATE EXTENSION hstore;" -d osm
Set osm
as the table owner.
psql -c "ALTER TABLE spatial_ref_sys OWNER TO osm;" -d osm
Create a database named natural_earth
and at the same time make osm
as the owner of the database.
createdb -E UTF8 -O osm natural_earth
Next, create the postgis
and hstore
extension for the natural_earth
database.
psql -c "CREATE EXTENSION postgis;" -d natural_earth psql -c "CREATE EXTENSION hstore;" -d natural_earth
Exit from the postgres
user.
exit
Step 3: Optimize PostgreSQL Server Performance
The import process can take some time. To speed up this process, we can tune some PostgreSQL server settings to improve performance. Edit PostgreSQL main configuration file.
sudo nano /etc/postgresql/15/main/postgresql.conf
First, we should change the value of shared_buffer
. The default setting is:
shared_buffers = 128MB
This is too small. The rule of thumb is to set it to 25% of your total RAM (excluding swap space). For example, my VPS has 60G RAM, so I set it to:
shared_buffers = 15GB
Find the following line.
#work_mem = 4MB #maintenance_work_mem = 64MB
Again, the value is too small. I use the following settings.
work_mem = 1GB maintenance_work_mem = 8GB
Then find the following line.
#effective_cache_size = 4GB
If you have lots of RAM like I do, you can set a higher value for the effective_cache_size like 20G.
effective_cache_size = 20GB
Save and close the file. Restart PostgreSQL for the changes to take effect.
sudo systemctl restart postgresql
By default, PostgreSQL would try to use huge pages in RAM. However, Linux by default does not allocate huge pages. Check the process ID of PostgreSQL.
sudo head -1 /var/lib/postgresql/15/main/postmaster.pid
Sample output:
7031
Then check the VmPeak value of this process ID.
grep ^VmPeak /proc/7031/status
Sample output:
VmPeak: 16282784 kB
This is the peak memory size that will be used by PostgreSQL. Now check the size of huge page in Linux.
cat /proc/meminfo | grep -i huge
Sample output:
AnonHugePages: 0 kB ShmemHugePages: 0 kB HugePages_Total: 0 HugePages_Free: 0 HugePages_Rsvd: 0 HugePages_Surp: 0 Hugepagesize: 2048 kB Hugetlb: 0 kB
We can calculate how many huge pages we need. Divide the VmPeak value by the size of huge page: 16282784 kB / 2048 kB = 7950. Edit /etc/sysctl.conf file.
sudo nano /etc/sysctl.conf
Add the following line to allocate 7950 huge pages.
vm.nr_hugepages = 7950
Save and close the file. Then apply the changes.
sudo sysctl -p
If you check the meminfo again,
cat /proc/meminfo | grep -i huge
We can see there are 7950 huge pages available.
AnonHugePages: 0 kB ShmemHugePages: 0 kB HugePages_Total: 7950 HugePages_Free: 7950 HugePages_Rsvd: 0 HugePages_Surp: 0 Hugepagesize: 2048 kB
Restart PostgreSQL to use huge pages.
sudo systemctl restart postgresql
Use Screen on Remote Servers
Since the import process can take a long time and your computer might be disconnected from Internet, it’s recommended to use the screen utility to keep your session alive. Install screen on the Ubuntu 20.04 server:
sudo apt install screen
Then start screen:
screen
Upon first launch, you will see an introduction text, simply press Enter
to end. Then you will be able to run commands as usual.
Step 4: Import the Map Data to PostgreSQL
To import map data, we will use imposm
which converts OpenStreetMap data to postGIS-enabled PostgreSQL databases. Download it from Github.
wget https://github.com/omniscale/imposm3/releases/download/v0.11.1/imposm-0.11.1-linux-x86-64.tar.gz
Extract the archive.
tar xvf imposm-0.11.1-linux-x86-64.tar.gz
Move it to /opt/
directory.
sudo mv imposm-0.11.1-linux-x86-64 /opt/imposm
Download tegola-osm
scripts.
git clone https://github.com/go-spatial/tegola-osm.git
Move it to /opt/
directory.
sudo mv tegola-osm /opt/
Next, run the following command to download the map data of the whole planet (50G) in PBF (ProtoBufBinary) format.
wget -c http://planet.openstreetmap.org/pbf/planet-latest.osm.pbf
Note that download speeds for openstreetmap.org are currently restricted to 2048 KB/s. You can download the plant map from another mirror, like
wget -c https://download.bbbike.org/osm/planet/planet-latest.osm.pbf
If you want a map of individual country/state/province/city, go to http://download.geofabrik.de. Also, BBBike.org provides extracts of more than 200 cities and regions worldwide in different formats. For example, download the map data of Great Britain (1.1G) with the following command.
wget -c http://download.geofabrik.de/europe/great-britain-latest.osm.pbf
Run the following command to import map data.
/opt/imposm/imposm import -connection postgis://osm:osm_password@localhost/osm -mapping /opt/tegola-osm/imposm3-mapping.json -read great-britain-latest.osm.pbf -write
Now you probably don’t need to do other things on your server. Since you are using Screen, you can press Ctrl+A, release those keys, and then press D key to detach from the current Screen session. You will see a message like below.
[detached from 32113.pts-1.focal]
This tells me that the previous Screen session ID is 32113. You can log out from the SSH session and even shut down your computer. Don’t worry, the OSM import process is still running. When you need to come back and check the import progress, SSH into your server and run the following command to get the previous Screen Session ID.
screen -ls
Sample output:
There is a screen on: 32113.pts-1.focal (05/19/2020 03:45:29 PM) (Detached) 1 Socket in /run/screen/S-linuxbabe.
Then you can re-attach to the previous Screen session.
screen -r 32113
And you will be able to continue your work.
Once the map data has been imported, run the following command to deploy it for production.
/opt/imposm/imposm import -connection postgis://osm:osm_password@localhost/osm -mapping /opt/tegola-osm/imposm3-mapping.json -deployproduction
Step 5: Download Tegola
Go to the Tegola Github page and download the linux version. You can use the following command to download it in terminal.
wget https://github.com/go-spatial/tegola/releases/download/v0.15.2/tegola_linux_amd64.zip
Unzip it.
sudo apt install unzip unzip tegola_linux_amd64.zip
Move the binary to /usr/local/bin/
directory.
sudo mv tegola /usr/local/bin/
Step 6: Import the OSM Land and Natural Earth dataset
Edit the /opt/tegola-osm/osm_land.sh
file.
sudo nano /opt/tegola-osm/osm_land.sh
Enter your database details.
# database connection variables
DB_NAME="osm"
DB_HOST="localhost"
DB_PORT="5432"
DB_USER="osm"
DB_PW="osm_password"
Save and close the file. Install gdal
.
sudo apt install gdal-bin
Generate relation land_polygons
in the osm
database.
/opt/tegola-osm/osm_land.sh
Next, edit the /opt/tegola-osm/natural_earth.sh
file.
sudo nano /opt/tegola-osm/natural_earth.sh
Enter your database details.
# database connection variables
DB_NAME="natural_earth"
DB_HOST="localhost"
DB_PORT="5432"
DB_USER="osm"
DB_PW="osm_password"
Save and close the file. Then generate tables in the natural_earth
database.
/opt/tegola-osm/natural_earth.sh
Run the postgis_helpers
SQL script.
sudo -u postgres -i psql -d osm -a -f /opt/tegola-osm/postgis_helpers.sql
Run the postgis_index.sql
script to add indexes to OSM table columns to increase query performance.
sudo -u postgres -i psql -d osm -a -f /opt/tegola-osm/postgis_index.sql
Step 7: Start Tegola
Edit the configuration file.
sudo nano /opt/tegola-osm/tegola.toml
Configure the listening port, cache type, and data provider as follows.
[webserver] port = ":8080" # Tegola offers three tile caching strategies: "file", "redis", and "s3" [cache] type = "redis" #bucket = "${S3CACHE_BUCKET}" #basepath = "${S3CACHE_BASEPATH}" #region = "${S3CACHE_REGION}" #aws_access_key_id = "${S3CACHE_AWS_ACCESS_KEY_ID}" #aws_secret_access_key = "${S3CACHE_AWS_SECRET_ACCESS_KEY}" # OpenStreetMap (OSM) [[providers]] name = "osm" type = "postgis" host = "127.0.0.1" port = "5432" database = "osm" user = "osm" password = "osm_password" # Natural Earth [[providers]] name = "ne" type = "postgis" host = "127.0.0.1" port = "5432" database = "natural_earth" user = "osm" password = "osm_password"
Notice there are two databases: osm
and natural_earth
.
Find the following line.
center = [-76.275329586789, 39.153492567373, 8.0] # optional center value. part of the TileJSON spec
You can set a custom center location (longitude and latitude) for your map and the default zoom level. Notice that you must use decimal values and can’t use integer values.
center = [0.8, 55.5, 5.0] # optional center value. part of the TileJSON spec
Save and close the file. Then install Redis cache server.
sudo apt install redis-server
Start Tegola.
/usr/local/bin/tegola serve --config=/opt/tegola-osm/tegola.toml
Now Tegola is listening on port 8080.
Step 8: Create a Systemd Service for Tegola
Tegola is running in the foreground. In order to run it in the background, we can create a systemd serivce, which also allow Tegola to automatically start at system boot time. Press Ctrl+C
to stop the current Tegola process, then create the tegola.service file.
sudo nano /etc/systemd/system/tegola.service
Add the following lines to this file.
[Unit] Description=Tegola Vector Tile Server [Service] Type=simple User=www-data ExecStart=/usr/local/bin/tegola serve --config=/opt/tegola-osm/tegola.toml Restart=on-failure RestartSec=5 [Install] WantedBy=multi-user.target
Save and close the file. Make www-data
as the owner of the /tmp/tegola-cache/
directory.
sudo chown www-data:www-data /tmp/tegola-cache/ -R
Then enable and start this service.
sudo systemctl enable tegola --now
Check its status. Make sure it’s running.
systemctl status tegola
If it’s not running, you can check the journal logs to find out what went wrong.
sudo journalctl -eu tegola
Then in your web browser address bar, type
your-server-ip-address:8080
You should see the vector tile map. Congrats! You just successfully built your own vector tile server. Note that old versions of Firefox can’t display these vector tiles. You need to use a third-party library to display vector tile based maps, which is explained at the end of this tutorial.
Step 9: Setting Up Reverse Proxy
To access the Tegola using a domain name, we can set up a reverse proxy for Tegola with Nginx or Apache. This will also allow us to enable HTTPS with free Let’s Encrypt certificate.
Nginx
Nginx is a very popular web server and reverse proxy. If you prefer to use Nginx, run the following command to install it.
sudo apt install nginx
Then create a server block file for Tegola.
sudo nano /etc/nginx/conf.d/tegola.conf
Add the following content to this file. Replace vector-tile.example.com
with your own domain name. You should also create DNS A record for this sub-domain. If you don’t have a real domain name, I recommend going to NameCheap to buy one. The price is low and they give whois privacy protection free for life.
server {
listen 80;
listen [::]:80;
server_name vector-ile.example.com;
access_log /var/log/nginx/tegola.access;
error_log /var/log/nginx/tegola.error;
location / {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Protocol $scheme;
proxy_set_header X-Forwarded-Host $http_host;
}
}
Save and close this file. Then test Nginx configuration.
sudo nginx -t
If the test is successful, reload Nginx for the change to take effect.
sudo systemctl reload nginx
Now you can access Tegola via vector-tile.example.com
.
Apache
If you prefer Apache over Nginx, then install Apache web server by using the following command.
sudo apt install apache2
To use Apache as a reverse proxy, we need to enable the proxy
modules and the header module.
sudo a2enmod proxy proxy_http headers
Then create a virtual host file for Tegola.
sudo nano /etc/apache2/sites-available/tegola.conf
Put the following configurations into the file. Replace vector-tile.example.com
with your actual domain name. Don’t forget to create DNS A record for this sub-domain. If you don’t have a real domain name, I recommend going to NameCheap to buy one. The price is low and they give whois privacy protection free for life.
<VirtualHost *:80>
ServerName vector-tile.example.com
ErrorDocument 404 /404.html
#HTTP proxy
ProxyPass / http://127.0.0.1:8080/
ProxyPassReverse / http://127.0.0.1:8080/
ProxyPreserveHost On
</VirtualHost>
Save and close the file. Then enable this virtual host.
sudo a2ensite tegola.conf
Restart Apache
sudo systemctl restart apache2
Now you can access Tegola using the domain name tile.example.com
.
Step 10: Enable HTTPS
To encrypt the HTTP traffic when you visit Tegola server from outside, we can enable HTTPS by installing a free TLS certificate issued from Let’s Encrypt. Run the following command to install Let’s Encrypt client (certbot) on Ubuntu 20.04.
sudo apt install certbot
If you use Nginx, then you also need to install the Certbot Nginx plugin.
sudo apt install python3-certbot-nginx
Next, run the following command to obtain and install TLS certificate.
sudo certbot --nginx --agree-tos --redirect --hsts --staple-ocsp --email [email protected] -d vector-tile.example.com
If you use Apache, then you need to install the Certbot Apache plugin.
sudo apt install python3-certbot-apache
Next, run the following command to obtain and install TLS certificate.
sudo certbot --apache --agree-tos --redirect --hsts --staple-ocsp --uir --email [email protected] -d vector-tile.example.com
Where:
--nginx
: Use the nginx plugin.--apache
: Use the Apache plugin.--agree-tos
: Agree to terms of service.--redirect
: Force HTTPS by 301 redirect.--hsts
: Add the Strict-Transport-Security header to every HTTP response. Forcing browser to always use TLS for the domain. Defends against SSL/TLS Stripping.--staple-ocsp
: Enables OCSP Stapling. A valid OCSP response is stapled to the certificate that the server offers during TLS.--uir
: upgrade insecure requests.
The certificate should now be obtained and automatically installed. And you can access Tegola via HTTPS: https://vector-tile.example.com
.
Set Up an Example Map
You need to use a third-party library in an HTML file to display vector tile-based map. Here are some common libraries you can use:
- Mapbox
- Maplibre: Open-source fork of Mapbox.
- OpenLayer
Mapbox
I created a map-mapbox.html
file, which you can access via https://www.linuxbabe.com/map-mapbox.html. Note that you need to use your own Mapbox access token. For how to use Mapbox GL JavaScript library, please check the official Mapbox guides and tutorials.
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Add a third party vector tile source</title> <meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no"> <link href="https://api.mapbox.com/mapbox-gl-js/v2.9.1/mapbox-gl.css" rel="stylesheet"> <script src="https://api.mapbox.com/mapbox-gl-js/v2.9.1/mapbox-gl.js"></script> <style> body { margin: 0; padding: 0; } #map { position: absolute; top: 0; bottom: 0; width: 100%; } </style> </head> <body> <div id="map"></div> <script> // TO MAKE THE MAP APPEAR YOU MUST // ADD YOUR ACCESS TOKEN FROM // https://account.mapbox.com mapboxgl.accessToken = 'pk.eyJ1IjoibGludXhiYWJlIiwiYSI6ImNsNHh2dTN5ZDAzajkzam8yamo3bWl4NDQifQ.zfb8pk0l2QV2SJpm-C4-Nw'; const map = new mapboxgl.Map({ container: 'map', style: 'mapbox://styles/mapbox/streets-v11', zoom: 5, center: [0.8, 55.0] }); map.on('load', () => { // Add a new vector tile source with ID 'linuxbabe'. map.addSource('linuxbabe', { 'type': 'vector', 'tiles': [ 'https://vector-tile.linuxbabe.com/maps/osm/{z}/{x}/{y}.pbf' ], 'minzoom': 6, 'maxzoom': 14 }); map.addLayer( { 'id': 'default', // Layer ID 'type': 'line', 'source': 'linuxbabe', // ID of the tile source created above // Source has several layers. We visualize the one with name 'sequence'. 'source-layer': 'sequence', 'layout': { 'line-cap': 'round', 'line-join': 'round' }, 'paint': { 'line-opacity': 0.6, 'line-color': 'rgb(53, 175, 109)', 'line-width': 2 } }, 'road-label' // Arrange our new layer beneath this layer ); }); map.addControl(new mapboxgl.NavigationControl()); </script> </body> </html>
Here’s how it looks:
To check if the map is using your own vector tile server, open the Developer Tools in Firefox (Ctrl+Alt+I), select the Network tab, press Reload button, then zoom in on the map. You will find that the web browser is requesting vector tiles from your own server.
Maplibre
I created a map-maplibre.html
file, which you can access via https://www.linuxbabe.com/map-maplibre.html. Note that you need to use your own Maptiler API Key. For how to use Maplibre GL JavaScript library, please check the official Maplibre guides.
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>vector tile map made with Tegola and Maplibre</title> <meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no"> <script src="https://unpkg.com/[email protected]/dist/maplibre-gl.js"></script> <link href="https://unpkg.com/[email protected]/dist/maplibre-gl.css" rel="stylesheet" /> <style> body { margin: 0; padding: 0; } #map { position: absolute; top: 0; bottom: 0; width: 100%; } </style> </head> <body> <div id="map"></div> <script> var map = new maplibregl.Map({ container: 'map', style: 'https://api.maptiler.com/maps/streets/style.json?key=5Wt1JU7PRdrMRzbqkJvG', zoom: 5, center: [0.8, 53.5] }); map.on('load', function () { // Add a new vector tile source with ID 'linuxbabe'. map.addSource('linuxbabe', { 'type': 'vector', 'tiles': [ 'https://vector-tile.linuxbabe.com/maps/osm/{z}/{x}/{y}.pbf' ], 'minzoom': 6, 'maxzoom': 14 }); map.addLayer( { 'id': 'default', // Layer ID 'type': 'line', 'source': 'linuxbabe', // ID of the tile source created above // Source has several layers. We visualize the one with name 'sequence'. 'source-layer': 'sequence', 'layout': { 'line-cap': 'round', 'line-join': 'round' }, 'paint': { 'line-opacity': 0.6, 'line-color': 'rgb(53, 175, 109)', 'line-width': 2 } }, ); }); map.addControl(new maplibregl.NavigationControl()); </script> </body> </html>
Here’s how it looks:
OpenLayer
Create a map.html
file on your server and put the following codes.
<!doctype html>
<html lang="en">
<head>
<link rel="stylesheet" href="https://openlayers.org/en/v5.3.0/css/ol.css" type="text/css">
<style>
#map{height:1000px;width:100%;background-color:#1C79B5;}
</style>
<script src="https://openlayers.org/en/v5.3.0/build/ol.js" type="text/javascript"></script>
<title>OpenLayers example</title>
</head>
<body>
<div id="map" class="map"></div>
<script type="text/javascript">
var defaultStyle = new ol.style.Style({
fill: new ol.style.Fill({
color: [234,231,221,1]
}),
stroke: new ol.style.Stroke({
color: [182,177,162,1],
width: 1
})
});
var waterStyle = new ol.style.Style({
fill: new ol.style.Fill({
color: [28,121,181,1]
}),
stroke: new ol.style.Stroke({
color: [27,107,159,1],
width: 1
})
});
var streetStyle = new ol.style.Style({
fill: new ol.style.Fill({
color: [111,44,173,1]
}),
stroke: new ol.style.Stroke({
color: [93,32,150,1],
width: 1
})
});
function styleFunction(feature, resolution){
if (feature.get('type') == 'water' || feature.get('layer') == 'water_areas' || feature.get('layer') == 'water_lines'){
return [waterStyle];
}
if (feature.get('layer') == 'transport_lines'){
return [streetStyle];
}
if (feature.get('layer') == 'country_polygons' || feature.get('layer') == 'landuse_areas'){
return null; // return null for no style to be applied
}
return [defaultStyle];
}
var map = new ol.Map({
target: 'map',
layers: [
new ol.layer.VectorTile({
source: new ol.source.VectorTile({
format: new ol.format.MVT(),
url:'https://vector-tile.linuxbabe.com/maps/osm/{z}/{x}/{y}.pbf'
}),
style:styleFunction
})
],
view: new ol.View({
center: ol.proj.fromLonLat([0.5,54.5]), //coordinates the map will center on initially
zoom: 6
})
});
</script>
</body>
</html>
Save and close the file. Here’s how it looks.
Pre-render Vector Tiles
A Vector tile server is already much faster than a raster tile server. If you want to furthur speed up map loading, you can pre-render the vector tiles. Run the following command as root.
/usr/local/bin/tegola cache seed --config /opt/tegola-osm/tegola.toml --bounds "-10,50,2,60" --min-zoom 0 --max-zoom 22
Sample output:
2022-06-30 04:55:37 [INFO] config.go:317: loading local config (/opt/tegola-osm/tegola.toml) 2022-06-30 04:55:37 [WARN] postgis.go:332: Connecting to PostGIS with connection parameters is deprecated. Use 'uri' instead. 2022-06-30 04:55:37 [INFO] providers.go:82: registering provider(type): osm (postgis) 2022-06-30 04:55:37 [WARN] postgis.go:332: Connecting to PostGIS with connection parameters is deprecated. Use 'uri' instead. 2022-06-30 04:55:37 [INFO] providers.go:82: registering provider(type): ne (postgis) 2022-06-30 04:55:37 [INFO] seed_purge.go:191: zoom list: [0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22] 2022-06-30 04:55:49 [INFO] worker.go:92: seeding map (osm) tile (4/7/4) took: 11639ms 2022-06-30 04:55:50 [INFO] worker.go:92: seeding map (osm) tile (2/1/1) took: 12708ms 2022-06-30 04:55:52 [INFO] worker.go:92: seeding map (osm) tile (4/7/5) took: 14093ms 2022-06-30 04:55:59 [INFO] worker.go:92: seeding map (osm) tile (2/2/1) took: 21279ms 2022-06-30 04:55:59 [INFO] worker.go:92: seeding map (osm) tile (3/3/2) took: 21785ms 2022-06-30 04:56:00 [INFO] worker.go:92: seeding map (osm) tile (1/0/0) took: 22286ms 2022-06-30 04:56:10 [INFO] worker.go:92: seeding map (osm) tile (4/8/4) took: 32075ms
The --bounds
option specifies the range of longitude and latitude. For UK and Ireland, the range is from -10° W longitude, 50° N latitude to 2° E longitude, 60° N latitude. You can find longitude and latitude ranges for each country on mapsofworld.com.
Troubleshooting PostgreSQL Error
Check PostgreSQL status:
sudo systemctl status [email protected]
If you encounter the following error.
FATAL: could not map anonymous shared memory: Cannot allocate memory
It means you allocated too much RAM to PostgreSQL shared_buffers
. Edit PostgreSQL config file.
sudo nano /etc/postgresql/14/main/postgresql.conf
Set shared_buffers
to a smaller value like 5GB.
shared_buffers = 5GB
Save and close the file. Then restart PostgreSQL.
sudo systemctl restart [email protected]
How to Upgrade PostgreSQL Database Server
When a new version of PostgreSQL comes out, you can upgrade to take advantage of performance improvements. Simply run the following command, and the apt package manager will install the latest version of PostgreSQL from the apt.postgresql.org
repository.
sudo apt update; sudo apt upgrade -y
After that, you also need to upgrade existing PostgreSQL clusters. Pro Tip: You should open a GNU Screen session to prevent connection drop because the upgrade will take sometime.
screen
Then list current clusters.
sudo pg_lsclusters
Sample output:
Ver Cluster Port Status Owner Data directory Log file
10 main 5432 online postgres /var/lib/postgresql/10/main /var/log/postgresql/postgresql-10-main.log
12 main 5433 online postgres /var/lib/postgresql/12/main /var/log/postgresql/postgresql-12-main.log
14 main 5434 online postgres /var/lib/postgresql/14/main /var/log/postgresql/postgresql-14-main.log
As you can see, PostgreSQL 10 is using the default 5432 port. PostgreSQL 12 is using port 5433 and PostgreSQL 14 is using port 5434. Stop PostgreSQL server.
sudo systemctl stop postgresql
Let’s check the cluster status again with: sudo pg_lsclusters
. They are all down.
Ver Cluster Port Status Owner Data directory Log file
10 main 5432 down postgres /var/lib/postgresql/10/main /var/log/postgresql/postgresql-10-main.log
12 main 5433 down postgres /var/lib/postgresql/12/main /var/log/postgresql/postgresql-12-main.log
14 main 5434 down postgres /var/lib/postgresql/14/main /var/log/postgresql/postgresql-14-main.log
Rename the cluster name of PostgreSQL 14 from main
to latest_stable
.
sudo pg_renamecluster 14 main latest_stable
Then we need to shrink the PostgreSQL shared_buffer.
sudo nano /etc/postgresql/10/main/postgresql.conf
Decrease the value to prevent out-of-memory problem during upgrade. For example, I reduce the value from 15GB
to 5GB
.
shared_buffers = 5GB
Save and close the file.
Next, upgrade the old PostgreSQL 10 cluster.
sudo pg_upgradecluster 10 main
Start PostgreSQL server.
sudo systemctl start postgresql
Now check if your application is working. If it’s working well, then drop the old cluster.
sudo pg_dropcluster 10 main
Check cluster status again:
sudo pg_lsclusters
If the upgrade is successful, you can change the shared_buffer
back to the original value in the /etc/postgresql/14/main/postgresql.conf
file. Don’t forget to restart PostgreSQL.
If the upgrade procedure can’t stop PostgreSQL,
pg_ctl: server does not shut down Error: Could not stop target cluster
then you need to run the following command to stop PostgreSQL.
pkill postgres
Then edit PostgreSQL 10 config file.
sudo nano /etc/postgresql/14/main/postgresql.conf
Set the listen port to 5432.
port = 5432
Save and close the file. Then start PostgreSQL 14.
sudo systemctl restart postgresql@14-main
Run the following command to make sure you can log into PostgreSQL console.
sudo -u postgres -i psql
Press Ctrl+D
to log out.
Restart Tegola.
sudo systemctl restart tegola
TileServer GL
TileServer GL is another open-source vector tile server that uses the OpenMapTiles schema.
Conclusion
I hope this article helped you set up Tegola Vector Tile Server on Ubuntu 20.04. As always, if you found this post useful, then subscribe to our free newsletter to get more tips and tricks. Take care 🙂
Nice tutorial man, I will have to try this one out.
Quick fix of a typo
# OpenStreetMap (OSM)
[[providers]]
name = “osm”
type = “postgis”
host = “127.0.0.1”
port = “5432”
database = “gis”
user = “osm”
password = “osm_password”
database should be osm instead of gis
Thanks, fixed the typo.
Great tutorial, can’t wait to try it this weekend. Thanks!
Setting up example map.
A little confused here, tegola is already running and nginx block is setup for reverse proxy, where does .html go?
You can put the .html file on any domain.
yup im up and running, nice guide.
can I ask, how can setup for viewing 3d buildings.
Very good tutorial ! Great job.
What about updating the data ? is there any “on the fly” way to do it ?
Sincerely,
Yann.
This step results in an error.
/opt/imposm/imposm import -connection postgis://osm:osm_password@localhost/osm -mapping /opt/tegola-osm/imposm3.json -read great-britain-latest.osm.pbf -write
It looks like tegola-osm made a change to their files.
This is correct:
/opt/imposm/imposm import -connection postgis://osm:osm_password@localhost/osm -mapping /opt/tegola-osm/imposm3-mapping.json -read great-britain-latest.osm.pbf -write