Tile38
Overview
Tile38 is an open-source geospatial database and realtime geofencing server. It keeps points, polygons, bounding boxes and GeoJSON objects in memory, indexes them spatially, and answers proximity, containment and intersection queries in microseconds. It also watches objects in motion and pushes enter, exit, cross and inside events to endpoints you nominate.
This SecureAnyCloud image installs Tile38 1.38.0 as a hardened systemd service with append-only persistence. It secures the server with a password that is unique to your VM and generated on first boot.
What you get:
- Tile38 1.38.0 server at
/usr/local/bin/tile38-serverand the matching client at/usr/local/bin/tile38-cli - One multiplexed port,
9851, serving the Redis RESP protocol, HTTP and WebSocket - A 48-character password generated on first boot and written into Tile38's own config before the server ever listens
- Append-only persistence at
/var/lib/tile38/appendonly.aof tile38.servicerunning as the unprivilegedtile38user- 24/7 SecureAnyCloud support
Prerequisites
You need an active Azure subscription, an SSH key, and a VNet with a subnet.
Standard_B2s is the recommended size for development and evaluation. Scale up for larger datasets, because Tile38 holds its working set in memory.
Tile38 listens on 0.0.0.0:9851, but your network security group governs who can reach it. The image does not open port 9851 for you. Add an inbound rule scoped to the application hosts that need it, and never open it to the whole internet.
Deploy and connect
Deploy the image from the Azure Marketplace, then connect over SSH as azureuser.
ssh azureuser@<vm-ip>Confirm that the service came up. ExecStartPre is a fail-closed gate that refuses to start Tile38 unless a per-VM password is present. When it exits 0/SUCCESS, the server is authenticated.
sudo systemctl status tile38.service --no-pagerYou should see Active: active (running), the ExecStartPre line reporting status=0/SUCCESS, and the server running with -d /var/lib/tile38 -h 0.0.0.0 -p 9851 --appendonly yes.
Retrieve your password
Every VM built from this image generates its own password on first boot. Nothing is shared between VMs, and nothing is baked into the image. Read the password from the credentials file:
sudo cat /stage/scripts/tile38-credentials.logThe file is mode 0600, owned by root, and records TILE38_PASSWORD, TILE38_HOST, TILE38_PORT and TILE38_URL.
Confirm that the listener is bound:
sudo ss -tlnp | grep 9851Confirm the server is authenticated
Tile38 answers four commands without a password: PING, ECHO, healthz and OUTPUT. All four are no-ops that read no data and no configuration. healthz is the liveness probe:
curl -sS http://127.0.0.1:9851/healthzEvery command that touches data or configuration is refused. Verify this with a real command rather than PING:
curl -sS 'http://127.0.0.1:9851/KEYS+*'
curl -sS 'http://127.0.0.1:9851/SET+probe+p1+POINT+1+1'Both return {"ok":false,"err":"authentication required"}. If either returns "ok":true, the server is not secured. Stop and contact support.
Now authenticate. Over HTTP, send the password in the Authorization header as the raw value, with no Bearer prefix:
PASS=$(sudo grep '^TILE38_PASSWORD=' /stage/scripts/tile38-credentials.log | cut -d= -f2-)
curl -sS -H "Authorization: $PASS" http://127.0.0.1:9851/SERVERThe response contains "ok":true and "version":"1.38.0", along with live statistics for objects, points, collections and heap size.
Store and query geospatial data
Tile38 organises objects into collections. SET writes an object, NEARBY finds objects within a radius, WITHIN finds objects inside a bounding box or polygon, and SCAN reads a whole collection. Over HTTP, the command and its arguments form the URL path, separated by +.
Write two points, then query them back:
PASS=$(sudo grep '^TILE38_PASSWORD=' /stage/scripts/tile38-credentials.log | cut -d= -f2-)
curl -sS -H "Authorization: $PASS" 'http://127.0.0.1:9851/SET+fleet+truck1+POINT+51.5007+-0.1246'
curl -sS -H "Authorization: $PASS" 'http://127.0.0.1:9851/SET+fleet+truck2+POINT+51.5033+-0.1195'
curl -sS -H "Authorization: $PASS" 'http://127.0.0.1:9851/NEARBY+fleet+POINT+51.5007+-0.1246+1000'NEARBY returns both trucks as GeoJSON, with a count of 2:
{"ok":true,"objects":[{"id":"truck1","object":{"type":"Point","coordinates":[-0.1246,51.5007]}},{"id":"truck2","object":{"type":"Point","coordinates":[-0.1195,51.5033]}}],"count":2,"cursor":0}Note the coordinate order. Tile38 takes POINT <latitude> <longitude> on input and returns GeoJSON, which is [longitude, latitude].
The bundled client reads the password from the TILE38_PASSWORD environment variable and issues AUTH for you. It has no password flag:
PASS=$(sudo grep '^TILE38_PASSWORD=' /stage/scripts/tile38-credentials.log | cut -d= -f2-) TILE38_PASSWORD="$PASS" tile38-cli -h 127.0.0.1 -p 9851 SCAN fleet TILE38_PASSWORD="$PASS" tile38-cli -h 127.0.0.1 -p 9851 GET fleet truck1To get an interactive prompt, run tile38-cli with no trailing command.
Realtime geofencing
A geofence is a standing query. Register one with SETHOOK, and Tile38 pushes an event to your endpoint the moment an object enters, exits or crosses the fence. Your application never has to poll.
The example below registers a fence named warehouse that watches the fleet collection within 500 metres of a point, then lists and removes it. Replace the endpoint with a URL that your own service listens on:
PASS=$(sudo grep '^TILE38_PASSWORD=' /stage/scripts/tile38-credentials.log | cut -d= -f2-)
curl -sS -H "Authorization: $PASS" 'http://127.0.0.1:9851/SETHOOK+warehouse+http://127.0.0.1:9999/hook+NEARBY+fleet+FENCE+POINT+51.5007+-0.1246+500'
curl -sS -H "Authorization: $PASS" 'http://127.0.0.1:9851/HOOKS+*'
curl -sS -H "Authorization: $PASS" 'http://127.0.0.1:9851/DELHOOK+warehouse'Hook endpoints can be HTTP, gRPC, Redis, Kafka, NATS, RabbitMQ, MQTT or Amazon SQS. Use DETECT to narrow which transitions fire, for example DETECT enter,exit.
For a live feed instead of a webhook, open a WebSocket to the same port and issue a FENCE query on it.
Components
These are the files and paths that make up the Tile38 installation:
- Server binary: /usr/local/bin/tile38-server
- Client binary: /usr/local/bin/tile38-cli
- Data directory: /var/lib/tile38/
- Config (holds the password): /var/lib/tile38/config (mode 0600)
- Append-only file: /var/lib/tile38/appendonly.aof
- Systemd unit: /etc/systemd/system/tile38.service
- Auth gate: /usr/local/sbin/tile38-require-auth.sh
- First-boot script: /usr/local/sbin/tile38-firstboot.sh
- Credentials: /stage/scripts/tile38-credentials.log (mode 0600)
Check the server version and list the data directory:
tile38-server --version sudo ls -la /var/lib/tile38/Security
- Scope the network security group. Port 9851 carries the whole database. Allow it only from the application subnets that need it, and never from
0.0.0.0/0. Restrict SSH equally. - Keep the password out of shell history. Read it into a variable from the credentials file, as every example above does, rather than typing it inline.
- Rotate the password. Connect with the current password and run
CONFIG SET requirepass <new-password>, thenCONFIG REWRITE. Update your clients and record the new value in your own secret store. - Terminate TLS in front of Tile38. The server speaks plaintext, so put it behind a TLS-terminating proxy, or keep it on a private subnet reachable only over a VPN or peering.
- Know which commands are unauthenticated.
PING,ECHO,healthzandOUTPUTanswer without a password. They expose only liveness, so they are safe for a load balancer probe, but they are not an authentication test. - Patch regularly. Unattended security upgrades are enabled in this image. Apply kernel updates and reboot on your own maintenance schedule.
Support and licensing
Tile38 is MIT licensed and free to use. SecureAnyCloud provides commercial support for this image separately.
- Email: sales@secureanycloud.com
- Support hours: 24/7, with a one-hour average response for critical issues
Deploy on Azure
Launch Tile38 with 24/7 support from SecureAnyCloud. View on Marketplace.
Deploy on Azure
Launch Tile38 on Ubuntu 24.04 LTS on Azure with 24/7 support from SecureAnyCloud.
View this image
Need Help?
Our support team is available 24/7.
sales@secureanycloud.com