diff --git a/service/ci.md b/service/ci.md
index 564c5e0956a82e9e94876579b4aea72043e6d1e7..9b3c3c1a31bc225929c7e57824811ae6c146848b 100644
--- a/service/ci.md
+++ b/service/ci.md
@@ -61,6 +61,29 @@ Jenkins.
 
 See [Runner disk fills up](#runner-disk-fills-up).
 
+## Running a job locally
+
+If you are having trouble reproducing a problem or just want to run a
+job in your local, trusted environment, know that you can [install
+your own GitLab runner](https://docs.gitlab.com/runner/install/index.html) and actually use it to run jobs locally,
+without registering it with the central server. The magic command is
+[`gitlab-runner exec`](https://docs.gitlab.com/runner/commands/#gitlab-runner-exec). For example, this will run a job named
+`tests` with a `shell` executor:
+
+    gitlab-runner exec shell tests
+
+To see a list of available executors, run:
+
+    gitlab-runner exec
+
+To see a list of all available options for the shell executor, run:
+
+    gitlab-runner exec shell
+
+Note that this feature was deprecated for a while but re-enabled. It
+is being [redesigned](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/2797) to be more complete, as the above has
+important limitations.
+
 ## FAQ
 
  * do runners have **network access**? **yes**, but that might