wanderer — a self-hosted trail database and GPS-track manager (a Strava/Komoot alternative): upload GPX tracks, browse them on a map, and search. Batteries-included: bundles Meilisearch and a PocketBase database. Deployed as a single host-networked Nomad service.
Needs nomad-pack on PATH. The script only adds the nomploy registry and runs this pack.
Source ↗ Project ↗ ★ 3.9k ⚑ Report an issue
Save as values.hcl, edit, then run:
# The name of the Nomad job.
job_name = "wanderer"
# The Nomad namespace to deploy into.
namespace = "default"
# The datacenters to deploy to.
datacenters = ["*"]
# The wanderer web image. Pin a tag in production (keep it in sync with db_image).
image = "flomp/wanderer-web:latest"
# The wanderer database (PocketBase) image. Keep its tag in sync with the web image.
db_image = "flomp/wanderer-db:latest"
# The Meilisearch image used for trail search.
meilisearch_image = "getmeili/meilisearch:v1.11.3"
# Host port for the wanderer web UI.
port = 3000
# Host port for the PocketBase database/API.
db_port = 8090
# Host port for the bundled Meilisearch (loopback only).
meili_port = 7700
# Public URL the web UI is reached at (ORIGIN). Empty = http://localhost:<port>. Set to your real host/domain.
base_url = ""
# Public URL the BROWSER uses to reach the database (PUBLIC_POCKETBASE_URL). Must be reachable from clients, e.g. http://your-host:8090. Empty = http://localhost:<db_port>.
pocketbase_url = ""
# Meilisearch master key (MEILI_MASTER_KEY), shared by the db and search engine. CHANGE THIS. Generate with: openssl rand -base64 36.
meili_master_key = "change-me-openssl-rand-base64-36"
# PocketBase settings encryption key (POCKETBASE_ENCRYPTION_KEY). MUST be exactly 32 characters. CHANGE THIS and keep it stable.
pocketbase_encryption_key = "0123456789abcdef0123456789abcdef"
# Named volume mounted at /pb_data — the PocketBase database and uploaded GPX/photos.
data_volume = "wanderer_data"
# Named volume for the Meilisearch index.
meili_data_volume = "wanderer_meili"
# Placement constraints. Pin to the node holding the volumes. On a nomploy cluster: attribute = "$${meta.nomploy_control_plane}", operator = "=", value = "true".
constraints = []
# Resources for the wanderer web task.
resources = {
cpu = 500
memory = 512
}
# Resources for the PocketBase database task.
db_resources = {
cpu = 300
memory = 256
}
# Resources for the Meilisearch task.
meilisearch_resources = {
cpu = 300
memory = 512
}
| Name | Type | Default | Description |
|---|---|---|---|
| job_name | string | "wanderer" | The name of the Nomad job. |
| namespace | string | "default" | The Nomad namespace to deploy into. |
| datacenters | list | ["*"] | The datacenters to deploy to. |
| image | string | "flomp/wanderer-web:latest" | The wanderer web image. Pin a tag in production (keep it in sync with db_image). |
| db_image | string | "flomp/wanderer-db:latest" | The wanderer database (PocketBase) image. Keep its tag in sync with the web image. |
| meilisearch_image | string | "getmeili/meilisearch:v1.11.3" | The Meilisearch image used for trail search. |
| port | number | 3000 | Host port for the wanderer web UI. |
| db_port | number | 8090 | Host port for the PocketBase database/API. |
| meili_port | number | 7700 | Host port for the bundled Meilisearch (loopback only). |
| base_url | string | "" | Public URL the web UI is reached at (ORIGIN). Empty = http://localhost:<port>. Set to your real host/domain. |
| pocketbase_url | string | "" | Public URL the BROWSER uses to reach the database (PUBLIC_POCKETBASE_URL). Must be reachable from clients, e.g. http://your-host:8090. Empty = http://localhost:<db_port>. |
| meili_master_key set me | string | "change-me-openssl-rand-base64-36" | Meilisearch master key (MEILI_MASTER_KEY), shared by the db and search engine. CHANGE THIS. Generate with: openssl rand -base64 36. |
| pocketbase_encryption_key key | string | "0123456789abcdef0123456789abcdef" | PocketBase settings encryption key (POCKETBASE_ENCRYPTION_KEY). MUST be exactly 32 characters. CHANGE THIS and keep it stable. |
| data_volume | string | "wanderer_data" | Named volume mounted at /pb_data — the PocketBase database and uploaded GPX/photos. |
| meili_data_volume | string | "wanderer_meili" | Named volume for the Meilisearch index. |
| constraints | list | [] | Placement constraints. Pin to the node holding the volumes. On a nomploy cluster: attribute = "$${meta.nomploy_control_plane}", operator = "=", value = "true". |
| resources | object | {
cpu = 500
memory = 512
} | Resources for the wanderer web task. |
| db_resources | object | {
cpu = 300
memory = 256
} | Resources for the PocketBase database task. |
| meilisearch_resources | object | {
cpu = 300
memory = 512
} | Resources for the Meilisearch task. |
No variables match.
This pack stores data in 2 Docker named volumes:
wanderer_meiliwanderer_data
⚠ This pack bundles a database. A cold copy of the volume can be inconsistent — for a reliable backup, dump the DB (pg_dump / mysqldump) or stop the job while backing up.
restic
# Run on the node hosting this pack. Point restic at your repo first: # export RESTIC_REPOSITORY="s3:https://<account>.r2.cloudflarestorage.com/<bucket>" # export RESTIC_PASSWORD="<repo-password>" # export AWS_ACCESS_KEY_ID=<key> AWS_SECRET_ACCESS_KEY=<secret> restic backup \ /var/lib/docker/volumes/wanderer_meili/_data \ /var/lib/docker/volumes/wanderer_data/_data
rclone (sync to S3/R2)
rclone sync /var/lib/docker/volumes/wanderer_meili/_data backup:<bucket>/wanderer_meili rclone sync /var/lib/docker/volumes/wanderer_data/_data backup:<bucket>/wanderer_data
Paths assume the default Docker volume location (/var/lib/docker/volumes). Restore by stopping the job, restoring files into the same volume, and re-running the pack.
wanderer — a self-hosted trail database and GPS-track manager: upload GPX/FIT tracks, view them on interactive maps with elevation profiles, tag and search your routes, and share them. A privacy-friendly Strava/Komoot alternative for planning and archiving your hikes, rides and runs.
This pack is batteries-included: a single host-networked group running three tasks —
/pb_data).nomad-pack registry add nomploy https://github.com/Nomploy/nomad-packs
nomad-pack run wanderer --registry=nomploy
| Variable | Default | Description |
|---|---|---|
port |
3000 |
Web UI port. |
db_port |
8090 |
PocketBase database/API port (must be browser-reachable). |
base_url |
"" |
Public URL of the web UI (ORIGIN). Empty = http://localhost:<port>. |
pocketbase_url |
"" |
Set for real use. Browser-reachable DB URL (PUBLIC_POCKETBASE_URL), e.g. http://your-host:8090. |
meili_master_key |
change-me-… |
Change this. Shared by the db and Meilisearch. |
pocketbase_encryption_key |
0123… |
Change this (exactly 32 chars) and keep it stable. |
data_volume |
wanderer_data |
/pb_data — database and uploads. |
meili_data_volume |
wanderer_meili |
the search index. |
image / db_image / meilisearch_image |
… | Pin the web and db images to the same wanderer version. |
resources / db_resources / meilisearch_resources |
… | Per-task resources. |
pocketbase_urlmust be reachable from browsers (it's baked into the frontend), so for anything beyond localhost set it to your real host/domain and port8090(andbase_urlto the web URL). All three tasks share the host network, so pin the job to the node holding the volumes withconstraints. The first account you register becomes the admin.