Hosting your own Shields server
You will need Node 12 or later, which you can install using a package manager.
On Ubuntu / Debian:
curl -sL https://deb.nodesource.com/setup_12.x | sudo -E bash -; sudo apt-get install -y nodejs
git clone https://github.com/badges/shields.git cd shields npm ci # You may need sudo for this.
Build the frontend
npm run build
Start the server
sudo node server
The server uses port 80 by default, which requires
There are two ways to provide an alternate port:
PORT=8080 node server node server 8080
The root gets redirected to https://shields.io.
For testing purposes, you can go to
Once you have installed the Heroku CLI
heroku login heroku create your-app-name git push heroku master heroku open
You can build and run the server locally using Docker. First build an image:
$ docker build -t shields . Sending build context to Docker daemon 3.923 MB … Successfully built 4471b442c220
Then run the container:
$ docker run --rm -p 8080:80 --name shields shields # or if you have shields.env file, run the following instead $ docker run --rm -p 8080:80 --env-file shields.env --name shields shields > firstname.lastname@example.org start /usr/src/app > node server.js http://[::1]/
Assuming Docker is running locally, you should be able to get to the application at http://localhost:8080/.
If you run Docker in a virtual machine (such as boot2docker or Docker Machine)
then you will need to replace
localhost with the IP address of that virtual
If you want to host PNG badges, you can also self-host a raster server
which points to your badge server. It's designed as a web function which is
tested on Zeit Now, though you may be able to run it on AWS Lambda. It's
built on the micro framework, and comes with a
start script that allows
it to run as a standalone Node service.
- In your raster instance, set
BASE_URLto your Shields instance, e.g.
- Optionally, in your Shields, instance, configure
RASTER_URLto the base URL, e.g.
https://raster.example.co. This will send 301 redirects for the legacy raster URLs instead of 404's.
If anyone has set this up, more documentation on how to do this would be welcome! It would also be nice to ship a Docker image that includes a preconfigured raster server.
To deploy using Zeit Now:
npm run build # Not sure why, but this needs to be run before deploying. now
To enable Redis-backed GitHub token persistence, point
REDIS_URL to your
You can add your own server secrets in environment variables or
These are documented in server-secrets.md
Separate frontend hosting
If you want to host the frontend on a separate server, such as cloud storage or a CDN, you can do that.
First, build the frontend, pointing
GATSBY_BASE_URL to your server.
GATSBY_BASE_URL=https://your-server.example.com npm run build
Then copy the contents of the
build/ folder to your static hosting / CDN.
There are also a couple settings you should configure on the server.
If you want to use server suggestions, you should also set
This should be a comma-separated list of allowed origin headers. They should not have paths or trailing slashes.
To help out users, you can make the Shields server redirect the server root.
REDIRECT_URI environment variable:
How to obtain the Sentry DSN
- Sign up for Sentry
- Log in to Sentry
- Create a new project for Node.js
- You should see Sentry DSN for your project. Sentry DSN can be found by navigating to [Project Name] -> Project Settings -> Client Keys (DSN) as well.
Start the server using the Sentry DSN. You can set it:
sudo SENTRY_DSN=https://xxx:email@example.com/zzz node server
Or via config as you would do with server secrets:
private: sentry_dsn: ...
sudo node server
Shields uses prom-client to provide default metrics. These metrics are disabled by default.
You can enable them by
METRICS_PROMETHEUS_ENDPOINT_ENABLED environment variables.
METRICS_PROMETHEUS_ENABLED=true METRICS_PROMETHEUS_ENDPOINT_ENABLED=true npm start
Metrics are available at
Shields uses Cloudflare as a downstream CDN. If your installation does the same,
you can configure your server to only accept requests coming from Cloudflare's IPs.