134 lines
6.8 KiB
Markdown
134 lines
6.8 KiB
Markdown
# Production hosting
|
|
|
|
Production hosting is managed by the Shields ops team:
|
|
|
|
- [calebcartwright](https://github.com/calebcartwright)
|
|
- [chris48s](https://github.com/chris48s)
|
|
- [paulmelnikow](https://github.com/paulmelnikow)
|
|
- [PyvesB](https://github.com/PyvesB)
|
|
|
|
[][operations issues]
|
|
|
|
[#ops chat room][ops discord]
|
|
|
|
[operations issues]: https://github.com/badges/shields/issues?q=is%3Aissue+is%3Aopen+label%3Aoperations
|
|
[ops discord]: https://discordapp.com/channels/308323056592486420/480747695879749633
|
|
|
|
| Component | Subcomponent | People with access |
|
|
| ----------------------------- | --------------------------- | --------------------------------------------------------------- |
|
|
| shields-io-production | Full access | @calebcartwright, @chris48s, @paulmelnikow |
|
|
| shields-io-production | Access management | @calebcartwright, @chris48s, @paulmelnikow |
|
|
| Raster server | Full access as team members | @paulmelnikow, @chris48s, @calebcartwright, @platan |
|
|
| shields-server.com redirector | Full access as team members | @paulmelnikow, @chris48s, @calebcartwright, @platan |
|
|
| Cloudflare (CDN) | Account owner | @espadrine |
|
|
| Cloudflare (CDN) | Access management | @espadrine |
|
|
| Cloudflare (CDN) | Admin access | @calebcartwright, @chris48s, @espadrine, @paulmelnikow, @PyvesB |
|
|
| Twitch | OAuth app | @PyvesB |
|
|
| Reddit | OAuth app | @chris48s, @PyvesB |
|
|
| Discord | OAuth app | @PyvesB |
|
|
| YouTube | Account owner | @PyvesB |
|
|
| GitLab | Account owner | @calebcartwright |
|
|
| GitLab | Account access | @calebcartwright, @chris48s, @paulmelnikow, @PyvesB |
|
|
| DNS | Account owner | @olivierlacan |
|
|
| DNS | Read-only account access | @espadrine, @paulmelnikow, @chris48s |
|
|
| Sentry | Error reports | @espadrine, @paulmelnikow |
|
|
| Metrics server | Owner | @platan |
|
|
| More metrics | Owner | @RedSparr0w |
|
|
|
|
## Attached state
|
|
|
|
Shields has mercifully little persistent state:
|
|
|
|
1. The GitHub tokens we collect are stored in a fly.io postgres database
|
|
2. The server keeps the [resource cache][] in memory. It is neither
|
|
persisted nor inspectable.
|
|
|
|
[resource cache]: https://github.com/badges/shields/blob/master/core/base-service/resource-cache.js
|
|
|
|
## Configuration
|
|
|
|
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`][config]) reads these
|
|
files:
|
|
|
|
- [`local-shields-io-production.yml`][local-shields-io-production.yml].
|
|
This file contains secrets which are checked in with a deploy commit.
|
|
- [`shields-io-production.yml`][shields-io-production.yml]. This file
|
|
contains non-secrets which are checked in to the main repo.
|
|
- [`default.yml`][default.yml]. This file contains defaults.
|
|
|
|
Secrets are supplied directly as environment vars.
|
|
|
|
[config]: https://github.com/lorenwest/node-config/wiki/Configuration-Files
|
|
[local-shields-io-production.yml]: ../config/local-shields-io-production.template.yml
|
|
[shields-io-production.yml]: ../config/shields-io-production.yml
|
|
[default.yml]: ../config/default.yml
|
|
|
|
## Badge CDN
|
|
|
|
Sitting in front of the three servers is a Cloudflare Free account which
|
|
provides several services:
|
|
|
|
- Global CDN, caching, and SSL gateway for `img.shields.io` and `shields.io`
|
|
- Analytics through the Cloudflare dashboard
|
|
- DNS resolution for `shields.io` (and subdomains)
|
|
|
|
Cloudflare is configured to respect the servers' cache headers.
|
|
|
|
## Raster server
|
|
|
|
The raster server `raster.shields.io` (a.k.a. the rasterizing proxy) is
|
|
hosted on Heroku. It's managed in the
|
|
[squint](https://github.com/badges/squint/) repo.
|
|
|
|
### Fly.io Deployment
|
|
|
|
Both the badge server and frontend are served from Fly.io. Deployments are
|
|
triggered using GitHub actions in a private repo.
|
|
|
|
## DNS
|
|
|
|
DNS is registered with [DNSimple][].
|
|
|
|
[dnsimple]: https://dnsimple.com/
|
|
|
|
## Error reporting
|
|
|
|
[Error reporting][sentry] is one of the most useful tools we have for monitoring
|
|
the server. It's generously donated by [Sentry][sentry home]. We bundle
|
|
[`@sentry/node`][sentry-node] into the application, and the Sentry DSN is configured
|
|
via `local-shields-io-production.yml` (see [documentation][sentry configuration]).
|
|
|
|
[sentry]: https://sentry.io/shields/
|
|
[sentry-node]: https://www.npmjs.com/package/@sentry/node
|
|
[sentry home]: https://sentry.io/shields/
|
|
[sentry configuration]: https://github.com/badges/shields/blob/master/doc/self-hosting.md#sentry
|
|
|
|
## URLs
|
|
|
|
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:
|
|
|
|
- We never show or generate the `img.`-less URL format on https://shields.io/
|
|
- We make no guarantees about the `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.
|
|
|
|
## Monitoring
|
|
|
|
Overall server performance and requests by service are monitored using
|
|
[Prometheus and Grafana][server metrics].
|
|
|
|
Request performance is monitored in two places:
|
|
|
|
- [Status][] (using NodePing)
|
|
- [Server metrics][] using Prometheus and Grafana
|
|
[#monitor chat room][monitor discord]
|
|
|
|
[metrics]: https://metrics.shields.io/
|
|
[status]: https://nodeping.com/reports/status/YBISBQB254
|
|
[server metrics]: https://metrics.shields.io/
|
|
[monitor discord]: https://discordapp.com/channels/308323056592486420/470700909182320646
|