diff --git a/common/terraform/firewall.tf b/common/terraform/firewall.tf
new file mode 100644
index 0000000000000000000000000000000000000000..1a3262ca3598e5abb466d0914efcd3af67ccd130
--- /dev/null
+++ b/common/terraform/firewall.tf
@@ -0,0 +1,94 @@
+resource "openstack_networking_secgroup_v2" "ping" {
+  name        = "ping"
+  description = "ICMP for ping"
+}
+
+resource "openstack_networking_secgroup_v2" "ssh" {
+  name        = "ssh"
+  description = "ssh connection"
+}
+
+resource "openstack_networking_secgroup_v2" "http" {
+  name        = "http"
+  description = "http/https"
+}
+
+resource "openstack_networking_secgroup_rule_v2" "ping4" {
+  direction         = "ingress"
+  ethertype         = "IPv4"
+  port_range_min    = 8
+  port_range_max    = 0
+  protocol          = "icmp"
+  remote_ip_prefix  = "0.0.0.0/0"
+  security_group_id = openstack_networking_secgroup_v2.ping.id
+}
+
+resource "openstack_networking_secgroup_rule_v2" "ping6" {
+  direction         = "ingress"
+  ethertype         = "IPv6"
+  port_range_min    = 128
+  port_range_max    = 0
+  protocol          = "icmp"  # icmp / ipv6-icmp
+  remote_ip_prefix  = "::/0"
+  security_group_id = openstack_networking_secgroup_v2.ping.id
+}
+
+resource "openstack_networking_secgroup_rule_v2" "ssh4" {
+  direction         = "ingress"
+  ethertype         = "IPv4"
+  port_range_min    = 22
+  port_range_max    = 22
+  protocol          = "tcp"
+  remote_ip_prefix  = "0.0.0.0/0"
+  security_group_id = openstack_networking_secgroup_v2.ssh.id
+}
+
+resource "openstack_networking_secgroup_rule_v2" "ssh6" {
+  direction         = "ingress"
+  ethertype         = "IPv6"
+  port_range_min    = 22
+  port_range_max    = 22
+  protocol          = "tcp"
+  remote_ip_prefix  = "::/0"
+  security_group_id = openstack_networking_secgroup_v2.ssh.id
+}
+
+resource "openstack_networking_secgroup_rule_v2" "http4" {
+  direction         = "ingress"
+  ethertype         = "IPv4"
+  port_range_min    = 80
+  port_range_max    = 80
+  protocol          = "tcp"
+  remote_ip_prefix  = "0.0.0.0/0"
+  security_group_id = openstack_networking_secgroup_v2.http.id
+}
+
+resource "openstack_networking_secgroup_rule_v2" "http6" {
+  direction         = "ingress"
+  ethertype         = "IPv6"
+  port_range_min    = 80
+  port_range_max    = 80
+  protocol          = "tcp"
+  remote_ip_prefix  = "::/0"
+  security_group_id = openstack_networking_secgroup_v2.http.id
+}
+
+resource "openstack_networking_secgroup_rule_v2" "https4" {
+  direction         = "ingress"
+  ethertype         = "IPv4"
+  port_range_min    = 443
+  port_range_max    = 443
+  protocol          = "tcp"
+  remote_ip_prefix  = "0.0.0.0/0"
+  security_group_id = openstack_networking_secgroup_v2.http.id
+}
+
+resource "openstack_networking_secgroup_rule_v2" "https6" {
+  direction         = "ingress"
+  ethertype         = "IPv6"
+  port_range_min    = 443
+  port_range_max    = 443
+  protocol          = "tcp"
+  remote_ip_prefix  = "::/0"
+  security_group_id = openstack_networking_secgroup_v2.http.id
+}
diff --git a/staging1/terraform/firewall.tf b/staging1/terraform/firewall.tf
new file mode 120000
index 0000000000000000000000000000000000000000..0088c1251a5778555091eb81f3bf6840486531ef
--- /dev/null
+++ b/staging1/terraform/firewall.tf
@@ -0,0 +1 @@
+../../common/terraform/firewall.tf
\ No newline at end of file
diff --git a/staging1/terraform/vms.tf b/staging1/terraform/vms.tf
index c7fdcda976fbdd2e67adf0aa64ea7f6af59bfc20..b196edab13a7ccf2a80186a39a67b6d177913411 100644
--- a/staging1/terraform/vms.tf
+++ b/staging1/terraform/vms.tf
@@ -10,103 +10,6 @@ locals {
   gpu_ips = [for s in openstack_compute_instance_v2.gpu[*].network[0].fixed_ip_v4 : s]
 }
 
