District registry and geo-proximity service for the Hydra infrastructure. Manages district definitions, service endpoints, and geographic coordinates.
| Server | hydradistrict.experiencenet.com (46.224.179.9) |
| hcloud | hydraexperiencenet context, cx23 nbg1 |
| Config | /root/.hydradistrict/config.yaml |
| Data | /root/.hydradistrict/ |
| Service | systemctl status hydradistrict |
| Logs | journalctl -u hydradistrict -f |
| Health | GET /api/v1/health |
curl -s https://hydradistrict.experiencenet.com/api/v1/health
The response includes the district count:
{
"service": "hydradistrict",
"status": "ok",
"district_count": 3
}
All mutating endpoints require a bearer token in the Authorization header. Read endpoints (GET) are unauthenticated.
| Method | Path | Auth | Description |
|---|---|---|---|
| GET | /api/v1/health |
no | Service health and district count |
| GET | /api/v1/runbook |
no | This runbook (rendered as Markdown) |
| GET | /api/v1/events |
yes | SSE stream of district events |
| GET | /api/v1/districts |
no | List all districts (supports ?provider= filter) |
| GET | /api/v1/districts/{id} |
no | Get a single district by ID |
| GET | /api/v1/districts/{id}/services |
no | Get service URL map for a district |
| POST | /api/v1/districts |
yes | Create a district |
| PUT | /api/v1/districts/{id} |
yes | Update a district |
| DELETE | /api/v1/districts/{id} |
yes | Delete a district |
| GET | /api/v1/nearest |
no | Find nearest district by ?lat=&lon= |
curl -X POST https://hydradistrict.experiencenet.com/api/v1/districts \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"id": "eu-nbg1",
"name": "EU Nuremberg",
"location": "Nuremberg, Germany",
"latitude": 49.45,
"longitude": 11.08,
"provider": "hetzner",
"services": [
{"type": "cluster", "url": "https://hydracluster.experiencenet.com"},
{"type": "venues", "url": "https://hydravenues.experiencenet.com"}
]
}'
curl -s https://hydradistrict.experiencenet.com/api/v1/districts | jq .
Filter by provider:
curl -s "https://hydradistrict.experiencenet.com/api/v1/districts?provider=hetzner" | jq .
curl -s https://hydradistrict.experiencenet.com/api/v1/districts/eu-nbg1 | jq .
curl -X PUT https://hydradistrict.experiencenet.com/api/v1/districts/eu-nbg1 \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"name": "EU Nuremberg",
"location": "Nuremberg, Germany",
"latitude": 49.45,
"longitude": 11.08,
"provider": "hetzner"
}'
curl -X DELETE https://hydradistrict.experiencenet.com/api/v1/districts/eu-nbg1 \
-H "Authorization: Bearer <token>"
Returns a map of service type to URL for the district. No auth required.
curl -s https://hydradistrict.experiencenet.com/api/v1/districts/eu-nbg1/services | jq .
Example response:
{
"district_id": "eu-nbg1",
"services": {
"cluster": "https://hydracluster.experiencenet.com",
"venues": "https://hydravenues.experiencenet.com"
}
}
Requires coordinates with geo-data set on at least one district. Returns the closest district and the distance in kilometers.
curl -s "https://hydradistrict.experiencenet.com/api/v1/nearest?lat=50.85&lon=4.35" | jq .
Example response:
{
"district": { "id": "eu-bxl1", "name": "EU Brussels", ... },
"distance_km": 12.3
}
HydraDistrict is a Go service (Cobra CLI, systemd) backed by a YAML store with no database dependency.
Data layout on disk:
/root/.hydradistrict/
config.yaml # server config
districts.yaml # index of all districts
districts/
<id>/
district.yaml # full district record
certs/ # autocert TLS cache
Writes are atomic: all YAML files are written to a .tmp file and renamed into place, so a crash mid-write never leaves a partially written file.
Events: on every create, update, or delete the service emits an SSE event (district.created, district.updated, district.deleted) via hydramonitor. Other services subscribe on GET /api/v1/events.
Auto-updates: the service polls releases.experiencenet.com every 6 hours and applies any newer version automatically. Releases are triggered by pushing a v* tag to GitHub, which runs CI, builds cross-platform binaries, and uploads them to the release server. Setting HYDRA_AUTO_UPDATE=off disables the poll entirely — the container image sets it, because there the image is the unit of update and there is no systemd unit to restart.
Container image: the same v* tag also builds a multi-arch (linux/amd64 + linux/arm64) OCI image and pushes it to scaleregistry.experiencenet.com/hydradistrict:<tag> and :latest. The image runs serve --dev --listen :8080 (plain HTTP, TLS terminated upstream) and carries no VOLUME directive: persistence must be attached as an Incus disk device (or a Docker bind mount) at /root/.hydradistrict, pre-staged with a config.yaml containing at least server.admin_token — the service refuses to start without it.
TLS: autocert issues and renews certificates automatically for hydradistrict.experiencenet.com. The certificate cache lives in /root/.hydradistrict/certs/.
ssh root@46.224.179.9 systemctl status hydradistrict
ssh root@46.224.179.9 journalctl -u hydradistrict -f
Show last 100 lines:
ssh root@46.224.179.9 journalctl -u hydradistrict -n 100 --no-pager
ssh root@46.224.179.9 systemctl restart hydradistrict
ssh root@46.224.179.9 hydradistrict version
Never deploy manually. Use the release pipeline:
git tag v<X.Y.Z>git push origin v<X.Y.Z>hydrarelease verify --project hydradistrictcurl -s https://hydradistrict.experiencenet.com/api/v1/healthssh root@46.224.179.9systemctl status hydradistrictjournalctl -u hydradistrict -n 50 --no-pagersystemctl restart hydradistrictjournalctl -u hydradistrict -n 50 --no-pagercat /root/.hydradistrict/config.yamlss -tlnp | grep 443ls -la $(which hydradistrict)hydradistrict serveIf the YAML store becomes corrupted (partial writes, disk issues):
systemctl stop hydradistrictls -la /root/.hydradistrict/cat /root/.hydradistrict/districts.yamlls /root/.hydradistrict/districts/systemctl start hydradistrictcat /root/.hydradistrict/config.yamlssh root@46.224.179.9 dateserver.admin_token in config and restart the serviceThe nearest endpoint only considers districts that have non-zero latitude and longitude values. If it returns 404, either no districts have coordinates set or the store is empty. Set coordinates via the update endpoint (see API Endpoints above).
Hetzner automated daily server snapshots are enabled on hydradistrict (46.224.179.9), context hydraexperiencenet. Backup window: 06:00-10:00 UTC, 7-day retention.
The snapshot covers the entire server disk, including all district YAML files, the TLS certificate cache, and the service configuration.
hydraexperiencenet project), open Servers -> hydradistrict -> Backups.curl -s https://hydradistrict.experiencenet.com/api/v1/health
curl -s https://hydradistrict.experiencenet.com/api/v1/districts | jq length