Deploying GraphHopper
Introduction
GraphHopper is a fast and memory-efficient open-source routing engine that calculates routes, distances, travel times, and turn-by-turn instructions using OpenStreetMap data. Whether you need point-to-point routing, isochrone calculations, or mobile navigation, GraphHopper provides the foundation for building your own self-hosted mapping and navigation services.
Built in Java for cross-platform compatibility and performance, GraphHopper supports multiple transportation modes including car, bike, foot, and public transit. The engine can be used as a Java library or deployed as a standalone web server with a beautiful web interface.
Key highlights of GraphHopper:
- Fast Routing: Calculate routes in milliseconds, even for long distances
- Memory Efficient: Optimized data structures for minimal RAM usage
- Multiple Profiles: Support for car, bike, foot, motorcycle, and custom profiles
- Turn-by-Turn Instructions: Detailed navigation instructions for mobile apps
- Isochrone Calculation: Find areas reachable within a given time
- Snap to Road: Match GPS traces to the road network
- GTFS Support: Integrate public transit data
- Custom Models: Define custom routing behavior and road preferences
- Web Interface: GraphHopper Maps for visual route planning
- 100% Open Source: Licensed under Apache 2.0
This guide walks through deploying GraphHopper on Klutch.sh using Docker, importing OpenStreetMap data, and setting up your own routing API.
Why Deploy GraphHopper on Klutch.sh
Deploying GraphHopper on Klutch.sh provides several advantages for routing services:
Simplified Deployment: Klutch.sh automatically detects your Dockerfile and builds GraphHopper without complex orchestration. Push to GitHub and your routing server deploys automatically.
Persistent Storage: Attach persistent volumes for your map data and routing graphs. Pre-processed data survives container restarts.
HTTPS by Default: Klutch.sh provides automatic SSL certificates for secure API access.
GitHub Integration: Connect your configuration repository directly from GitHub. Updates trigger automatic redeployments.
Scalable Resources: Allocate CPU and memory based on your map coverage and expected query volume.
Custom Domains: Assign a custom domain for your routing API.
Always-On Availability: Your routing service remains accessible 24/7.
Prerequisites
Before deploying GraphHopper on Klutch.sh, ensure you have:
- A Klutch.sh account
- A GitHub account with a repository for your GraphHopper configuration
- OpenStreetMap data for your region (PBF format)
- Basic familiarity with Docker and containerization concepts
- Understanding of your geographic coverage needs
Understanding GraphHopper Architecture
GraphHopper consists of several components:
Routing Engine: Core Java engine that calculates optimal routes.
Graph Storage: Pre-processed road network stored as a graph structure.
Web Server: Jetty-based HTTP server exposing the routing API.
Web Interface: GraphHopper Maps for visual route planning and testing.
Import Process: Converts OSM data into an optimized routing graph.
Preparing Your Repository
To deploy GraphHopper on Klutch.sh, create a GitHub repository containing your Dockerfile and configuration.
Repository Structure
graphhopper-deploy/├── Dockerfile├── config.yml├── README.md└── .dockerignoreCreating the Dockerfile
Create a Dockerfile in the root of your repository:
FROM ghcr.io/graphhopper/graphhopper:latest
# Copy configuration fileCOPY config.yml /graphhopper/config.yml
# Set working directoryWORKDIR /graphhopper
# Create data directoryRUN mkdir -p /graphhopper/data
# Expose the web interface portEXPOSE 8989
# Default commandCMD ["java", "-Xmx2g", "-Xms1g", "-jar", "graphhopper.jar", "server", "config.yml"]Advanced Dockerfile with Custom Memory Settings
For larger map coverage:
FROM ghcr.io/graphhopper/graphhopper:latest
# Copy configurationCOPY config.yml /graphhopper/config.yml
WORKDIR /graphhopper
# Create data directoryRUN mkdir -p /graphhopper/data
# Set Java options via environmentENV JAVA_OPTS="-Xmx4g -Xms2g -XX:+UseG1GC"
# Health checkHEALTHCHECK --interval=60s --timeout=10s --start-period=300s --retries=3 \ CMD curl -f http://localhost:8989/health || exit 1
EXPOSE 8989
CMD ["sh", "-c", "java ${JAVA_OPTS} -jar graphhopper.jar server config.yml"]Creating the config.yml File
Create a GraphHopper configuration file:
graphhopper: # Data directory for graph storage graph.location: /graphhopper/data/graph-cache
# OSM file to import datareader.file: /graphhopper/data/region.osm.pbf
# Profiles for different transportation modes profiles: - name: car vehicle: car weighting: fastest turn_costs: true - name: bike vehicle: bike weighting: fastest - name: foot vehicle: foot weighting: shortest
# Enable CH (Contraction Hierarchies) for fast queries profiles_ch: - profile: car
# Enable LM (Landmarks) for flexible queries profiles_lm: - profile: car - profile: bike - profile: foot
# Server configuration server: application_connectors: - type: http port: 8989 bind_host: 0.0.0.0 admin_connectors: - type: http port: 8990 bind_host: localhost
# Import settings import: osm: ignored_highways: footway, cycleway, path, pedestrian, stepsCreating the .dockerignore File
Create a .dockerignore file:
.git.github*.mdREADME.mdLICENSE.gitignore*.log.DS_Store*.pbfgraph-cache/Configuration Options Reference
| Option | Description |
|---|---|
graph.location | Directory for the routing graph |
datareader.file | Path to OSM PBF file |
profiles | Available routing profiles |
profiles_ch | Profiles with Contraction Hierarchies |
profiles_lm | Profiles with Landmarks |
server.port | HTTP port for API |
Deploying GraphHopper on Klutch.sh
Once your repository is prepared, follow these steps to deploy GraphHopper:
- Select HTTP as the traffic type
- Set the internal port to 8989
- Detect your Dockerfile automatically
- Build the container image
- Attach the persistent volumes
- Start the GraphHopper container
- Provision an HTTPS certificate
Download OpenStreetMap Data
Download OSM data for your region from Geofabrik:
# Example: Download data for a small regionwget https://download.geofabrik.de/europe/monaco-latest.osm.pbfChoose a region appropriate for your needs. Larger regions require more memory and storage.
Push Your Repository to GitHub
Initialize your repository and push to GitHub:
git initgit add Dockerfile config.yml .dockerignore README.mdgit commit -m "Initial GraphHopper deployment configuration"git remote add origin https://github.com/yourusername/graphhopper-deploy.gitgit push -u origin mainCreate a New Project on Klutch.sh
Navigate to the Klutch.sh dashboard and create a new project. Give it a descriptive name like “graphhopper” or “routing-engine”.
Create a New App
Within your project, create a new app. Connect your GitHub account if you haven’t already, then select the repository containing your GraphHopper Dockerfile.
Configure HTTP Traffic
GraphHopper serves its API over HTTP. In the deployment settings:
Attach Persistent Volumes
Persistent storage is essential for GraphHopper. Add the following volume:
| Mount Path | Recommended Size | Purpose |
|---|---|---|
/graphhopper/data | 20+ GB | OSM data and routing graph cache |
Size depends on your region. Small country: 5-10 GB. Large country: 50+ GB.
Deploy Your Application
Click Deploy to start the build process. Klutch.sh will:
Upload OSM Data
After deployment, upload your OSM PBF file to the persistent volume at /graphhopper/data/region.osm.pbf.
Import the Data
GraphHopper will automatically import the data on first startup. This can take from minutes to hours depending on region size. Check logs for progress.
Access GraphHopper
Once import completes, access your GraphHopper instance at https://your-app-name.klutch.sh. The GraphHopper Maps interface allows visual route planning.
Using the Routing API
Basic Route Request
Calculate a route between two points:
curl "https://your-app-name.klutch.sh/route?point=52.5170,13.3889&point=52.5205,13.4094&profile=car"Route Response
The API returns JSON with route details:
{ "paths": [{ "distance": 1234.5, "time": 180000, "points": { ... }, "instructions": [ { "text": "Turn right onto Main Street", "distance": 100, "time": 12000 } ] }]}API Endpoints
| Endpoint | Description |
|---|---|
/route | Calculate route between points |
/isochrone | Calculate reachable area |
/match | Match GPS trace to roads |
/matrix | Calculate distance matrix |
/health | Health check endpoint |
Route Parameters
| Parameter | Description |
|---|---|
point | Coordinates (lat,lon). Repeat for multiple waypoints |
profile | Routing profile (car, bike, foot) |
locale | Language for instructions |
instructions | Include turn-by-turn instructions |
points_encoded | Use polyline encoding |
type | Response format (json, gpx) |
Isochrone Request
Calculate areas reachable within a time limit:
curl "https://your-app-name.klutch.sh/isochrone?point=52.5170,13.3889&profile=car&time_limit=600"Customizing Routing Profiles
Creating Custom Profiles
Define custom routing behavior in config.yml:
profiles: - name: truck vehicle: car weighting: fastest turn_costs: true
custom_models: truck: speed: - if: road_class == PRIMARY multiply_by: 0.8 - if: road_class == SECONDARY multiply_by: 0.7 priority: - if: max_weight < 7.5 multiply_by: 0Profile Options
| Option | Description |
|---|---|
vehicle | Base vehicle type (car, bike, foot) |
weighting | Optimization target (fastest, shortest) |
turn_costs | Consider turn restrictions |
custom_model | Apply custom routing rules |
Performance Optimization
Memory Configuration
Adjust Java heap size based on your region:
| Region Size | Recommended Heap |
|---|---|
| City | 1-2 GB |
| Small country | 2-4 GB |
| Large country | 4-8 GB |
| Continent | 8+ GB |
Contraction Hierarchies (CH)
Enable CH for fastest query performance:
profiles_ch: - profile: carCH pre-calculates shortcuts, reducing query time from seconds to milliseconds.
Landmarks (LM)
Enable LM for flexible queries with custom models:
profiles_lm: - profile: carLM allows runtime customization while maintaining reasonable performance.
Troubleshooting Common Issues
Import Takes Too Long
Symptoms: Data import runs for hours.
Solutions:
- Use a smaller region for testing
- Increase Java heap size
- Verify disk I/O performance
- Check for sufficient disk space
Out of Memory Errors
Symptoms: Application crashes with OOM errors.
Solutions:
- Increase Java heap size in Dockerfile
- Use a smaller region
- Enable disk-based storage with
graph.dataaccess=MMAP
Routing Fails for Some Points
Symptoms: Some coordinates return no route.
Solutions:
- Verify points are within the imported region
- Check that roads exist near the coordinates
- Try snapping to nearest road first
- Verify the profile supports the road types
Web Interface Not Loading
Symptoms: API works but maps don’t display.
Solutions:
- Check browser console for errors
- Verify HTTPS is working
- Clear browser cache
- Try a different browser
Additional Resources
- GraphHopper Website
- GraphHopper Documentation
- GraphHopper GitHub Repository
- Geofabrik OSM Downloads
- Klutch.sh Persistent Volumes
- Klutch.sh Deployments
Conclusion
Deploying GraphHopper on Klutch.sh gives you a powerful, self-hosted routing engine with full control over your map data. The combination of GraphHopper’s performance and Klutch.sh’s deployment simplicity means you can build navigation services without depending on third-party APIs.
With support for multiple transportation modes, isochrone calculations, and customizable routing profiles, GraphHopper provides the foundation for logistics applications, mobile navigation, and location-based services. Whether you’re building a delivery routing system or adding navigation to your mobile app, GraphHopper on Klutch.sh delivers fast, reliable routing on your infrastructure.