-# Security groups
-
-resource "openstack_networking_secgroup_v2" "ping" {
-  name        = "ping"
-  description = "ICMP for ping"
-}
-
-resource "openstack_networking_secgroup_v2" "ssh" {
-  name        = "ssh"
-  description = "ssh connection"
-}
-
-resource "openstack_networking_secgroup_v2" "http" {
-  name        = "http"
-  description = "http/https"
-}
-
-resource "openstack_networking_secgroup_rule_v2" "ping4" {
-  direction         = "ingress"
-  ethertype         = "IPv4"
-  port_range_min    = 8
-  port_range_max    = 0
-  protocol          = "icmp"
-  remote_ip_prefix  = "0.0.0.0/0"
-  security_group_id = openstack_networking_secgroup_v2.ping.id
-}
-
-resource "openstack_networking_secgroup_rule_v2" "ping6" {
-  direction         = "ingress"
-  ethertype         = "IPv6"
-  port_range_min    = 128
-  port_range_max    = 0
-  protocol          = "icmp"  # icmp / ipv6-icmp
-  remote_ip_prefix  = "::/0"
-  security_group_id = openstack_networking_secgroup_v2.ping.id
-}
-
-resource "openstack_networking_secgroup_rule_v2" "ssh4" {
-  direction         = "ingress"
-  ethertype         = "IPv4"
-  port_range_min    = 22
-  port_range_max    = 22
-  protocol          = "tcp"
-  remote_ip_prefix  = "0.0.0.0/0"
-  security_group_id = openstack_networking_secgroup_v2.ssh.id
-}
-
-resource "openstack_networking_secgroup_rule_v2" "ssh6" {
-  direction         = "ingress"
-  ethertype         = "IPv6"
-  port_range_min    = 22
-  port_range_max    = 22
-  protocol          = "tcp"
-  remote_ip_prefix  = "::/0"
-  security_group_id = openstack_networking_secgroup_v2.ssh.id
-}
-
-resource "openstack_networking_secgroup_rule_v2" "http4" {
-  direction         = "ingress"
-  ethertype         = "IPv4"
-  port_range_min    = 80
-  port_range_max    = 80
-  protocol          = "tcp"
-  remote_ip_prefix  = "0.0.0.0/0"
-  security_group_id = openstack_networking_secgroup_v2.http.id
-}
-
-resource "openstack_networking_secgroup_rule_v2" "http6" {
-  direction         = "ingress"
-  ethertype         = "IPv6"
-  port_range_min    = 80
-  port_range_max    = 80
-  protocol          = "tcp"
-  remote_ip_prefix  = "::/0"
-  security_group_id = openstack_networking_secgroup_v2.http.id
-}
-
-resource "openstack_networking_secgroup_rule_v2" "https4" {
-  direction         = "ingress"
-  ethertype         = "IPv4"
-  port_range_min    = 443
-  port_range_max    = 443
-  protocol          = "tcp"
-  remote_ip_prefix  = "0.0.0.0/0"
-  security_group_id = openstack_networking_secgroup_v2.http.id
-}
-
-resource "openstack_networking_secgroup_rule_v2" "https6" {
-  direction         = "ingress"
-  ethertype         = "IPv6"
-  port_range_min    = 443
-  port_range_max    = 443
-  protocol          = "tcp"
-  remote_ip_prefix  = "::/0"
-  security_group_id = openstack_networking_secgroup_v2.http.id
-}
-
 resource "openstack_networking_floatingip_v2" "public_ip" {
   pool = var.ip_pool
 }
