doc/production-hosting.md
Production hosting is managed by the Shields ops team:
| Component | Subcomponent | People with access |
|---|---|---|
| Fly.io | Admin access | @calebcartwright, @chris48s, @paulmelnikow, @PyvesB |
| Fly.io | Account access | @calebcartwright, @chris48s, @jNullj, @paulmelnikow, @PyvesB |
| Cloudflare (CDN) | Account owner | @espadrine |
| Cloudflare (CDN) | Admin access | @calebcartwright, @chris48s, @espadrine, @paulmelnikow, @PyvesB |
| DNS | Account owner | @olivierlacan |
| DNS | Read-only account access | @chris48s, @espadrine, @paulmelnikow |
| Sentry | Account access | @calebcartwright, @chris48s, @espadrine, @jNullj, @paulmelnikow, @platan, @PyvesB |
| Metrics server | Owner | @platan |
| More metrics | Owner | @RedSparr0w |
| Twitch | OAuth app | @PyvesB |
| OAuth app | @chris48s, @PyvesB | |
| Discord | OAuth app | @PyvesB |
| CurseForge | OAuth app | @PyvesB |
| YouTube | Account owner | @PyvesB |
| GitLab | Account owner | @calebcartwright |
| GitLab | Account access | @calebcartwright, @chris48s, @paulmelnikow, @PyvesB |
Shields has mercifully little persistent state:
To bootstrap the configuration of non-secret settings, we set a single environment variable:
NODE_CONFIG_ENV=shields-io-production
With that variable set, the server (using config) reads these files:
local-shields-io-production.yml. This file contains secrets which are checked in with a deploy commit.shields-io-production.yml. This file contains non-secrets which are checked in to the main repo.default.yml. This file contains defaults.Secrets are supplied directly as environment vars.
Sitting in front of our servers is a Cloudflare Free account which provides several services:
img.shields.io and shields.ioshields.io (and subdomains)Cloudflare is configured to respect the servers' cache headers.
Both the badge server and frontend are served from Fly.io. Deployments are triggered using GitHub actions in a private repo.
The raster server raster.shields.io (a.k.a. the rasterizing proxy) is also hosted on Fly.io. It's managed in the squint repo.
DNS is registered with DNSimple.
Error reporting is one of the most useful tools we have for monitoring the server. It's generously donated by Sentry. We bundle @sentry/node into the application, and the Sentry DSN is configured via local-shields-io-production.yml (see documentation).
The canonical and only recommended domain for badge URLs is img.shields.io. Currently it is possible to request badges on both img.shields.io and shields.io i.e: https://img.shields.io/badge/build-passing-brightgreen and https://shields.io/badge/build-passing-brightgreen will both work. However:
img.-less URL format on https://shields.io/img.-less URL format. At some future point we may remove the ability to serve badges on shields.io (without img.) without any warning. img.shields.io should always be used for badge urls.Overall server performance and requests by service are monitored using Prometheus and Grafana.
Request performance is monitored in two places: