A topographic server (or elevation server) exposes an HTTP API that returns the altitude of one or more GPS coordinates. It is typically used for:
-
the elevation profile (climb) of a route,
-
enriching GPX tracks,
-
slope computation / terrain analysis,
-
showing altitude in an application.
In this guide, we set up OpenTopoData, an open-source elevation API, with Docker, make it “production-friendly” with systemd, and go through dataset management (SRTM / EU-DEM).
OpenTopoData
1) Installation
Prerequisites
Install Docker.
OpenTopoData ships with a Docker image; it is the simplest and most reproducible path.
Getting the project and building the image
Clone, then build:
git clone https://github.com/ajnisbet/opentopodata.git
cd opentopodata/
make build
make run
-
make build: builds the Docker image -
make run: starts the container (optional, for a quick test)
Starting the server with Docker (direct command)
You can also start it without make run, straight from the CLI, mounting the data directory read-only:
docker run --rm -it --volume "/home/www/opentopodata/data:/app/data:ro" -p 5000:5000 opentopodata:`cat VERSION`
Explanation:
-
--volume "/home/www/opentopodata/data:/app/data:ro": makes your datasets available to the container -
-p 5000:5000: exposes the API on port 5000 -
opentopodata:`cat VERSION`: runs the tagged version matching the repository
Plan your own route
MapPlanner helps you calculate distances, elevation, duration and plan your hikes, runs and bike rides on an interactive map.
- Automatic distance & elevation calculation
- Topographic, satellite maps
- GPX/KML export for your GPS
- Real-time GPS tracking
2) Creating a systemd service (automatic startup)
The goal: run OpenTopoData as a service that restarts automatically and is managed with systemctl.
Create the service:
sudo nano /etc/systemd/system/elevation.service
Content:
[Unit]
Description=OpenTopoData elevation API
After=network.target
[Service]
Type=simple
User=deploy
Group=deploy
WorkingDirectory=/home/www/opentopodata
ExecStart=docker run --rm --volume '/home/www/opentopodata/data:/app/data:ro' --network host opentopodata:1.10.0
# if we crash, restart
TimeoutSec=30
Restart=on-failure
TimeoutStartSec=120
TimeoutStopSec=30
# output goes to the journal
StandardOutput=journal
StandardError=journal
SyslogIdentifier=opentopodata-elevation
[Install]
WantedBy=multi-user.target
Key points for the service to work:
-
pin the version (1.10.0)
-
do not use the
-tand-ioptions -
use the host network (
--network host) so the API can be called locally on port 5000; the-poption is then useless -
the service user must belong to the
dockergroup
Enable and start it:
sudo systemctl daemon-reload
sudo systemctl enable elevation.service
sudo systemctl start elevation.service
sudo systemctl status elevation.service
Alternative: installing without Docker
It can be installed without Docker:
https://www.opentopodata.org/notes/running-without-docker/
Performance is the same with or without Docker.
3) Choosing and configuring the topographic data
OpenTopoData supports several datasets. Two useful pages:
-
dataset list (public API):
https://www.opentopodata.org/ (§Public API) -
dataset sizes:
https://www.opentopodata.org/notes/dataset-sizes/
After adding data, the Docker image has to be rebuilt.
Datasets in use: history and current setup
In the current version, only SRTM30 data is used, for the whole world.
Previous setup:
-
Europe: EU-DEM
-
North America: SRTM30
-
Elsewhere: SRTM90
Comparing the data
-
SRTM30: the most precise data (2x slower than SRTM90)
-
SRTM90: approximate data (the fastest)
-
EU-DEM: 25 m, but less precise than SRTM30 (3x slower than SRTM90)
4) World: SRTM (SRTM30m / SRTM GL1)
OpenTopoData dataset (SRTM):
Create an account on OpenTopography:
Total size of the tif files: 126 GB.
The data sits on S3-compatible storage; to download it, first install aws-cli:
curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
unzip awscliv2.zip
sudo ./aws/install
Then, in the target directory:
aws s3 cp s3://raster/SRTM_GL1/ . --recursive --endpoint-url https://opentopography.s3.sdsc.edu --no-sign-request
The global VRT file is downloaded too (-32768 for areas without data).
Optimizing: converting to compressed GeoTIFF
If the files are not tif already (or to optimize I/O), convert them to compressed GeoTIFF:
Install GDAL:
sudo apt install gdal-bin
Conversion:
for f in *.hgt.zip; do gdal_translate -co COMPRESS=DEFLATE -co PREDICTOR=2 "$f" "${f%.*}.tif"; done
Cleanup:
rm *.zip
Time to generate the TIF files for North America: 30 min.
Deploying the data to the server and rebuilding
Copy the generated tif files to the server, update the config.yaml file and rebuild the Docker image:
make build
Restart the service:
sudo systemctl restart elevation.service
Test (if the server accepts local requests):
curl "http://localhost:5000/v1/srtm30m?locations=57.688709,11.97"
5) Europe: EU-DEM
OpenTopoData dataset (EU-DEM):
Download: since January 2024, EU-DEM is no longer distributed by Copernicus. The OpenTopoData page above says where to get a copy of the dataset.
Steps:
-
Download all the data at once
-
Extract all the files
-
Keep only the TIF files
Total size of the tif files: 38 GB.
Adding EU-DEM to OpenTopoData
In the opentopodata directory:
mkdir ./data/eudem
Copy the TIF files into it (rename them as described here: https://www.opentopodata.org/datasets/eudem/)
Create the config.yaml file declaring the dataset:
datasets:
- name: eudem25m
path: data/eudem/
filename_epsg: 3035
filename_tile_size: 1000000
Rebuild and restart the container:
make build && make run
Test (if the server accepts local requests):
curl "http://localhost:5000/v1/eudem25m?locations=57.688709,11.976404"
6) Getting a specific continent for SRTM
Reference:
Rename the file extension and prepend the URL to each line.