diff --git a/staging2/terraform/firewall.tf b/staging2/terraform/firewall.tf
new file mode 120000
index 0000000000000000000000000000000000000000..0088c1251a5778555091eb81f3bf6840486531ef
--- /dev/null
+++ b/staging2/terraform/firewall.tf
@@ -0,0 +1 @@
+../../common/terraform/firewall.tf
\ No newline at end of file
diff --git a/staging2/terraform/vms.tf b/staging2/terraform/vms.tf
index d46b46e93b250c14fc18931c3b80ad4e1cfb1db5..c6314656be86bbec189412d06b34531e1409eea8 100644
--- a/staging2/terraform/vms.tf
+++ b/staging2/terraform/vms.tf
@@ -10,103 +10,6 @@ locals {
   gpu_ips = [for s in openstack_compute_instance_v2.gpu[*].network[0].fixed_ip_v6 : replace(s, "/\\[(.*)\\]/", "$1")]
 }
 
-# Security groups
-
-resource "openstack_networking_secgroup_v2" "ping" {
-  name        = "ping"
-  description = "ICMP for ping"
-}
-
-resource "openstack_networking_secgroup_v2" "ssh" {
-  name        = "ssh"
-  description = "ssh connection"
-}
-
-resource "openstack_networking_secgroup_v2" "http" {
-  name        = "http"
-  description = "http/https"
-}
-
-resource "openstack_networking_secgroup_rule_v2" "ping4" {
-  direction         = "ingress"
-  ethertype         = "IPv4"
-  port_range_min    = 8
-  port_range_max    = 0
-  protocol          = "icmp"
-  remote_ip_prefix  = "0.0.0.0/0"
-  security_group_id = openstack_networking_secgroup_v2.ping.id
-}
-
-resource "openstack_networking_secgroup_rule_v2" "ping6" {
-  direction         = "ingress"
-  ethertype         = "IPv6"
-  port_range_min    = 128
-  port_range_max    = 0
-  protocol          = "icmp"  # icmp / ipv6-icmp
-  remote_ip_prefix  = "::/0"
-  security_group_id = openstack_networking_secgroup_v2.ping.id
-}
-
-resource "openstack_networking_secgroup_rule_v2" "ssh4" {
-  direction         = "ingress"
-  ethertype         = "IPv4"
-  port_range_min    = 22
-  port_range_max    = 22
-  protocol          = "tcp"
-  remote_ip_prefix  = "0.0.0.0/0"
-  security_group_id = openstack_networking_secgroup_v2.ssh.id
-}
-
-resource "openstack_networking_secgroup_rule_v2" "ssh6" {
-  direction         = "ingress"
-  ethertype         = "IPv6"
-  port_range_min    = 22
-  port_range_max    = 22
-  protocol          = "tcp"
-  remote_ip_prefix  = "::/0"
-  security_group_id = openstack_networking_secgroup_v2.ssh.id
-}
-
-resource "openstack_networking_secgroup_rule_v2" "http4" {
-  direction         = "ingress"
-  ethertype         = "IPv4"
-  port_range_min    = 80
-  port_range_max    = 80
-  protocol          = "tcp"
-  remote_ip_prefix  = "0.0.0.0/0"
-  security_group_id = openstack_networking_secgroup_v2.http.id
-}
-
-resource "openstack_networking_secgroup_rule_v2" "http6" {
-  direction         = "ingress"
-  ethertype         = "IPv6"
-  port_range_min    = 80
-  port_range_max    = 80
-  protocol          = "tcp"
-  remote_ip_prefix  = "::/0"
-  security_group_id = openstack_networking_secgroup_v2.http.id
-}
-
-resource "openstack_networking_secgroup_rule_v2" "https4" {
-  direction         = "ingress"
-  ethertype         = "IPv4"
-  port_range_min    = 443
-  port_range_max    = 443
-  protocol          = "tcp"
-  remote_ip_prefix  = "0.0.0.0/0"
-  security_group_id = openstack_networking_secgroup_v2.http.id
-}
-
-resource "openstack_networking_secgroup_rule_v2" "https6" {
-  direction         = "ingress"
-  ethertype         = "IPv6"
-  port_range_min    = 443
-  port_range_max    = 443
-  protocol          = "tcp"
-  remote_ip_prefix  = "::/0"
-  security_group_id = openstack_networking_secgroup_v2.http.id
-}
-
 data "openstack_images_image_v2" "ubuntu" {
   name = "ubuntu-22.04"
 }
