diff --git a/tasks/main.yml b/tasks/main.yml
index 220221803d699f2135038397075a03ee3e43a1ca..7232dc95778f6791803a225115c63c913a1e1be0 100644
--- a/tasks/main.yml
+++ b/tasks/main.yml
@@ -63,4 +63,12 @@
       tags:
         - cron
 
+    - name: Auto-register runners for projects
+      cron:
+        name: Auto-register runners
+        job: /usr/local/bin/register-gitlab-runner auto > /dev/null 2>&1 && {{ lookup('healthchecks', '', user='root', jobname='Auto-register runners', schedule='* * * * *', disabled=crons_disabled|default(false)) }}
+        disabled: '{{ crons_disabled|default(false) }}'
+      tags:
+        - cron
+
   when: not excluded_roles or "gitlab-runner" not in excluded_roles
diff --git a/templates/register.sh b/templates/register.sh
index 009182bc9defacb78ab020a7d90956652f741194..6a584566e3c8dc656d28c92c3b6f9458391490a8 100755
--- a/templates/register.sh
+++ b/templates/register.sh
@@ -1,12 +1,22 @@
 #!/bin/bash
 
+set -e
+
 if [[ "$1" == "" ]]; then
   echo "Project ID required as first argument."
   exit 1
+elif [[ "$1" == "auto" ]]; then
+  ID=$(curl -s -H "PRIVATE-TOKEN: {{ gitlab_issue.token }}" "https://gitlab.lakedrops.com/api/v4/projects/?topic=needs_runner_{{ inventory_hostname }}" | jq -r '.[0].id')
+  if [[ "$ID" == "null" ]]; then
+    echo "Nothing to do"
+    exit 0
+  fi
+  echo "Adding runner for project ID $ID"
+  curl -X PUT -s -H "PRIVATE-TOKEN: {{ gitlab_issue.token }}" "https://gitlab.lakedrops.com/api/v4/projects/${ID}" -d "topics=runner_{{ inventory_hostname }}"
+else
+  ID=$1
 fi
 
-ID=$1
-
 TOKEN=$(curl -s -H "PRIVATE-TOKEN: {{ gitlab_issue.token }}" "https://gitlab.lakedrops.com/api/v4/projects/${ID}" | jq -r .runners_token)
 NAME=$(curl -s -H "PRIVATE-TOKEN: {{ gitlab_issue.token }}" "https://gitlab.lakedrops.com/api/v4/projects/${ID}" | jq -r .path_with_namespace)