{"id":15284707,"url":"https://github.com/dechristopher/lod","last_synced_at":"2025-06-16T07:40:45.277Z","repository":{"id":61623727,"uuid":"375317258","full_name":"dechristopher/lod","owner":"dechristopher","description":"LOD is an intelligent map tile caching proxy for the edge.","archived":false,"fork":false,"pushed_at":"2025-05-30T21:49:42.000Z","size":6039,"stargazers_count":22,"open_issues_count":12,"forks_count":1,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-05-31T08:10:11.068Z","etag":null,"topics":["cache","gis","go","lod","map","mapbox-vector-tile","mvt","openstreetmap","proxy","redis","server","tile","vector","vector-tiles"],"latest_commit_sha":null,"homepage":"https://lod.tile.fund","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/dechristopher.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"COPYING","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null},"funding":{"github":["dechristopher"]}},"created_at":"2021-06-09T10:35:30.000Z","updated_at":"2025-01-05T12:13:43.000Z","dependencies_parsed_at":"2023-10-23T14:57:06.320Z","dependency_job_id":"2c80d966-80e1-4d00-aaa7-80ae4e8cb9dd","html_url":"https://github.com/dechristopher/lod","commit_stats":null,"previous_names":["tile-fund/lod"],"tags_count":20,"template":false,"template_full_name":null,"purl":"pkg:github/dechristopher/lod","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dechristopher%2Flod","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dechristopher%2Flod/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dechristopher%2Flod/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dechristopher%2Flod/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dechristopher","download_url":"https://codeload.github.com/dechristopher/lod/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dechristopher%2Flod/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":260120142,"owners_count":22961670,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cache","gis","go","lod","map","mapbox-vector-tile","mvt","openstreetmap","proxy","redis","server","tile","vector","vector-tiles"],"created_at":"2024-09-30T14:59:29.537Z","updated_at":"2025-06-16T07:40:45.239Z","avatar_url":"https://github.com/dechristopher.png","language":"Go","funding_links":["https://github.com/sponsors/dechristopher"],"categories":[],"sub_categories":[],"readme":"\u003c!--suppress HtmlDeprecatedAttribute --\u003e\n\n\u003ch1 align=\"center\"\u003e\u003ca href=\"https://lod.tile.fund\"\u003eLOD\u003c/a\u003e: Levels of Detail\u003c/h1\u003e\n\u003cp align=\"center\"\u003eAn intelligent map tile caching proxy for the edge.\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://github.com/dechristopher/lod/releases/latest\" style=\"text-decoration: none\"\u003e\n    \u003cimg src=\"https://img.shields.io/github/v/release/dechristopher/lod?style=flat-square\" alt=\"Latest Release\"\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://github.com/dechristopher/lod/stargazers\" style=\"text-decoration: none\"\u003e\n    \u003cimg src=\"https://img.shields.io/github/stars/dechristopher/lod.svg?style=flat-square\" alt=\"Stars\"\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://github.com/dechristopher/lod/fork\" style=\"text-decoration: none\"\u003e\n    \u003cimg src=\"https://img.shields.io/github/forks/dechristopher/lod.svg?style=flat-square\" alt=\"Forks\"\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://opensource.org/licenses/AGPL-3.0\" style=\"text-decoration: none\"\u003e\n    \u003cimg src=\"https://img.shields.io/badge/license-AGPL%20v3-blue.svg?style=flat-square\" alt=\"License: AGPL v3\"\u003e\n  \u003c/a\u003e\n  \u003cbr/\u003e\n  \u003ca href=\"https://github.com/dechristopher/lod/releases\" style=\"text-decoration: none\"\u003e\n    \u003cimg src=\"https://img.shields.io/badge/platforms-linux%20%7C%20macos%20%7C%20windows-informational?style=for-the-badge\" alt=\"Downloads\"\u003e\n  \u003c/a\u003e\n  \u003cbr/\u003e\n  \u003ca href=\"https://github.com/dechristopher/lod/actions/workflows/build.yml\" style=\"text-decoration: none\"\u003e\n    \u003cimg src=\"https://img.shields.io/github/workflow/status/dechristopher/lod/build?style=flat-square\" alt=\"Build Status\"\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://lod.tile.fund\" style=\"text-decoration: none\"\u003e\n    \u003cimg src=\"https://img.shields.io/badge/docs-here-success?style=flat-square\" alt=\"Docs\"\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://goreportcard.com/report/github.com/dechristopher/lod\" style=\"text-decoration: none\"\u003e\n    \u003cimg src=\"https://img.shields.io/badge/go%20report-A+-success.svg?style=flat-square\" alt=\"Go Report Card\"\u003e\n  \u003c/a\u003e\n\u003c/p\u003e\n\nLOD (Levels of Detail) is a thin map tile proxy with in-memory caching and a\nslim authentication backend. It will sit in front of any tile server and will\naggressively cache tiles in memory, optionally storing them in a configured\nRedis cluster for faster fetching later. LOD is cluster-aware and uses Redis\nmessage queueing for intra-cluster communication when multiple instances are\ndeployed together.\n\nLOD is written in Go 1.19 using [fiber](https://github.com/gofiber/fiber). TOML\nis used for configuration. Go templates are used for templating. Internal\nin-memory caching is built upon the [bigcache](https://github.com/allegro/bigcache)\nlibrary by [allegro](https://github.com/allegro).\n\n## Getting Started\nDownload a build from the releases page or just run:\n```bash\n$ go install github.com/dechristopher/lod@latest\n```\n\n**NOTE: You'll need the GEOS library installed on your system to use some of\nLOD's more advanced cache invalidation and priming functionality.**\n\n```bash\nFlags:\n  --conf  Path/URL to TOML configuration file. Default: config.toml\n  --dev   Whether to enable developer mode. Default: false\n  --debug Optional comma separated debug flags. Ex: foo,bar,baz\n  --help  Shows this help menu.\nUsage:\n  lod [--conf config.toml] [--dev]\n```\n\nOr just use our Docker image!\n\nYou can create your own Dockerfile that adds a `config.toml` from the context\ninto the config directory, like so:\n```Dockerfile\nFROM dechristopher/lod:0.9.0\nCOPY /path/to/your_config.toml /opt/lod_cfg/config.toml\nCMD [ \"/opt/lod\", \"--conf\", \"/opt/lod_cfg/config.toml\" ]\n```\n\nAlternatively, you can specify something along the same lines with Docker run options:\n```bash\n$ docker run -v /path/to/lod-config:/opt/lod_config -p 1337:1337 lod --conf /opt/lod_config/config.toml\n```\n\n## Core Principles\n\n- Lightweight, parallel, and non-blocking\n- Tileserver agnostic (Martin, Tegola, flat file NGINX, etc.)\n- Tile format and content agnostic\n  - Vector ([Mapbox Vector Tiles](https://github.com/mapbox/vector-tile-spec)\n    or [other vector formats](https://wiki.openstreetmap.org/wiki/Vector_tiles))\n  - Raster (PNG/JPG/TIFF)\n  - And [more](https://wiki.openstreetmap.org/wiki/Tiles)...\n- Supports [XYZ (Slippy)](https://wiki.openstreetmap.org/wiki/Slippy_map_tilenames)\n  and [TMS](https://wiki.openstreetmap.org/wiki/TMS) tile indexing schemes\n\n## v1.0 Feature Roadmap\n\n- [X] Multi-level caching\n  - [X] In-memory, tunable LRU cache as first level\n  - [X] Redis cluster with configurable TTL as second level\n- [X] Dynamic query parameters\n  - [X] Allow configurable query parameters for tile URLs\n  - [X] Add to cache key for separate caching (osm/4/5/6/{osm_id})\n- [X] Configurable header proxying and deletion\n  - [X] Configurable headers to pull back into proxied responses from LOD\n  - [X] Configurable headers to delete from proxied responses from LOD\n  - [X] Configurable headers to inject into upstream tileserver requests\n  - [X] `Content-Type` and `Content-Encoding` added by default\n- [ ] Internal stats tracking\n  - [X] Hits, misses, hit-rate\n  - [ ] Tiles per second (load averages)\n  - [ ] Tile upstream fetch times (avg, 75th, 99th)\n  - [X] Expose Prometheus endpoint\n- [X] Supports multiple configured tileserver proxies\n  - [X] Separate authentication (bearer tokens and CORS)\n  - [X] Separate internal cache instances per proxy\n  - [X] Separate stats tracking\n- [ ] Administrative endpoints\n  - [X] Security via Bearer Token Authorization\n  - [X] Reload the instance configuration\n  - [X] Flush the instance caches\n  - [X] Invalidate a given tile and re-prime it\n  - [X] Iteratively invalidate all tiles under a given tile (all zoom levels)\n  - [X] Iteratively prime all tiles under a given tile\n  - [ ] Cluster-wide operations\n    - [ ] Flush the instance caches across all instances\n    - [ ] Invalidate a given tile and re-prime it across the cluster\n\n## Sample Config\nA more verbose version of this config actually used for internal testing can be\nfound at [config.toml.example](config.toml.example) in the root of the repo.\n\nMore detailed information about configuring LOD and hardening it for production\nuse can be found by reading the [source code](config/config.go).\n\n```toml\n[instance]\n# port to bind to\nport = 1337\n# admin endpoint bearer token\nadmin_token = \"${ADMIN_TOKEN}\" # config supports environment variables\n\n# base proxy configuration\n[[proxies]]\n# name of this proxy, available at http://lod/{name}/{z}/{x}/{y}.{file_extension}\nname = \"osm\"\n# url of the upstream tileserver with template parameters\n# for the X, Y, and Z values. These are required.\ntile_url = \"https://tile.example.com/osm/{z}/{x}/{y}.pbf\"\n# comma-separated list of allowed CORS origins\ncors_origins = \"https://example.com\"\n# auth token (?token=XXX) to require for requests to upstream tileserver\naccess_token = \"MyTilesArePrivate\"\n# headers to pull and cache from the tileserver response\npull_headers = [\"X-We-Want-This\", \"X-This-One-Too\"]\n# headers to delete from the tileserver response\ndel_headers = [\"X-Get-Rid-Of-Me\"]\n\n# proxy cache configuration\n[proxies.cache]\n# enable in-memory cache\nmem_enabled = true\n# maximum capacity in MB of the in-memory cache\nmem_cap = 100\n# Cache TTLs are set using Go's built-in time.ParseDuration\n# Valid time units are \"ns\", \"us\" (or \"µs\"), \"ms\", \"s\", \"m\", \"h\".\n# For example: 1h, 5m, 300s, 1000ms, 2h35m, etc.\n# in-memory cache TTL\nmem_ttl = \"1h\"\n# enable redis cache\nredis_enabled = true\n# redis tile cache TTL, or \"0\" for no expiry\nredis_ttl = \"24h\"\n# redis connection URL\nredis_url = \"redis://localhost:6379/0\"\n# cache key template string, supports parameter names\nkey_template = \"{z}/{x}/{y}\"\n\n# headers to inject into upstream tileserver requests\n[[proxies.add_headers]]\n# name of header to add\nname = \"Referer\"\n# value of header to add\nvalue = \"https://yoursite.com/\"\n\n\n# Supports many configured proxy instances for caching multiple tileservers\n[[proxies]]\nname = \"another\"\n# etc.\n```\n\n## Additional Configuration\n\n**WARNING**: these are experimental configuration properties. Only change them if you know what you're doing. All are\nexposed as environment variables.\n\n```\nMAX_ENTRY_SIZE: int\n  Size in MB of the \"entry\" that bigcache sizes its internal cache buckets by. Should be about the size of your 90th\n  percentile tiles.\n```\n\n## License\n\nLOD is licensed under the GNU Affero General Public License 3 or any later\nversion at your choice. See COPYING for details.\n\n## More Tile Resources\n\n- https://wiki.openstreetmap.org/wiki/Category:Tiles_and_tiling\n- https://wiki.openstreetmap.org/wiki/Tile_servers\n- https://github.com/mapbox/awesome-vector-tiles\n- https://docs.mapbox.com/vector-tiles/reference/\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdechristopher%2Flod","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdechristopher%2Flod","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdechristopher%2Flod/lists"}