# PagerDuty Incident Response Docs: a real process, published as MkDocs

> The incident-response-docs repository publishes the process PagerDuty uses internally, including the preparation new engineers do before they take an on-call shift. It is a small MkDocs project with a house theme, a Docker image and two deployment paths, and it is more useful as a worked example of incident process than as a generic template.

**PagerDuty/incident-response-docs** — PagerDuty's Incident Response Documentation.

- Repository: https://github.com/PagerDuty/incident-response-docs
- Website: https://response.pagerduty.com
- Stars: 1,053 · Forks: 218
- Language: Dockerfile
- License: Apache-2.0
- Published: 2026-10-19 · Updated: 2026-10-19 · Language: en
- Canonical page: https://hysenlabs.com/projects/pagerduty-incident-response-docs

## The public copy of an internal incident process

The repository holds PagerDuty's incident response documentation in public, and the README is explicit about the intent on both sides of the fence. It is a public version of the incident response process used at PagerDuty, and it is also used to prepare new employees for on-call responsibilities. The scope runs beyond the incident itself: the documentation covers preparing for an incident, what to do during one, and what to do afterwards.

That second purpose is the interesting one for an engineer reading it. A published runbook tells you how one company escalates and recovers. A published preparation process tells you how they decide whether somebody is ready to hold a pager, which is a question most teams answer by accident rather than on purpose.

The content itself lives in the docs directory rather than in the README. The README points to an about page, docs/about.md, for more information on what the documentation is and why it exists, and it also lets you read the documentation directly in the repository through docs/index.md. The rendered site lives at response.pagerduty.com, with a Netlify deploy status badge in the README and a screenshot of the site next to it. The project is licensed under Apache 2.0, and the last push to the default branch was on 2026-07-02.

## MkDocs, three Python packages and a theme tracked on a branch

The site is generated with MkDocs, as the README states, and the whole toolchain is pinned in a small requirements.txt:

```
mkdocs
pymdown-extensions
pygments
git+https://github.com/pagerduty/mkdocs-theme-pagerduty.git@master
```

Three of those entries are ordinary packages. MkDocs does the building, Pygments handles syntax highlighting for code examples, and the Pymdown extensions provide the Markdown extras the documentation uses. The fourth is a theme, and the fourth line is the one to look at carefully: it pulls a Git repository at the master branch rather than at a tag or a commit hash. That means a rebuild can pick up a change in the theme that nobody reviewed, which matters when the theme is what makes the documentation readable.

The repository layout matches a small static site project. There is a mkdocs.yml for the site configuration, a docs/ directory for the content, a netlify.toml for the hosted build, a runtime.txt for the Python runtime, a Dockerfile and a requirements.txt. The primary language recorded for the repository is that Dockerfile, which tells you that the build and its container are the centre of the project, while the documentation content is the payload.

## Reading the site on your own machine

The native path in the README is a short list of pip installs followed by one command. Install MkDocs, the Pymdown extensions and Pygments, then install the PagerDuty theme from its own repository, which the README does by cloning it and running its setup script:

```bash
pip install mkdocs
pip install pymdown-extensions
pip install pygments
```

With the theme in place, you run the development server from the project directory:

```bash
mkdocs serve
```

The README then tells you the address to open, http://127.0.0.1:8000, and notes that the site updates automatically as you edit. That last point is the reason to prefer serve over build while you work: the page in front of you is regenerated on save, so a broken link or a bad table shows up immediately rather than after a full build.

The theme install step is the awkward part of the native path, because it clones a repository and runs setup.py, which is a packaging approach that newer Python tooling discourages. The Docker path below avoids it, and is the one the project appears to have set up most carefully.

## The container runs MkDocs as an unprivileged user

The Dockerfile is short and does one unusual thing, which is creating a non-root user for the development server. The base image is the CircleCI Python image, and the README comments that the same image is used for deploying the sites, so local and hosted builds share a base:

```dockerfile
FROM cimg/python:3.9.2
RUN pip3 install mkdocs pymdown-extensions pygments
USER mkdocs
EXPOSE 8000
ENTRYPOINT ["mkdocs"]
CMD ["serve", "--dev-addr=0.0.0.0:8000"]
```

The container adds a user with a fixed user id, switches to it, and exposes port 8000. The entrypoint is MkDocs itself and the default command serves the site bound to all interfaces, which is what lets the port mapping work from the host.

The README gives the two commands that use it, a build step that loads the image locally and a run step that mounts the current directory into the container:

