Cloudflare Integration
Installation
1. Upload to R2
Uploading via Web UI is limited to 300 MB.
Use rclone to upload larger PMTiles archives to R2 (you can use the rclone/rclone
docker image in order to avoid installation, the config is at /etc/rclone
for mounting). This requires a token from R2 > Manage R2 API Tokens. Note Access Key ID, the Secret Access Key and the Endpoint for S3 Clients from the API key creation screen. Run the following commands:
rclone config
and follow the on screen questions, the endpoint should look like:https://<ACCOUNT_ID>.r2.cloudflarestorage.com
rclone copyto <FILE> <rclone configuration name>:<BUCKET_NAME>/<FILE> --progress --s3-no-check-bucket --s3-chunk-size=256M
to upload to the root of the bucket.
Name your uploads to storage with the .pmtiles
extension. Your tile requests to the Workers URL will look like /NAME/0/0/0.<mvt | png>
for the archive NAME.pmtiles
.
2. Create Worker with Web Console
In the Workers left menu of the Cloudflare dashboard, choose Create Worker.
It will ask you to deploy it first before you can edit the code, click Deploy.
Edit Code and paste the bundled index.js from PMTiles/serverless/cloudflare.
Leave the default HTTP handler option.
Choose Save and Deploy and leave the code editing window.
Select the newly created worker from the Workers list.
In Settings of your worker, choose Variables > R2 Bucket Bindings > Add Binding.
Create a variable named
BUCKET
and select your R2 bucket from Step 1.Choose Save and Deploy.
Your worker should now be active at its *.workers.dev
domain.
Make a request for <ACCOUNT_NAME>.workers.dev/<FILENAME>/0/0/0.<mvt | png>
to verify tiles are served.
Alternative: Use Wrangler
Clone the PMTiles repository and change to the
serverless/cloudflare
directory.npm install
inPMTiles/js
to get the dependencies of the core JS libraryAlso
npm install
inPMTiles/serverless/cloudflare
Copy
wrangler.toml.example
towrangler.toml
Edit
wrangler.toml
, replacingbucket_name
with your bucket.Publish the worker:
npm run deploy
3. Create Worker Route
For the cache to work, the worker must be assigned a zone on your own domain, not workers.dev
.
In Triggers for your Worker, Add Custom Domain e.g.
subdomain.mydomain.com
. This will create a DNS entry in your Cloudflare site.In Routes, Assign the route
subdomain.mydomain.com/*
to your worker. This directs traffic to the above subdomain to this specific worker.
Verify your deployment is working by checking for the Cf-Cache-Status
header with a value of HIT
on tile requests. This may take 2-3 attempts.
Example with curl
for vector tiles and TileJSON:
curl -v https://subdomain.mydomain.com/FILENAME/0/0/0.mvt
curl -v https://subdomain.mydomain.com/FILENAME.json
curl -v https://subdomain.mydomain.com/FILENAME/0/0/0.mvt
curl -v https://subdomain.mydomain.com/FILENAME.json
Configuration
Optional environment variables can be set set in [vars]
of wrangler.toml
or in the Workers web console.
PMTILES_PATH
- A string likefolder/{name}.pmtiles
specifying the path to archives in your bucket. Default{name}.pmtiles
DeprecatedTILES_PATH
- a string likeprefix/{name}/{z}/{x}/{y}.{ext}
specifying the tile path exposed by the worker. Default{name}/{z}/{x}/{y}.{ext}
PUBLIC_HOSTNAME
- Optional, override the absolute hostname in TileJSON responses. Exampletiles.example.com
ALLOWED_ORIGINS
- a comma-separated list of allowed CORS origins. Default none. Examples:https://example.com,https://localhost:3000
,*
CACHE_MAX_AGE
: max age in the Cloudflare cache, in seconds. default 86400, or 1 day.
Cost Estimate
- Cloudflare Workers is $5 USD per month with 10 million requests a month included, plus $0.50 per additional million.
- Cloudflare R2 incurs costs for storage, write requests and read requests. These will only happen on tile cache misses. See the Cost Calculator for estimates based on usage.
Cache Invalidation
- For Cloudflare, "Purge Cache" applies to all cached resources in the zone (domain). It's recommended to deploy on a dedicated zone for this reason.