---
title: "Deploy Nominatim"
description: "OpenStreetMap geocoder turning addresses into coordinates and back"
category: "Other"
url: https://railway.com/deploy/nominatim
---

# Deploy Nominatim

OpenStreetMap geocoder turning addresses into coordinates and back

**[Deploy Nominatim on Railway](https://railway.com/template/nominatim)**

Machine-readable deploy manifest (JSON, validated by TemplateCI): https://railway.com/deploy/nominatim/manifest.json

- **Creator:** A3A
- **Category:** Other
- **Total deploys:** 1

## Template content

### nominatim https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons/svg/openstreetmap.svg

- **Source:** https://github.com/gridalpha/nominatim-railway
- **Health check:** /status
- **Public domain:** Yes

## Documentation

# Deploy and Host Nominatim on Railway

Nominatim is the geocoder behind search on openstreetmap.org. It turns a written address into coordinates and a pair of coordinates back into an address, using nothing but OpenStreetMap data and a PostgreSQL database you control. Mapping teams, logistics platforms and anyone tired of per-request billing from Google or Mapbox self-host Nominatim for unmetered geocoding with no API quota and no user addresses leaving their infrastructure.

Deploy Nominatim on Railway as a single `nominatim` service. It packages the Nominatim 5.3 API, the OSM importer and a PostgreSQL 16 database with PostGIS in one container, with the cluster on a Railway volume at `/var/lib/postgresql/16/main`. A Caddy front door serves nominatim-ui at `/ui/`, proxies every API route, and protects both with HTTP basic auth, because Nominatim ships no authentication of its own. The first deployment imports the extract named by `PBF_URL`; every later one finds the finished database on the volume and serves in seconds.

![Diagram of the single Nominatim service and its database volume on Railway](https://res.cloudinary.com/rroe4rtk/image/upload/f_auto,q_auto/v1789572163/nominatim-architecture.webp)

## Getting Started with Nominatim on Railway

The template defaults to the Monaco extract, so the first import finishes in under a minute — change `PBF_URL` before deploying if you want another region. The logs show the download, `osm2pgsql` loading it, the index ranks building, then `Starting Gunicorn`. Open the deployed URL: the browser asks for `API_USERNAME` and `API_PASSWORD`, then redirects to `/ui/`, the nominatim-ui search page. Type a place name that exists in your extract and press Search — a result card and a map marker confirm the import worked.

Click **details** on any result for the full OpenStreetMap record: every localised name, the address breakdown, the search and address ranks, and the computed postcode. The **Reverse** tab turns a coordinate pair into the nearest addressable feature. The same answers come back as JSON from `/search?q=...&format=jsonv2` and `/reverse?lat=...&lon=...&format=jsonv2`, which is what your application calls. `/status` is left unauthenticated for health checks and monitoring; it queries the database and reports the software version and the age of your data.

![Nominatim search for Casino de Monte-Carlo with the match on a map](https://res.cloudinary.com/rroe4rtk/image/upload/f_auto,q_auto/v1789572166/nominatim-search-results.webp)

![Nominatim place details listing every name, tag and rank](https://res.cloudinary.com/rroe4rtk/image/upload/f_auto,q_auto/v1789572168/nominatim-place-details.webp)

![Reverse geocoding a coordinate pair to Place du Casino](https://res.cloudinary.com/rroe4rtk/image/upload/f_auto,q_auto/v1789572173/nominatim-reverse-geocoding.webp)

## About Hosting Nominatim

Nominatim is a search engine built for OpenStreetMap's data model. Importing an extract is not a copy: `osm2pgsql` loads the raw OSM objects, then Nominatim derives a place hierarchy — country, state, county, city, suburb, street, house number — computes address interpolations, normalises names through an ICU tokenizer, and builds the indexes that let a free-text query resolve to one building.

Key capabilities:

- Forward geocoding, structured address search, and reverse geocoding from coordinates
- Polygons, bounding boxes, address breakdowns and per-language name variants
- Continuous replication of OpenStreetMap's own diffs, so your data stays current
- JSON, GeoJSON, GeoCodeJSON and XML output, compatible with existing Nominatim clients

The service holds three cooperating parts. PostgreSQL 16 with PostGIS stores the place table and its indexes on the volume. The Nominatim API runs under Gunicorn with uvicorn workers sized from the container's CPU quota. Caddy sits in front, serving nominatim-ui, proxying the API, and applying basic auth so the deployment is not an open geocoder for strangers. One caveat worth knowing: the optional Wikipedia and Wikidata importance tables are not imported, so forward search may prefer a less prominent match among identically named places. Reverse geocoding is unaffected.

## Why Deploy Nominatim on Railway

Railway removes the parts of self-hosting Nominatim that go wrong:

- One click provisions the container, the volume and the public domain
- The import runs on first boot and is skipped on every deploy afterwards
- PostgreSQL memory and worker counts are derived from your plan's limits
- The health check waits out a long first import instead of failing the deploy
- Basic auth and TLS are in place before the service is reachable

## Common Use Cases

- Address autocomplete and validation in a checkout or onboarding form, with no per-lookup fees
- Reverse geocoding fleet, delivery or asset telemetry into street addresses
- Batch-geocoding a customer database privacy rules forbid sending to a third party
- Backing an internal mapping tool where usage spikes make a metered geocoder unpredictable

## Dependencies for Nominatim

- `mediagis/nominatim:5.3` — the project's own container: Nominatim 5.3.2, PostgreSQL 16, PostGIS, `osm2pgsql`
- `nominatim-ui` 3.12.0 — the official web frontend, served from `/ui/`
- `caddy:2` — the front door providing basic auth and static file serving
- A Railway volume — where the PostgreSQL cluster and the imported data live

### Environment Variables Reference

| Variable | Purpose |
|---|---|
| `PBF_URL` | The OpenStreetMap extract to import on first boot |
| `API_USERNAME` / `API_PASSWORD` | HTTP basic auth credentials for the UI and API |
| `API_AUTH` | Set to `disabled` to serve anonymously |
| `NOMINATIM_PASSWORD` | Password for the internal PostgreSQL role |
| `REPLICATION_URL` | The `-updates/` directory beside your extract |
| `UPDATE_MODE` | `continuous`, `once`, `catch-up`, or unset to freeze the data |
| `THREADS` / `GUNICORN_WORKERS` | Import threads and API workers; default to the CPU quota |
| `REVERSE_ONLY` | Skip the search index for a smaller, reverse-only database |
| `IMPORT_STYLE` | `full`, `street`, `address` or `admin` — detail versus import speed |

### Deployment Dependencies

- Source repository: https://github.com/gridalpha/nominatim-railway
- Upstream project: https://github.com/osm-search/Nominatim
- Container project: https://github.com/mediagis/nominatim-docker
- Documentation: https://nominatim.org/release-docs/latest/
- Extracts: https://download.geofabrik.de/

## Hardware Requirements for Self-Hosting Nominatim

Requirements scale with the extract, not with traffic. The table covers a city or small-country extract.

| Resource | Minimum | Recommended |
|---|---|---|
| CPU | 2 vCPU | 4–8 vCPU (import is parallel) |
| RAM | 2 GB | 8 GB |
| Storage | 5 GB volume | ~10× the `.osm.pbf` size |
| Runtime | PostgreSQL 16 + PostGIS, Python 3 | same |

A country extract of a few hundred megabytes imports in tens of minutes and wants a volume in the tens of gigabytes. A whole-planet import needs roughly 1 TB of fast SSD.

## Self-Hosting Nominatim

To change region, point `PBF_URL` at any Geofabrik extract and redeploy onto an empty volume. For Great Britain:

```
PBF_URL=https://download.geofabrik.de/europe/great-britain-latest.osm.pbf
REPLICATION_URL=https://download.geofabrik.de/europe/great-britain-updates/
UPDATE_MODE=continuous
```

Query it from any HTTP client. The following uses curl with the basic-auth credentials:

```
curl -u "$API_USERNAME:$API_PASSWORD" \
  "https://your-app.up.railway.app/search?q=10+Downing+Street&format=jsonv2&limit=1"

curl -u "$API_USERNAME:$API_PASSWORD" \
  "https://your-app.up.railway.app/reverse?lat=51.5034&lon=-0.1276&format=jsonv2"
```

## How Much Does Nominatim Cost to Self-Host?

Nominatim is free and open source under GPL-2.0, and OpenStreetMap data is free under the ODbL. There is no paid tier, no seat count and no request quota — the only cost is the infrastructure, billed by Railway for the container's CPU, memory and volume. That is the appeal next to Google Geocoding, Mapbox or LocationIQ, which charge per request once a modest free allowance is gone. Attribution to OpenStreetMap contributors is required when you display results.

## FAQ

**What is Nominatim?**
Nominatim is the open-source geocoding engine behind OpenStreetMap's search box. It converts addresses and place names into coordinates, and coordinates back into addresses, from an OpenStreetMap extract loaded into PostgreSQL.

**What does this Railway template deploy?**
One service running Nominatim 5.3, PostgreSQL 16 with PostGIS and the nominatim-ui frontend, with a volume for the database and a Caddy front door adding HTTP basic auth. It imports the extract named by `PBF_URL` on first boot.

**Why does Nominatim need a volume instead of a managed database?**
Nominatim's importer initialises its own PostgreSQL cluster, installs PostGIS and a large body of PL/pgSQL, and tunes the server for a bulk load. Railway's managed Postgres has neither PostGIS nor those settings, so the database runs inside the service and persists on the volume.

**How do I geocode a different country or region?**
Point `PBF_URL` at another Geofabrik extract, set `REPLICATION_URL` to the matching `-updates/` directory, and deploy onto a fresh volume — the import only runs when the volume holds no database.

**How do I keep the OpenStreetMap data up to date?**
Leave `UPDATE_MODE=continuous` and `REPLICATION_URL` set. A background process applies OpenStreetMap's published diffs on the `REPLICATION_UPDATE_INTERVAL` schedule, and `/status` reports the newest data applied.

**Can I expose the API without a password?**
Yes — set `API_AUTH=disabled` and redeploy. Do that only if you mean to run a public geocoder, since an open endpoint is usable by anyone who finds the URL.


## Similar templates

- [Rocky Linux](https://railway.com/deploy/rocky-linux) — Hosted Rocky Linux 9 workspace with SSH and persistent storage. 🚀
- [Foundry Virtual Tabletop](https://railway.com/deploy/X5tR6G) — A Self-Hosted & Modern Roleplaying Platform
- [Letta Code Remote](https://railway.com/deploy/letta-code-remote) — Run a Letta Code agent 24/7. No inbound ports, just deploy.

Open this page in a browser: https://railway.com/deploy/nominatim
