Skip to content
Go back

OsmAnd + Self-Hosted Tiles, Offline

By SumGuy 11 min read
OsmAnd + Self-Hosted Tiles, Offline
Contents

Your Phone Shrugs. OsmAnd Does Not.

You’re three miles into a trail that probably has a name but definitely doesn’t have cell signal. You pull out your phone. Google Maps shows a cheerful “you are here” dot surrounded by a gray void. Apple Maps says something similar but with slightly better kerning. The trail you’re standing on, the one with actual dirt, actual elevation gain, actual switchbacks, does not exist as far as either of them is concerned.

OsmAnd, on the other hand, has the trail. It has the contour lines. It has the creek crossing, the junction marker, and the distance to the next waypoint. All of it sitting in local storage, no signal required. Because you downloaded the regional vector map before you left the house, like a person who has made this mistake before.

That’s the short version of why OsmAnd exists. The longer version gets into privacy, offline routing, self-hosted tile servers, and a UI that looks like it was designed by someone who wanted to expose every possible option simultaneously. We’ll cover all of it.

Full example: Tile server side + OsmAnd tile-source XML at github.com/KingPin/sumguy-examples/tree/main/self-hosting/osmand-self-hosted-tiles-offline

What OsmAnd Actually Is

OsmAnd (OpenStreetMap Automated Navigation Directions) is an open-source maps and navigation app built on OpenStreetMap data. It runs on Android and iOS. The Android version is available on F-Droid (completely free, no limitations) and Google Play (free tier with map download limits; OsmAnd+ is a one-time paid unlock for the full feature set). iOS has OsmAnd Maps on the App Store.

The core feature is offline vector maps. Download a regional .obf file (OsmAnd’s binary format) directly in the app, and the map renders locally, no remote tile fetches, no internet required. Covers the full OSM dataset: roads, trails, POIs, elevation contours, transit lines, building outlines, addresses.

By default, OsmAnd requires no account, has no login screen, ships with analytics disabled, and never asks for your email. Location data stays on the device.

If you open the Play Store reviews you’ll find complaints that the UI is overwhelming. That’s fair. OsmAnd’s settings menu has more options than most enterprise software. That’s also why it can do: offline routing with multiple algorithms, custom map styles, GPX trip recording, nautical charts, ski resort maps, Wikipedia POI overlays, and custom raster tile sources from your own server.

Swiss Army knife with all the blades extended simultaneously. You get used to it.

Why Privacy Matters Here

Every time you open Google Maps, it knows where you are. Every search, every navigation request logged against your account. Same with Apple Maps, though Apple’s story is somewhat better. The business model around maps is knowing where people go.

OsmAnd breaks that chain. Combined with a self-hosted tile server, you get a complete maps stack where zero location data leaves your network. Tile server serves raster images. Routing calculates locally. Search indexes locally. The only outbound request is something like Wikipedia POIs, which you can turn off.

That sounds like paranoia until you consider who benefits from location data. Surveillance-aware travel, countries where your route history could be legally problematic, real use cases, not hypotheticals. For most home lab people the argument is simpler: you already self-host your photos, passwords, and calendar. Why hand your location to Google?

Step 1, Offline Vector Maps (The Easy Default)

Before we talk about self-hosted tile servers, let’s get the basic offline maps working. This is the part you actually need. The tile server is a nice enhancement. The offline vector maps are the whole reason OsmAnd exists.

Open OsmAnd → tap the hamburger menu → Download maps → navigate to your region.

You’ll see a list of countries, then states or regions within each country. Tap the download icon next to what you need. A typical US state is 200 to 400 MB. Western Europe countries run 500 MB to 2 GB. The map downloads in the background and is immediately available offline after.

A few things worth knowing:

That’s it. Offline maps working. For hikes, travel, or anywhere signal is unreliable, this alone is everything you need.

Step 2, Custom Raster Tiles From Your Own Server

The offline vector maps are OsmAnd’s native format, rendering locally from the .obf file. The custom tile source approach works differently: instead of downloading vector data once, OsmAnd fetches raster tile images from a URL on demand, caching them locally as they’re viewed. Point that URL at your own server instead of a public CDN, and you control the whole pipeline.

Why would you want this? A few reasons:

The server side is straightforward. Here’s a minimal Compose stack using Tileserver-GL, which serves MBTiles or PMTiles files as raster or vector tiles:

docker-compose.yml
services:
tileserver:
image: maptiler/tileserver-gl:latest
container_name: tileserver
ports:
- "8080:80"
volumes:
- ./tiles:/data
command: --config /data/config.json
restart: unless-stopped

Put your .mbtiles or .pmtiles file in ./tiles/ and a minimal config.json:

config.json
{
"options": {
"paths": {
"root": "/data"
}
},
"data": {
"osm-bright": {
"mbtiles": "your-region.mbtiles"
}
}
}

Download regional MBTiles from openmaptiles.org or generate them with tilemaker from a Geofabrik PBF. Same data source as the vector maps, different format for raster serving.

Once the server is running, it exposes a tile endpoint at:

http://your-server-ip:8080/data/osm-bright/{z}/{x}/{y}.png

Verify it works by hitting that URL with a real tile coordinate in a browser: /{z}/{x}/{y} with something like /12/1234/567.png. If you see a map tile image, the server is healthy.

The OsmAnd Tile Source Format

OsmAnd uses an XML format for custom online tile sources. You create this file, import it into OsmAnd, and it shows up as a selectable map source. The format is specific and the whitespace matters more than you’d expect:

