azavea / tilegarden

Serverless raster and vector map tile generation using Mapnik and AWS Lambda
https://azavea.github.io/tilegarden/
Other
98 stars 7 forks source link
aws aws-lambda claudiajs gis mapnik serverless tileserver

tilegarden :world_map::sunflower: Build Status

Contents

About

Tilegarden is a serverless tile-rendering tool using Mapnik, built for AWS Lambda. Serve custom-generated map tiles without having to worry about server maintenance, scaling, or paying for resources that aren't being accessed.

Usage

Deployment to AWS

A deployed instance of Tilegarden consists of several AWS resources:

  1. An AWS Lambda function which handles the tiling logic.
  2. An API Gateway API that acts as an endpoint and routes HTTP requests to the lambda function.
  3. A CloudFront distribution that acts as a proxy in order to circumvent some issues that API Gateway has serving image content.

    • Specify your map in a map configuration file and place it in src/tiler/src/config/ (where you can find pre-existing examples). A full specification for Carto's .mml format can be found here.
    • Specify your production credentials and lambda function settings in .env. The following variables are required:
    • AWS_PROFILE: the name of the AWS user profile you want to deploy your project as. You may have this set already in your environment, otherwise you'll want to set it to one of the names of the sets of credentials specified in ~/.aws/credentials. Defaults to “default”.
    • PROJECT_NAME: the name of your project. This must be unique among the functions you currently have deployed to AWS Lambda.
    • PROD_TILEGARDEN_*: the credentials necessary to connect to your production database.
    • LAMBDA_REGION: the AWS region to which you want your lambda functions deployed.
    • LAMBDA_ROLE: the name/ARN of the IAM role to give your lambda. Leave this blank to have one created for you automatically.
    • LAMBDA_SUBNETS and LAMBDA_SECURITY_GROUPS: only required if you need to connect to other AWS resources (such as an RDS instance), in which case these should match the values that those resources have.
    • See below for more options.
    • See below to make sure your AWS profile has the requisite permissions for automated deployment.
    • Run ./scripts/deploy --new to create new instances of the necessary AWS resources.
    • Updates to an existing project can be deployed by running ./scripts/deploy (no “--new”). Note that only certain function settings (LAMBDA_TIMEOUT and LAMBDA_MEMORY) are updated by this command, changes to IAM Role/subnets/security groups/etc. must be made manually on the AWS dashboard.
    • All deployed resources can be removed by running ./scripts/destroy.

Additional Configuration Options

Required AWS Permissions

The AWS profile used for deployment must have at least the following policies and permissions:

Features

Configuration Selection and Storage

Multiple map configuration .xml files can be included in your project's src/tiler/src/config to be dynamically loaded at run-time. Use the config path parameter with the name of your configuration file (without the file extension) to select which file gets loaded when rendering tiles.

Datasources

Tilegarden supports the use of any geospatial data source that Mapnik/Carto does (shapefile, postgis, pgraster, raster). However, bear in mind that only PostGIS data sources support custom queries, and are thus the only ones that allow you to perform additional filtering on your data (see Filters). Also, attempting to bundle large local data files into your Tilegarden deployment could lead to rejection by AWS Lambda due to size restrictions.

Map Styles

Map styles are specified in CartoCSS, the specification for which can be found here. The default stylesheet is located at src/tiler/src/config/style.mss. Multiple stylesheets can be used by adding them to the parameter “Stylesheet” in src/tiler/src/config/map-config.mml. Each .mss “class” refers to a map layer (its “id” property), specified in map-config.mml.

Filters

Filtering your geospatial data can be done in two ways:

Custom Layer Queries

Filters can be specified on the back-end by altering the query of one of your map's layers in src/tiler/src/config/map-config.mml, and can then be fetched through the API. To create a filtered layer, modify the “table” property of the layer to have the format (QUERY) as VARIABLE.

Layers can be accessed from the API by adding ?layers=["layer1","layer2",etc.] (a valid JSON array)as a query string to a tile or UTF grid URL. If no layers are specified in the query string, all layers specified in map-config.mml are displayed simultaneously.

Client-specified Filtering

Layers can also be filtered dynamically by passing a JSON object as a value of a layer in the ?layers array. The schema for this sort of request looks like the following:

[
    {
        "name":"layer1",
        "mode": "AND" // optional, operator to use to combine filters, can either be AND or OR, defaults to AND
        "filters": [ // optional, applies no filters if missing
            {
                "col":"column1", // table column you wish to filter by
                "val":"value1", // value to filter on
                "op": ">" // optional, boolean operator to use when comparing col to val, = by default
            }
        ]
    }
]

The resulting url would have the query string ?layers=[{"name":"layer1","filters":[{"col":"column1","val":"value1","like": true}]}]. Filtering layers in this way appends WHERE col='val' to the existing query defined for the layer. Defining multiple filters in the "filters" array of the layer object ANDs the filters together in the query.

UTF Grids

UTF grids can be generated at the url /grid/{z}/{x}/{y}?utfFields=field1,field2,etc., where “utfFields” is a comma-separated list of one or more table columns from the database. Each grid url MUST have a “utfFields” query string. If you have already modified the table query of a layer to specify a filter, be sure the include the utf field column in the query. Ex. (SELECT geom,homes,dog... ), if you want to base a UTF grid off the value of “dog”.

Vector Tiles

Vector tiles of your data can be generated at the endpoint /vector/{z}/{x}/{y}. Filtering by layer works via query string but can also be handled client side, as can styling. See here for more info about the Mapbox Vector Tile specification.

Local Development

Dependencies: docker, docker-compose

Debugging

The local development server exposes a Node.js process WebSocket that can be attached to your IDE of choice to step through and debug your code. Here are instructions on how to do so using Google Chrome's Dev Tools:

Helpful Links