diff --git a/testing/terraform/firewall.tf b/testing/terraform/firewall.tf
new file mode 120000
index 0000000000000000000000000000000000000000..0088c1251a5778555091eb81f3bf6840486531ef
--- /dev/null
+++ b/testing/terraform/firewall.tf
@@ -0,0 +1 @@
+../../common/terraform/firewall.tf
\ No newline at end of file
diff --git a/testing/terraform/vms.tf b/testing/terraform/vms.tf
index 6003936177ff0bc6630e8d316ea82d88d515873e..0c5751c9ad49a11f8d97b600c5ffec7a80a14dd2 100644
--- a/testing/terraform/vms.tf
+++ b/testing/terraform/vms.tf
@@ -10,103 +10,6 @@ locals {
   gpu_ips = [for s in openstack_compute_instance_v2.gpu[*].network[1].fixed_ip_v6 : replace(s, "/\\[(.*)\\]/", "$1")]
 }
 
-# Security groups
-
-resource "openstack_networking_secgroup_v2" "ping" {
-  name        = "ping"
-  description = "ICMP for ping"
-}
-
-resource "openstack_networking_secgroup_v2" "ssh" {
-  name        = "ssh"
-  description = "ssh connection"
-}
-
-resource "openstack_networking_secgroup_v2" "http" {
-  name        = "http"
-  description = "http/https"
-}
-
-resource "openstack_networking_secgroup_rule_v2" "ping4" {
-  direction         = "ingress"
-  ethertype         = "IPv4"
-  port_range_min    = 8
-  port_range_max    = 0
-  protocol          = "icmp"
-  remote_ip_prefix  = "0.0.0.0/0"
-  security_group_id = openstack_networking_secgroup_v2.ping.id
-}
-
-resource "openstack_networking_secgroup_rule_v2" "ping6" {
-  direction         = "ingress"
-  ethertype         = "IPv6"
-  port_range_min    = 128
-  port_range_max    = 0
-  protocol          = "icmp"  # icmp / ipv6-icmp
-  remote_ip_prefix  = "::/0"
-  security_group_id = openstack_networking_secgroup_v2.ping.id
-}
-
-resource "openstack_networking_secgroup_rule_v2" "ssh4" {
-  direction         = "ingress"
-  ethertype         = "IPv4"
-  port_range_min    = 22
-  port_range_max    = 22
-  protocol          = "tcp"
-  remote_ip_prefix  = "0.0.0.0/0"
-  security_group_id = openstack_networking_secgroup_v2.ssh.id
-}
-
-resource "openstack_networking_secgroup_rule_v2" "ssh6" {
-  direction         = "ingress"
-  ethertype         = "IPv6"
-  port_range_min    = 22
-  port_range_max    = 22
-  protocol          = "tcp"
-  remote_ip_prefix  = "::/0"
-  security_group_id = openstack_networking_secgroup_v2.ssh.id
-}
-
-resource "openstack_networking_secgroup_rule_v2" "http4" {
-  direction         = "ingress"
-  ethertype         = "IPv4"
-  port_range_min    = 80
-  port_range_max    = 80
-  protocol          = "tcp"
-  remote_ip_prefix  = "0.0.0.0/0"
-  security_group_id = openstack_networking_secgroup_v2.http.id
-}
-
-resource "openstack_networking_secgroup_rule_v2" "http6" {
-  direction         = "ingress"
-  ethertype         = "IPv6"
-  port_range_min    = 80
-  port_range_max    = 80
-  protocol          = "tcp"
-  remote_ip_prefix  = "::/0"
-  security_group_id = openstack_networking_secgroup_v2.http.id
-}
-
-resource "openstack_networking_secgroup_rule_v2" "https4" {
-  direction         = "ingress"
-  ethertype         = "IPv4"
-  port_range_min    = 443
-  port_range_max    = 443
-  protocol          = "tcp"
-  remote_ip_prefix  = "0.0.0.0/0"
-  security_group_id = openstack_networking_secgroup_v2.http.id
-}
-
-resource "openstack_networking_secgroup_rule_v2" "https6" {
-  direction         = "ingress"
-  ethertype         = "IPv6"
-  port_range_min    = 443
-  port_range_max    = 443
-  protocol          = "tcp"
-  remote_ip_prefix  = "::/0"
-  security_group_id = openstack_networking_secgroup_v2.http.id
-}
-
 resource "openstack_networking_floatingip_v2" "public_ip" {
   pool = var.ip_pool
 }