diff --git a/.env.example b/.env.example
index acba987..2ad1fa2 100755
--- a/.env.example
+++ b/.env.example
@@ -19,11 +19,6 @@ TF_VAR_aws_region=
 TF_VAR_aws_access_key=
 TF_VAR_aws_secret_key=
 
-TF_VAR_contabo_client_id=
-TF_VAR_contabo_client_secret=
-TF_VAR_contabo_user=
-TF_VAR_contabo_pass=
-
 TF_VAR_hcloud_token=
 
 TF_VAR_healthchecksio_api_key=
diff --git a/modules/infrastructure/ovh.tf b/modules/infrastructure/ovh.tf
index efba640..13d6591 100644
--- a/modules/infrastructure/ovh.tf
+++ b/modules/infrastructure/ovh.tf
@@ -52,10 +52,10 @@ resource "ovh_domain_zone_record" "tailscale_vpn" {
   target    = each.value.address
 }
 
-resource "ovh_domain_zone_record" "status_page_cname" {
+resource "ovh_domain_zone_record" "gpg_verify" {
   zone      = "serguzim.net"
-  subdomain = "status"
-  fieldtype = "CNAME"
+  subdomain = ""
+  fieldtype = "TXT"
   ttl       = 3600
-  target    = "status.serguzim.me."
+  target    = "openpgp4fpr:723B78C0BF8D8C721D2C4EEF41E544A54E2533B2"
 }
diff --git a/playbooks/filter_plugins/gatus.py b/playbooks/filter_plugins/gatus.py
index 08e8568..1eb3ceb 100644
--- a/playbooks/filter_plugins/gatus.py
+++ b/playbooks/filter_plugins/gatus.py
@@ -75,6 +75,7 @@ class FilterModule(object):
                     "group": mon.get("group"),
                     "url": url,
                     "conditions": conditions,
+                    "interval": mon.get("interval"),
                     "alerts": self.default_alerts,
                     "ui": {
                         "hide-url": True
diff --git a/playbooks/roles/backup/tasks/main.yml b/playbooks/roles/backup/tasks/main.yml
index 5f67f92..f36059d 100644
--- a/playbooks/roles/backup/tasks/main.yml
+++ b/playbooks/roles/backup/tasks/main.yml
@@ -35,14 +35,3 @@
       ansible.builtin.import_tasks: recovery.yml
     - name: Import tasks specific to systemd
       ansible.builtin.import_tasks: systemd.yml
-
-    - name: Verify service
-      ansible.builtin.command:
-        cmd: autorestic -v check
-        chdir: "{{ service_path }}"
-      changed_when: false
-      become: true
-      register: cmd_result_verify
-      until: "cmd_result_verify is not failed"
-      retries: 10
-      delay: 10
diff --git a/playbooks/roles/forgejo/templates/footer.tmpl.j2 b/playbooks/roles/forgejo/templates/footer.tmpl.j2
index 53fcdad..6a06196 100644
--- a/playbooks/roles/forgejo/templates/footer.tmpl.j2
+++ b/playbooks/roles/forgejo/templates/footer.tmpl.j2
@@ -1 +1,2 @@
 <script async src="/_a/script.js" data-website-id="{{ vault_forgejo.umami }}"></script>
+<script async src="/_a/track-external.js"></script>
diff --git a/playbooks/roles/forgejo_runner/vars/main.yml b/playbooks/roles/forgejo_runner/vars/main.yml
index 19705d3..6fd207d 100644
--- a/playbooks/roles/forgejo_runner/vars/main.yml
+++ b/playbooks/roles/forgejo_runner/vars/main.yml
@@ -22,6 +22,7 @@ forgejo_runner_compose:
       docker-in-docker:
         image: docker:dind
         privileged: true
+        dns: 1.1.1.1
         restart: always
         command: dockerd -H tcp://0.0.0.0:2375 --tls=false
         networks:
diff --git a/playbooks/roles/homebox/vars/main.yml b/playbooks/roles/homebox/vars/main.yml
index 3929cc0..34895b9 100644
--- a/playbooks/roles/homebox/vars/main.yml
+++ b/playbooks/roles/homebox/vars/main.yml
@@ -14,7 +14,7 @@ homebox_env:
 
 homebox_compose:
   watchtower: update
-  image: ghcr.io/sysadminsmedia/homebox:latest-rootless
+  image: ghcr.io/sysadminsmedia/homebox:0-rootless
   volumes:
     - data:/data
   file:
diff --git a/playbooks/roles/umami/vars/main.yml b/playbooks/roles/umami/vars/main.yml
index 092e8c4..48d906d 100644
--- a/playbooks/roles/umami/vars/main.yml
+++ b/playbooks/roles/umami/vars/main.yml
@@ -10,6 +10,21 @@ umami_docker_image: docker.umami.dev/umami-software/umami:postgresql-latest
 
 umami_svc:
   domain: "{{ all_services | service_get_domain(role_name) }}"
+  caddy_extra: |
+    handle /track-external.js {
+      header Content-Type text/javascript
+      respond <<JS
+        (() => {
+          const name = 'outbound-link-click';
+          document.querySelectorAll('a').forEach(a => {
+            if (a.host !== window.location.host && !a.getAttribute('data-umami-event')) {
+              a.setAttribute('data-umami-event', name);
+              a.setAttribute('data-umami-event-url', a.href);
+            }
+          });
+        })();
+        JS 200
+    }
   port: 3000
 
 umami_env:
diff --git a/playbooks/unlock-backup.yml b/playbooks/unlock-backup.yml
index 78fea7c..40403e4 100644
--- a/playbooks/unlock-backup.yml
+++ b/playbooks/unlock-backup.yml
@@ -3,7 +3,7 @@
   hosts: serguzim_net
   become: true
   tasks:
-  - name: Change password
+  - name: Unlock backups
     ansible.builtin.shell:
       cmd: autorestic unlock --force && autorestic exec -va unlock
       chdir: "{{ (services_path, 'backup') | path_join }}"
diff --git a/playbooks/verify-backup-yml b/playbooks/verify-backup-yml
new file mode 100644
index 0000000..b34bf67
--- /dev/null
+++ b/playbooks/verify-backup-yml
@@ -0,0 +1,15 @@
+---
+- name: Unlock backups
+  hosts: serguzim_net
+  become: true
+  tasks:
+  - name: Verify backup
+    ansible.builtin.command:
+      cmd: autorestic -v check
+      chdir: "{{ (services_path, 'backup') | path_join }}"
+    changed_when: false
+    become: true
+    register: cmd_result_verify
+    until: "cmd_result_verify is not failed"
+    retries: 10
+    delay: 10
diff --git a/templates/infrastructure.d2.j2 b/templates/infrastructure.d2.j2
index 86d5670..0f47193 100644
--- a/templates/infrastructure.d2.j2
+++ b/templates/infrastructure.d2.j2
@@ -15,16 +15,25 @@ external: {
     }
 }
 
-{% for host in hosts %}
-{{ host.key }}: {
-}
-
-{{ host.key }}.backup -> external.restic {
-    style: {
-        stroke: "#0f0"
-        stroke-dash: 3
+classes: {
+    zero_grid: {
+        grid-columns: 3
+        grid-gap: 0
+    }
+    monitored: {
+        style: {
+            fill: "#1E9025"
+        }
+    }
+    backup: {
+        style: {
+            fill: "#0f0"
+        }
     }
 }
+
+{% for host in hosts %}
+{{ host.key }}
 {% endfor %}{# host #}
 
 {% for svc in svcs %}
@@ -36,32 +45,25 @@ external: {
 }
 
 {% for backup in svc.backup or [] %}
-{{ svc.key }} -> {{ svc.host_key }}.backup: {{ backup.name }} {
-    style: {
-        stroke: "#0f0"
-        stroke-dash: 3
-    }
-}
-{% endfor %}{# backup #}
+{{ svc.key }}.'{{ backup.name }}'.class: backup
+{% endfor %}
 
 {% if svc.monitoring %}
-{{ monitoring_key }} -> {{ svc.key }}: {
-    style.stroke: "#1E9025"
-}
+{{ svc.key }}.monitored.class: monitored
 {% endif %}
 
 {% if svc.database %}
 {{ svc.key }} -> {{ db_key }}: {
     style.stroke: "#336791"
 }
-{{ db_key }}.{{ svc.name }}
+{{ db_subkey }}.{{ svc.name }}
 {% endif %}
 
 {% if svc.auth %}
 {{ svc.key }} -> {{ auth_key }}: {
     style.stroke: "#FD4B2D"
 }
-{{ auth_key }}.{{ svc.name }}
+{{ auth_subkey }}.{{ svc.name }}
 {% endif %}
 
 {% if svc.s3 %}
@@ -78,14 +80,11 @@ external.scaleway.s3.{{ svc.name }}
 {{ svc.key }} -> {{ mail_key }}: {
     style.stroke: "#C9B81F"
 }
-{{ mail_key }}.{{ svc.name }}
+{{ mail_subkey }}.{{ svc.name }}
 {% endif %}
 
 {% endfor %}{# svc #}
 
 {% for svc in grid_svcs %}
-{{ svc }}: {
-    grid-columns: 3
-    grid-gap: 0
-}
+{{ svc }}.class: zero_grid
 {% endfor %}
diff --git a/variables.tf b/variables.tf
index d49b584..acaf01e 100644
--- a/variables.tf
+++ b/variables.tf
@@ -148,6 +148,7 @@ variable "services" {
     monitoring = optional(object({
       url   = optional(string)
       group = optional(string)
+      interval = optional(string)
       conditions = optional(list(string))
     }))
     ports = optional(list(object({
diff --git a/visualize.py b/visualize.py
index 3dc3af7..62c8a43 100755
--- a/visualize.py
+++ b/visualize.py
@@ -11,6 +11,7 @@ icon_overrides = {
     "backup": "restic",
     "dokku": None,
     "extra_services": None,
+    "factorio": None,
     "forgejo_runner": "forgejo",
     "healthcheck": "healthchecks",
     "lego": "lets-encrypt",
@@ -96,20 +97,21 @@ if __name__ == '__main__':
     with open('./services.auto.tfvars', 'r') as file:
         services = hcl2.load(file)["services"][0]
 
-    db_key = service_key_find("postgresql", services, hosts)
-    auth_key = service_key_find("authentik", services, hosts)
-    monitoring_key = service_key_find("gatus", services, hosts)
-    mail_key = service_key_find("mailcowdockerized", services, hosts)
+    keys = {}
+    keys["db_key"] = service_key_find("postgresql", services, hosts)
+    keys["db_subkey"] = f"{keys["db_key"]}.dbs"
+    keys["auth_key"] = service_key_find("authentik", services, hosts)
+    keys["auth_subkey"] = f"{keys["auth_key"]}.apps"
+    keys["mail_key"] = service_key_find("mailcowdockerized", services, hosts)
+    keys["mail_subkey"] = f"{keys["mail_key"]}.mailboxes"
+    keys["monitoring_key"] = service_key_find("gatus", services, hosts)
 
     jinja_loader = jinja2.FileSystemLoader(searchpath="./templates")
     jinja_env = jinja2.Environment(loader=jinja_loader)
     template = jinja_env.get_template("infrastructure.d2.j2")
     print(template.render(
-        grid_svcs=[db_key, auth_key, mail_key],
+        grid_svcs=[keys["db_subkey"], keys["auth_subkey"], keys["mail_subkey"]],
         svcs=parse_services(services, hosts),
         hosts=parse_hosts(hosts),
-        db_key=db_key,
-        auth_key=auth_key,
-        monitoring_key=monitoring_key,
-        mail_key=mail_key,
+        **keys
     ))