Show HN: Offline tiles and routing and geocoding in one Docker Compose stack
102 points| packet_mover | 1 month ago |corviont.com
I’m building Corviont, a self-hosted offline maps appliance (tiles + routing + search) for edge/on-prem devices.
Hosted demo (no install): https://demo.corviont.com/
Self-host (Docker Compose repo): https://github.com/corviont/monaco-demo
Docs: https://www.corviont.com/docs
What’s inside:
- Vector tiles served locally (PMTiles)
- Routing served locally (Valhalla)
- Offline geocoding/search + reverse (SQLite Nominatim-based index)
- MapLibre UI wired to the local endpoints
After the initial image + data pulls, it runs fully offline (no external map/routing/geocoding API calls).Next (if people need it): a signed on-device updater for regional datasets (verify → atomic swap → reload).
I’d love feedback: where offline maps/routing/search matters for you, and what constraints bite (hardware, fleet size, update windows, regions, deployment style).
oakhaven|1 month ago
Why not create a "builder" repo, where people could generate their own local datasets by a bounding box?
packet_mover|1 month ago
Re: a bbox "builder" repo - it's an interesting idea. I could see it going two ways: (a) you want to run a bbox builder yourself, or (b) you want a simple way to specify a bbox so the dataset pack can be produced for you.
I started with the "ship a known-good pack" approach because the build pipeline is the messy part, and I want deployed boxes to stay simple/reproducible.
For your use case, which did you mean - run the build locally, or "draw/paste a bbox and get back a ready-to-run pack"? And would bbox be OK, or do you prefer admin boundaries (country/state/city)?
mike_d|1 month ago
If you read the bottom of the page they plan to sell it. Not sure how that works when all the software/data is open.
onaclov2000|1 month ago
I've played around with OSRM, and Nominatim, etc, but had to do some trickery to run on a raspberry pi.
(For anyone interested in running some of these kind of things on a pi, I talk about it generally here, I need to post an update with more info at some point. http://blog.onaclovtech.com/2025/02/general-purpose-to-speci...)
packet_mover|1 month ago
One goal of Corviont is to avoid the on-device pain you hit with OSRM/Nominatim: the region pack is built once elsewhere, and the edge box mostly just serves prebuilt artifacts (PMTiles tiles, Valhalla routing tiles, and a SQLite geocoder index based on Nominatim).
In practice, requirements scale with region size and traffic. For larger regions the main constraint is usually SSD storage plus enough RAM headroom for routing/cache. I also picked Valhalla partly because it generally has a smaller RAM footprint than OSRM at serving time (OSRM is extremely fast but tends to be more memory-hungry).
tomaskafka|1 month ago
If I may have a feature request, I’d like to have only some of the features turned on - in my case it would be just the reverse geocoder (so I could skip the map and routing data download and storage).
Right now I have my own reverse geocoder for https://weathergraph.app which downloads OSM dumps and builds in-memory KD tree for lookups. Surprisingly, the whole world can fit in 3-4 GB of RAM, and service starts in 90 seconds on a cheap VPS, no database needed, but of course, having a battle tested solution that just works (and someone else maintains it) would help.
packet_mover|1 month ago
Re: Weathergraph - thanks for the details. Since you already run whole-world reverse geocoding on a single server, that's a bit different from Corviont's current regional/fleet packaging (where you ship only the area you need to each edge/on-prem deployment). A "world geocoder-only" pack could still make sense - but it's a different distribution/update story than my default.
For your use case, do you want reverse results at the city/region/country level - or do you also need street/house number detail? That choice mostly determines how heavy a world geocoder-only pack needs to be.
bikelang|1 month ago
michaelt|1 month ago
The algorithms do divide the map up into chunks that are themselves divided up and so on, but not on the strict geographical basis a quadtree uses. You might not want to divide Manhattan in two for routing purposes, even if the 74th longitude line runs straight through it.
[1] https://turing.iem.thm.de/routeplanning/hwy/esaHwyHierarchie... [2] https://publikationen.bibliothek.kit.edu/1000028701/14297392...
packet_mover|1 month ago
FWIW, Valhalla already does a version of this: it partitions the routing graph into hierarchical tiles and runs with multiple hierarchy levels (highway / arterial / local) specifically to keep search + in-memory working set smaller on long routes: https://valhalla.github.io/valhalla/tiles/
The "quadtree tile unlock" mental model is a nice way to think about it though - if you have a favorite paper / implementation that leans harder into the tiling aspect, I’d love a pointer. I’m currently focused on packaging + offline data consistency, but routing performance on constrained edge boxes is definitely a core constraint I care about.
krapht|1 month ago
dabreegster|1 month ago
packet_mover|1 month ago
One place Corviont is trying to differentiate is the update story for edge/fleet deployments: the goal is a signed, resumable regional dataset updater (verify manifest -> atomic swap -> reload/rollback) so boxes in the field can stay fresh without manual rebuilds or "re-download the world" updates. Headway (at least from a quick skim) looks more like "bring your own data / regenerate when needed," which is totally fine for servers, but fleets usually need something more automated.
If you've seen Headway (or similar) handle incremental/regional updates well, I'd love to learn from it - updater design is the big missing piece I'm validating demand for.
leros|1 month ago
I ask because I've been looking to self host some sort of map tile server and they seem to have database in the hundreds of GB.
packet_mover|1 month ago
Also it’s not one giant tile DB - there are 3 datasets:
For Monaco all three are tiny - you can see the exact files here: https://github.com/corviont/monaco-demo/tree/main/dataFor small countries like Austria/Slovakia, each is typically hundreds of MB.
KomoD|1 month ago
Maptiler has a bunch of datasets, anywhere from 385MB to 527GB but the OSM dataset is only 70GB. (MBTiles format)
willi59549879|1 month ago
packet_mover|1 month ago
Right now the offline geocoder in the demo does place/street-level search + reverse, but street + house number ("Main St 12") isn't supported yet. It's explicitly on the near-term roadmap: richer geocoding output with house numbers and (optionally) street/area geometry instead of just centerpoints.
Natfan|1 month ago
packet_mover|1 month ago
If you have 1-2 concrete suggestions on what makes it feel that way (copy/layout/typography), I am happy to improve it.