```bash
docker build --load -t mkdocs .
docker run -v $(pwd):/docs -p 127.0.0.1:8000:8000 mkdocs
```

There is one platform note, and it saves real time. On an Apple Silicon machine you are told to add the platform flag to the build command so you get a native arm64 image instead of a translated one. The server is again reachable at http://127.0.0.1:8000 and updates as you edit, and the published container runs as the unprivileged user, which is a small but sensible default for something a developer runs locally.

## Two ways to publish, and a rule about what not to upload

Publishing is documented in two steps. First you build the static site, and the README asks you to clean the output directory so stale files do not survive:

```bash
mkdocs build --clean
```

Then you upload the site directory to S3, or to wherever you want it hosted, and the command in the README is a single sync with a public read ACL:

```bash
aws s3 sync ./site/ s3://[BUCKET_NAME] \
  --acl public-read \
  --exclude "*.py*" \
  --delete
```

Three flags in that command carry the design. The delete flag removes objects that are no longer in the local build, so a renamed page does not leave a stale copy behind. The exclude pattern keeps Python files out of the bucket, which makes sense for a bucket served as a public website. The public read ACL is what makes the site reachable without authentication, and it is also the flag worth thinking about twice, since it applies to every uploaded object.

The Netlify path is the other option, and the repository carries a netlify.toml plus a Netlify deploy status badge in the README, so the hosted build runs from the same repository content. There is no documentation in the README of the Netlify configuration itself, so the badge is the only feedback channel, which tells you a commit is what tells you the site changed.

## What you get, and what you do not

There are two ways to read this project, and the choice between them is the decision to make. As a document, it is a specific, published account of how a company with a large on-call organisation prepares people and handles incidents, written by the people who do the work, with an about page explaining the reasoning. That is harder to produce than it looks, and it is the reason the repository exists as a public project rather than as a wiki page.

As a starting point for your own process, it is thin. The content is PagerDuty's, not a neutral framework, and the README offers no way to rename the organisation, strip the parts that do not apply, or merge it with an existing runbook system. There is also no release history, so the project is versioned only by commits, and the last push was on 2026-07-02, which tells you the content is not being revised every week.

The tooling has the same character. It is four lines of dependencies, one Dockerfile and a handful of commands, with a theme tracked at a moving branch and a base image pinned to Python 3.9.2. Nothing here is hard to adopt, and nothing here is hard to replace either. The value is in the example, and the example is what you should take away from it.

## Conclusion

Read this repository when you want a concrete, published example of how a large on-call organisation prepares engineers and runs incidents, and copy the tooling only if you already run MkDocs with a self-hosted theme. Do not expect a template that maps onto your own company, because the content is PagerDuty's process rather than a neutral framework. Before adopting the setup, check the four pinned entries in requirements.txt, in particular the theme pulled from a master branch, and confirm that the Python 3.9.2 base image in the Dockerfile still matches the versions your own pipeline can build.

## FAQ

### What is PagerDuty's incident-response-docs repository for?

It is a public version of the incident response process used at PagerDuty, and it is also used to prepare new employees for on-call responsibilities, covering preparation, the incident itself and what follows. The content lives in the docs directory and renders at response.pagerduty.com.

### How do I run the documentation site locally?

Install mkdocs, pymdown-extensions and pygments, install the PagerDuty mkdocs theme from its own repository, then run mkdocs serve from the project directory. The site is then at http://127.0.0.1:8000 and updates as you edit.

### How does the Docker development setup work?

Build the image with docker build --load -t mkdocs . and run it with docker run -v $(pwd):/docs -p 127.0.0.1:8000:8000 mkdocs. On Apple Silicon, the README recommends adding the platform flag to the build command for a native image.

### How is the site published?

The README documents building with mkdocs build --clean and uploading the site directory with an aws s3 sync that sets a public read ACL, excludes Python files and deletes objects that are no longer in the build. A netlify.toml in the repository also supports a hosted build.

### What licence does the documentation use?

The repository is released under Apache 2.0, as stated in the README and the LICENSE file at the root of the repository.

## Sources

- [Issues](https://github.com/PagerDuty/incident-response-docs/issues)
- [License: Apache-2.0](https://github.com/PagerDuty/incident-response-docs/blob/master/LICENSE)
- [PagerDuty/incident-response-docs on GitHub](https://github.com/PagerDuty/incident-response-docs)
- [Project website](https://response.pagerduty.com)
- [README](https://github.com/PagerDuty/incident-response-docs/blob/master/README.md)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/pagerduty-incident-response-docs