sumguy-tiles.xml
<?xml version="1.0" encoding="utf-8"?>
<item>
<name>SumGuy Tile Server</name>
<url_template>http://192.168.1.100:8080/data/osm-bright/{0}/{1}/{2}.png</url_template>
<min_zoom>1</min_zoom>
<max_zoom>19</max_zoom>
<tile_size>256</tile_size>
<img_density>1</img_density>
<avg_img_size>18000</avg_img_size>
<ellipsoid>false</ellipsoid>
<inverted_y>false</inverted_y>
<time_to_live>3600</time_to_live>
</item>

The URL template uses {0} for zoom, {1} for X, {2} for Y, not the {z}/{x}/{y} format you’re used to from web mapping. OsmAnd’s own convention. Get this wrong and the tiles either won’t load or will load in the wrong position.

time_to_live is in seconds. 3600 means OsmAnd re-fetches a tile after an hour. Set this higher if your map data changes slowly. 86400 (24h) is fine for static regional tiles. Set it to 0 to disable expiry entirely if you want pure offline caching after the first load.

Save this as sumguy-tiles.xml on your phone. Then in OsmAnd:

Map → Configure Map → Map Source → + (add) → Import from file

Select your XML file. The source appears in the list immediately. Switch to it and pan around your region to populate the local cache while you’re still on WiFi.

Caching: Tile Storage on a 128 GB Phone

Once the tile source is set up, OsmAnd fetches tiles on demand as you pan, storing them in a local SQLite cache, different from the bulk offline vector downloads. Manage the limit under Settings → OsmAnd settings → Storage.

Practical sizing: z1 to z17 coverage of a mid-sized region can hit a few GB in raster tiles. Set a 2 to 4 GB cache limit. That covers a full trip’s area without eating your storage.

Pre-caching workflow before a trip:

  1. Connect to home WiFi with Tileserver-GL running
  2. Open OsmAnd with your custom tile source selected
  3. Pan the area you’ll travel through at zoom levels 10 to 16
  4. Let it fill, repeat for route corridors
  5. Leave WiFi. Cached tiles serve locally until time_to_live expires

Set time_to_live to 0 in the XML and tiles never expire. Perfect for remote trips where you want the cache to hold indefinitely.

Routing on the Phone

Offline map tiles are great. Offline routing is what makes navigation actually work without a connection.

OsmAnd ships with its own built-in offline routing engine. Enable it under Settings → Navigation settings → Route parameters → Routing typeOsmAnd (offline). It reads the .obf vector map locally and handles car, bicycle, pedestrian, and boat routing, no network required.

For serious outdoor use, OsmAnd integrates with BRouter, a dedicated offline engine optimized for cycling, hiking, and mixed terrain. We covered it in the BRouter offline routing post. Short version: install BRouter, download routing segments for your region, configure OsmAnd to use BRouter as its engine. You get profiles that weight for trail surface, grade, and waypoint snapping, things the built-in engine doesn’t expose.

City driving and casual navigation: built-in engine is fine. Elevation, trail types, cycling surfaces: BRouter is worth the extra setup.

Who Actually Needs This

The full setup, self-hosted tile server plus OsmAnd with offline vector maps, serves a few distinct audiences:

Hikers and outdoor people. Offline maps that work without signal are not optional in the wilderness. OsmAnd with downloaded regional vectors covers this, no tile server required. Add the tile server if you want terrain-shaded or custom-styled imagery alongside the vector layer.

Travelers in expensive data regions. International roaming is still stupidly priced in a lot of places. Download maps at home, cache tiles on hotel WiFi, navigate the whole trip without touching data.

Surveillance-aware travelers. If you’re going somewhere where you’d prefer your location data not be logged by a US tech company, a fully local stack is the answer. Phone, on-device routing, self-hosted tiles on your VPN/LAN. Location data stays on your hardware.

Home lab people who are just annoyed. Honestly, this is most of the audience. You’ve already got a server. You already resent handing personal data to companies that treat it as inventory. Setting up Tileserver-GL is an afternoon of work and then you have your own maps stack indefinitely.

The Honest Trade-Off

OsmAnd’s UI is busy. There’s no polite way to say this. The main menu alone has eleven top-level sections. The map configuration panel has options nested three levels deep for things you will never need and options you desperately want hidden behind a toggle you found by accident.

Google Maps is better-looking and faster to use for the simple “get me to this restaurant” case. If that’s all you need, Google Maps is the correct answer. Go use it.

The deal with OsmAnd is that the complexity is the feature. Every one of those settings panel items corresponds to something you can actually control. The privacy defaults are reasonable out of the box. The offline capability is complete, not a stripped-down “offline mode” that stops working at zoom 14. The data source is OSM, which means you can contribute corrections if something’s wrong. The custom tile source support means you can wire it to your own server without jailbreaking anything.

It’s the difference between renting a tool and owning one. Ownership involves maintenance and a learning curve. In exchange, nobody else holds the keys.

For the hike where you’re out of signal range and the trail is actually on the map, it’s not even a close call.

Wrapping Up

Two things to get working, in order of priority:

  1. Download regional vector maps in OsmAnd. Free, offline, works without a server. Do this even if you stop here.
  2. Add your tile server as a custom raster source. Import the XML, cache the tiles on WiFi, use them everywhere.

The Compose stack and the OsmAnd XML are both in the sumguy-examples repo. Drop your .mbtiles file in, edit the IP in the XML, and you’re there.

Your phone knows where you are. It doesn’t have to tell anyone else.


Share this post on:

Send a Webmention

Written about this post on your own site? Send a webmention and it'll show up above once verified.


Next Post
Synthetic Browser Monitoring with Playwright + Grafana

Discussion

Powered by Garrul . Sign in with GitHub or Google, or post anonymously.

Related Posts