Configuration
Tileserver RS uses a TOML configuration file to define tile sources, styles, and server settings.
Configuration File
Create a config.toml file. Note that root-level options (fonts, files) must come before any [section] headers due to TOML parsing rules:
# Root-level options (must come before [sections])
fonts = "/data/fonts"
files = "/data/files"
[server]
host = "0.0.0.0"
port = 8080
cors_origins = ["*"]
[telemetry]
enabled = false
# endpoint = "http://localhost:4317"
# metrics_enabled = true
# metrics_export_interval_secs = 60
[[sources]]
id = "openmaptiles"
type = "pmtiles"
path = "/data/tiles.pmtiles"
name = "OpenMapTiles"
attribution = "© OpenMapTiles © OpenStreetMap contributors"
[[sources]]
id = "terrain"
type = "mbtiles"
path = "/data/terrain.mbtiles"
name = "Terrain Data"
[[styles]]
id = "osm-bright"
path = "/data/styles/osm-bright/style.json"
fonts and files must appear before any section headers ([server], [telemetry], etc.) in the TOML file. Otherwise they will be incorrectly parsed as part of the preceding section.Server Configuration
| Option | Description | Default |
|---|---|---|
host | IP address to bind to | 0.0.0.0 |
port | Port number | 8080 |
cors_origins | Allowed CORS origins | ["*"] |
Source Configuration
File-based sources (PMTiles, MBTiles) are configured in [[sources]] arrays. PostgreSQL sources are configured separately in [postgres].
Each file source requires:
| Option | Description | Required |
|---|---|---|
id | Unique identifier | Yes |
type | pmtiles or mbtiles | Yes |
path | Path to tile file (local or URL) | Yes |
name | Display name | No |
attribution | Map attribution | No |
PMTiles Sources
[[sources]]
id = "world"
type = "pmtiles"
path = "/data/world.pmtiles"
# Or from a URL (requires http feature)
# path = "https://example.com/tiles.pmtiles"
MBTiles Sources
[[sources]]
id = "local-data"
type = "mbtiles"
path = "/data/local.mbtiles"
PostgreSQL Configuration
postgres feature flag when building from source.Configure PostgreSQL connection and sources in the [postgres] section:
[postgres]
connection_string = "postgresql://user:pass@localhost:5432/tiles"
pool_size = 20
# Table sources (recommended - auto-generates optimized SQL)
[[postgres.tables]]
id = "points"
table = "my_points"
geometry_column = "geom"
minzoom = 0
maxzoom = 14
# Function sources (for custom SQL logic)
[[postgres.functions]]
id = "custom_tiles"
function = "get_tiles"
minzoom = 0
maxzoom = 14
Connection Options
| Option | Description | Default |
|---|---|---|
connection_string | PostgreSQL connection URL | Required |
pool_size | Maximum connections | 20 |
ssl_cert | Path to SSL certificate | - |
ssl_key | Path to SSL key | - |
ssl_root_cert | Path to SSL root certificate | - |
Table Sources
Table sources auto-discover geometry columns and generate optimized tile queries with spatial index filtering.
[[postgres.tables]]
id = "buildings"
schema = "public"
table = "buildings"
geometry_column = "geom" # Optional, auto-detected
id_column = "id" # Optional, for feature IDs
properties = ["name", "type"] # Optional, defaults to all columns
minzoom = 0
maxzoom = 14
bounds = [-180, -85, 180, 85] # Optional, auto-detected
extent = 4096 # MVT extent (default: 4096)
buffer = 64 # Tile buffer in pixels (default: 64)
max_features = 10000 # Optional feature limit per tile
| Option | Description | Default |
|---|---|---|
id | Unique source identifier | Required |
schema | PostgreSQL schema | public |
table | Table name | Required |
geometry_column | Geometry column name | Auto-detected |
id_column | Column for feature IDs | - |
properties | Columns to include | All non-geometry columns |
minzoom | Minimum zoom level | 0 |
maxzoom | Maximum zoom level | 22 |
bounds | Bounds [west, south, east, north] | Auto-detected |
extent | MVT tile extent | 4096 |
buffer | Tile buffer in pixels | 64 |
max_features | Max features per tile | Unlimited |
Function Sources
Function sources call PostgreSQL functions that return MVT tiles directly.
[[postgres.functions]]
id = "dynamic_tiles"
schema = "public"
function = "get_tiles"
minzoom = 0
maxzoom = 14
bounds = [-180, -85, 180, 85]
The function must have one of these signatures:
-- Simple (z, x, y)
CREATE FUNCTION get_tiles(z integer, x integer, y integer)
RETURNS bytea AS $$ ... $$ LANGUAGE plpgsql;
-- With query parameters (z, x, y, query)
CREATE FUNCTION get_tiles(z integer, x integer, y integer, query json)
RETURNS bytea AS $$ ... $$ LANGUAGE plpgsql;
| Option | Description | Default |
|---|---|---|
id | Unique source identifier | Required |
schema | PostgreSQL schema | public |
function | Function name | Required |
minzoom | Minimum zoom level | 0 |
maxzoom | Maximum zoom level | 22 |
bounds | Bounds [west, south, east, north] | - |
Table vs Function Sources
| Aspect | Table Source | Function Source |
|---|---|---|
| Setup | Minimal config | Requires SQL function |
| Performance | Optimized (uses spatial index) | Depends on function |
| Flexibility | Fixed schema | Custom SQL logic |
| Use case | Standard tables | Complex queries, joins |
Style Configuration
[[styles]]
id = "bright"
path = "/data/styles/bright/style.json"
name = "Bright Style" # Optional display name
Styles should include sprites alongside the style.json:
styles/
└── bright/
├── style.json
├── sprite.json
├── sprite.png
├── [email protected]
└── [email protected]
Font Configuration
Fonts are required for rendering text labels. Configure the fonts directory:
fonts = "/data/fonts"
The fonts directory should contain subdirectories for each font family with PBF glyph files:
fonts/
├── Noto Sans Regular/
│ ├── 0-255.pbf
│ ├── 256-511.pbf
│ └── ...
├── Noto Sans Medium/
│ ├── 0-255.pbf
│ └── ...
└── Open Sans Bold/
└── ...
Static Files Configuration
Optionally serve static files from a directory:
files = "/data/files"
Files in this directory will be accessible at /files/{filepath}. This is useful for:
- GeoJSON overlays
- Custom marker icons
- Other static assets
Telemetry Configuration
tileserver-rs supports OpenTelemetry for exporting traces and metrics via OTLP gRPC.
[telemetry]
enabled = true
endpoint = "http://localhost:4317"
service_name = "tileserver-rs"
sample_rate = 1.0
metrics_enabled = true
metrics_export_interval_secs = 60
| Option | Description | Default |
|---|---|---|
enabled | Enable OpenTelemetry (traces + metrics) | false |
endpoint | OTLP gRPC collector endpoint | http://localhost:4317 |
service_name | Service name for traces and metrics | tileserver-rs |
sample_rate | Trace sampling rate (0.0 to 1.0) | 1.0 |
metrics_enabled | Enable metrics export (requires enabled = true) | true |
metrics_export_interval_secs | How often metrics are pushed to the collector | 60 |
When enabled, the following metrics are exported:
| Metric | Type | Unit | Description |
|---|---|---|---|
http.server.request.count | Counter | requests | Total HTTP requests |
http.server.request.duration | Histogram | seconds | Request duration |
http.server.response.body.size | Histogram | bytes | Response body size |
Each metric includes attributes: http.request.method, http.response.status_code, url.path.
See the Telemetry Guide for setup examples with Grafana, Jaeger, and other backends.
Environment Variables
| Variable | Description | Default |
|---|---|---|
RUST_LOG | Log level (error, warn, info, debug, trace) | info |
CONFIG_PATH | Path to config file | config.toml |
HOST | Override server host | - |
PORT | Override server port | - |
CLI Options
tileserver-rs --help
Options:
-c, --config <FILE> Path to configuration file [default: config.toml]
-h, --host <HOST> Override server host
-p, --port <PORT> Override server port
-v, --verbose Enable verbose logging
--help Print help
--version Print version