---
title: "Deploy Wanderer | (Just Updated) Self-Hosted Trail Database & GPS Route Planner, Ready to Use"
description: "Wanderer self-hosted trail database and GPS route planner, GPX upload API"
category: "Other"
url: https://railway.com/deploy/wanderer-or-just-updated-self-hosted-tra
---

# Deploy Wanderer | (Just Updated) Self-Hosted Trail Database & GPS Route Planner, Ready to Use

Wanderer self-hosted trail database and GPS route planner, GPX upload API

**[Deploy Wanderer | (Just Updated) Self-Hosted Trail Database & GPS Route Planner, Ready to Use on Railway](https://railway.com/template/wanderer-or-just-updated-self-hosted-tra)**

Machine-readable deploy manifest (JSON, validated by TemplateCI): https://railway.com/deploy/wanderer-or-just-updated-self-hosted-tra/manifest.json

- **Creator:** SuperSlowSloth
- **Category:** Other

## Template content

### db

- **Image:** flomp/wanderer-db:v0.21.2@sha256:2f8d7f29c2a473dce8e84b1a33ac3a692a21238c39b6757fa0e0162542d85865
- **Start command:** `/pocketbase serve --http=[::]:8090 --dir=/pb_data`

### web

- **Image:** flomp/wanderer-web:v0.21.2@sha256:849f63732d3e751f077c1567bda77aebc68c8b5691271cb418e10efbcf2f364f
- **Public domain:** Yes

### search

- **Image:** getmeili/meilisearch:v1.36.0@sha256:203a0854738be101bfdada825ac3cbf95e5681bc849757b6bc199e4cfae98faa
- **Start command:** `/bin/meilisearch --http-addr [::]:7700 --no-analytics`

## Documentation

# Deploy and Host Wanderer on Railway

**Built for an LLM agent to deploy and use.** The deploy form has no fields to fill: the search key, the proxy secret and the encryption key are all generated, and Wanderer lets a client create its own account over the REST API, so nobody opens a registration page first. Wanderer is a self-hosted trail database and GPS route planner: upload GPX tracks, browse them on a map with elevation, plan routes, keep lists, and share trails.

## About Hosting Wanderer

This template runs three services from the stock upstream images, pinned by digest: **web** (the SvelteKit app and REST API, the only public service), **db** (the PocketBase API with the trail files and users on a volume at `/pb_data`) and **search** (Meilisearch, with its index on a volume at `/meili_data`). The private services listen on both IPv4 and IPv6, so they answer on Railway's private network.

**Sign-up is open by default.** Upstream allows anyone to register, which is what lets an agent create its own account with no human step. To close it after you have created your accounts, add a `PUBLIC_DISABLE_SIGNUP` variable set to `true` on the `web` service and redeploy.

**What persists.** Users, trails, GPX files, photos and lists live on the `db` volume; the search index is rebuilt from it if the `search` volume is lost. The keys are stable variables, so redeploys keep sessions and stored data valid.

### Agent contract

- Public URL: `https://RAILWAY_PUBLIC_DOMAIN` (the generated domain of the `web` service)
- Private URL: `http://web.railway.internal:8080`
- Credentials: none are preset; the agent registers its own account (username, email and password are not template variables)
- Auth: `PUT /api/v1/user` creates the account, `POST /api/v1/auth/login` sets a `pb_auth` cookie to send on later requests; a write without that cookie answers `401`
- Health: `GET /` returns 200

```bash
# needs: SITE_URL (public https URL of the web service); also curl, sed, date
U="agent$(date +%s)"; P="Pw-$(date +%s%N)-Aa1"; JAR=$(mktemp); GPX=$(mktemp)
echo 'PD94bWwgdmVyc2lvbj0iMS4wIj8+PGdweCB2ZXJzaW9uPSIxLjEiIGNyZWF0b3I9ImFnZW50IiB4bWxucz0iaHR0cDovL3d3dy50b3BvZ3JhZml4LmNvbS9HUFgvMS8xIj48dHJrPjxuYW1lPkFnZW50IHRlc3QgdHJhaWw8L25hbWU+PHRya3NlZz48dHJrcHQgbGF0PSIzNS4zNjA2IiBsb249IjEzOC43Mjc0Ij48ZWxlPjEwMDA8L2VsZT48dGltZT4yMDI2LTAxLTAxVDAwOjAwOjAwWjwvdGltZT48L3Rya3B0Pjx0cmtwdCBsYXQ9IjM1LjM2NTAiIGxvbj0iMTM4LjczMDAiPjxlbGU+MTEwMDwvZWxlPjx0aW1lPjIwMjYtMDEtMDFUMDA6MTA6MDBaPC90aW1lPjwvdHJrcHQ+PHRya3B0IGxhdD0iMzUuMzcwMCIgbG9uPSIxMzguNzM1MCI+PGVsZT4xMjAwPC9lbGU+PHRpbWU+MjAyNi0wMS0wMVQwMDoyMDowMFo8L3RpbWU+PC90cmtwdD48L3Rya3NlZz48L3Ryaz48L2dweD4=' | base64 -d | dd of="$GPX" status=none
curl -s -o /dev/null -w "health: %{http_code}\n" "$SITE_URL/"
curl -s -o /dev/null -w "sign up: %{http_code}\n" -X PUT "$SITE_URL/api/v1/user" -H 'content-type: application/json' -d "{\"username\":\"$U\",\"email\":\"$U@example.com\",\"password\":\"$P\",\"passwordConfirm\":\"$P\"}"
curl -s -o /dev/null -w "log in: %{http_code}\n" -c "$JAR" -X POST "$SITE_URL/api/v1/auth/login" -H 'content-type: application/json' -d "{\"username\":\"$U\",\"password\":\"$P\"}"
curl -s -o /dev/null -w "write without key: %{http_code}\n" -X PUT "$SITE_URL/api/v1/trail/upload" -F "file=@$GPX"
curl -s -o /dev/null -w "write wrong key: %{http_code}\n" -X PUT "$SITE_URL/api/v1/trail/upload" -H 'Authorization: Bearer wanderer_key_wrong' -F "file=@$GPX"
ID=$(curl -s -b "$JAR" -X PUT "$SITE_URL/api/v1/trail/upload" -F "file=@$GPX" | sed -n 's/.*"id":"\([^"]*\)","iri".*/\1/p')
echo "trail created: $ID"
curl -s -b "$JAR" "$SITE_URL/api/v1/trail/$ID" | sed -n 's/.*"name":"\([^"]*\)".*/trail name: \1/p'; echo
curl -s -o /dev/null -w "trail delete: %{http_code}\n" -b "$JAR" -X DELETE "$SITE_URL/api/v1/trail/$ID"
rm -f "$JAR" "$GPX"
```

A fresh deploy prints `health: 200`, `sign up: 200`, `log in: 200`, `write without key: 401`, `write wrong key: 401`, a created trail id, `trail name: Agent test trail` and `trail delete: 200`.

## Why Deploy Wanderer on Railway?

Railway is a singular platform to deploy your infrastructure stack. Railway will host your infrastructure so you don't have to deal with configuration, while allowing you to vertically and horizontally scale it.

By deploying Wanderer on Railway, you are one step closer to supporting a complete full-stack application with minimal burden. Host your servers, databases, AI agents, and more on Railway.

- **Agent-ready** - no deployer fields, a contract block and one script that signs up, uploads a GPX trail and shows the refusal without a key.
- **Data survives redeploys** - the trail database and the search index each sit on a volume, and the secrets are stable.
- **Pinned** - all three images are pinned by digest.
- **Your trails stay yours** - tracks, photos and lists stay on your own service, with no third-party trail account.
- **Private services stay private** - the database and search have no public domain.

## Common Use Cases

- **Self-hosted trail database** - keep your hikes, rides and runs from GPX files in one searchable place.
- **GPS route planning** - plan routes on a map with elevation profiles and waypoints.
- **Shared trail lists** - publish lists of trails for a club or a trip.
- **Agent-driven trail logging** - an agent uploads GPX tracks and manages lists through the REST API.

## Dependencies for Wanderer Hosting

- Nothing outside the template: the database, the search and the web app are the three services. A custom domain is optional.

### Deployment Dependencies

- [Wanderer repository](https://github.com/Flomp/wanderer)
- [Wanderer documentation](https://wanderer.to)
- [Web image](https://hub.docker.com/r/flomp/wanderer-web)
- [Database image](https://hub.docker.com/r/flomp/wanderer-db)
- [Meilisearch](https://github.com/meilisearch/meilisearch)


## 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/wanderer-or-just-updated-self-hosted-tra
