diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..596881b22652099c232d55eda336f3431a1f977a
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,9 @@
+./terraform/.terraform.lock.hcl
+./terraform/.terraform.tfstate.lock.info
+./terraform/terraform.tfstate*
+./terraform/.terraform/*
+./terraform/variables-local.tf
+./terraform/variables-local.tfvars
+./terraform/tfplan
+.env
+.idea
\ No newline at end of file
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
new file mode 100644
index 0000000000000000000000000000000000000000..a2c734ddadfe54edf449fd93d0ac22571dbd34ac
--- /dev/null
+++ b/.gitlab-ci.yml
@@ -0,0 +1,76 @@
+default:
+  image: registry.gitlab.com/gitlab-org/terraform-images/stable:latest
+
+variables:
+  TF_ROOT: ${CI_PROJECT_DIR}/terraform
+  TF_ADDRESS: ${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/terraform/state/${TF_STATE_NAME}
+  TF_STATE_NAME: ${ENVIRONMENT}
+  TF_CACHE_KEY: default
+
+before_script:
+  - cd ${TF_ROOT}
+  - which ssh-agent || ( apt-get install -qq openssh-client )
+  - ssh-keygen -b 2048 -t rsa -f ./tf.rsa -q -N "" -C "FORGE alpha-project-manager"
+  - export TF_VAR_SCW_ACCESS_KEY=${TF_VAR_SCW_ACCESS_KEY}
+  - export TF_VAR_SCW_SECRET_KEY=${TF_VAR_SCW_SECRET_KEY}
+  - export TF_VAR_SCW_PROJECT_ID=${TF_VAR_SCW_PROJECT_ID}
+  - export TF_VAR_INSTANCES_COUNT=${TF_VAR_INSTANCES_COUNT}
+  - export TF_VAR_ENVIRONMENT=${ENVIRONMENT}
+  - export TF_VAR_SCW_SSH_PUB_KEY=$(cat tf.rsa.pub)
+  - export TF_VAR_SCW_SSH_PRIVATE_KEY=$(cat tf.rsa)
+  - echo ${TF_VAR_SCW_SSH_PUB_KEY}
+  - echo ${TF_VAR_SCW_SSH_PRIVATE_KEY}
+  - echo $(ssh-keygen -E md5 -lf ./tf.rsa.pub)
+
+stages:
+  - prepare
+  - validate
+  - build
+  - deploy
+  - destroy
+
+init:
+  stage: prepare
+  script:
+    - gitlab-terraform init
+
+validate:
+  stage: validate
+  script:
+    - gitlab-terraform validate
+
+plan:
+  stage: build
+  script:
+    - gitlab-terraform plan
+    - gitlab-terraform plan-json
+  artifacts:
+    name: plan
+    paths:
+      - ${TF_ROOT}/plan.cache
+    reports:
+      terraform: ${TF_ROOT}/plan.json
+
+apply:
+  stage: deploy
+  environment:
+    name: ${ENVIRONMENT}
+  script:
+    - gitlab-terraform apply
+  dependencies:
+    - plan
+  when: manual
+  only:
+    - develop
+    - main
+
+destroy:
+  stage: destroy
+  environment:
+    name: ${ENVIRONMENT}
+  script:
+    - gitlab-terraform destroy
+  when: manual
+  only:
+    - develop
+    - main
\ No newline at end of file
diff --git a/create_lab.sh b/create_lab.sh
new file mode 100755
index 0000000000000000000000000000000000000000..42d181771c11debe6651cc850594b443a7aa9f08
--- /dev/null
+++ b/create_lab.sh
@@ -0,0 +1,35 @@
+#!/bin/bash
+
+echo "|------------------------|"
+echo "| INITIALISATION DU LABO |"
+echo "|------------------------|"
+
+if [ ! -f ".env" ]; then
+    echo "Créez un fichier .env de la forme suivante :"
+    echo "SCW_ACCESS_KEY="
+    echo "SCW_SECRET_KEY="
+    echo "TF_VAR_PROJECT_ID="
+    echo "TF_VAR_INSTANCES_COUNT=2"
+    exit 1
+fi
+
+export $(cat .env | xargs)
+# Move to Terraform directory
+cd ./terraform
+# Initialize a Terraform working directory
+terraform init
+# Generate and show the execution plan
+terraform plan
+# Build the infrastructure
+terraform apply
+# Echo Terraform outputs
+terraform output
+# Move to default directory
+cd ..
+
+echo "|--------------|"
+echo "| LABO DÉMARRÉ |"
+echo "|--------------|"
+
+echo "Se connecter sur les IPs, avec le port 80 pour webtop, et 8080 pour code-server."
+echo "Le mot de passe des instances est yfB4W23G."
diff --git a/delete_lab.sh b/delete_lab.sh
new file mode 100755
index 0000000000000000000000000000000000000000..47aaecf4d10489acb191b15b1b8aade0372d01bc
--- /dev/null
+++ b/delete_lab.sh
@@ -0,0 +1,3 @@
+#!/bin/bash
+export $(cat .env | xargs)
+terraform destroy
diff --git a/instance_scripts/atrium_scripts/atrium.yaml b/instance_scripts/atrium_scripts/atrium.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..badb1c51084f904337285db8875e8291e05e2786
--- /dev/null
+++ b/instance_scripts/atrium_scripts/atrium.yaml
@@ -0,0 +1,19 @@
+hostname: labo.alpha.grandlyon.com
+debug_mode: false
+letsencrypt_email: nrodet@alpha.grandlyon.com
+apps: # optional : applications served by atrium
+  - id: $COUNT
+    name: Code
+    icon: web_asset
+    color: 4292030255
+    is_proxy: true
+    host: instance$COUNT-code
+    target: $PRIVATE_IP:8080
+apps: # optional : applications served by atrium
+  - id: $COUNT
+    name: Desktop
+    icon: web_asset
+    color: 4292030255
+    is_proxy: true
+    host: instance$COUNT-desktop
+    target: $PRIVATE_IP:8081
\ No newline at end of file
diff --git a/instance_scripts/atrium_scripts/deploy.sh b/instance_scripts/atrium_scripts/deploy.sh
new file mode 100644
index 0000000000000000000000000000000000000000..b947e39a17dbac0bae9f544c29be22edaf3c7f4e
--- /dev/null
+++ b/instance_scripts/atrium_scripts/deploy.sh
@@ -0,0 +1,21 @@
+cat<<EOF >> ./atrium.yaml
+hostname: labo.alpha.grandlyon.com
+debug_mode: false
+letsencrypt_email: nrodet@alpha.grandlyon.com
+apps: # optional : applications served by atrium
+  - id: "$COUNT"
+    name: Code
+    icon: web_asset
+    color: 4292030255
+    is_proxy: true
+    host: machine$COUNT-code
+    target: $PRIVATE_IP:8080
+apps: # optional : applications served by atrium
+  - id: "$COUNT"
+    name: Desktop
+    icon: web_asset
+    color: 4292030255
+    is_proxy: true
+    host: machine$COUNT-desktop
+    target: $PRIVATE_IP:8081
+EOF
diff --git a/instance_scripts/start_webtop.sh b/instance_scripts/start_webtop.sh
new file mode 100755
index 0000000000000000000000000000000000000000..9650b16760d6e85b07c37c3e7ba6fadd0cc8e9fe
--- /dev/null
+++ b/instance_scripts/start_webtop.sh
@@ -0,0 +1,21 @@
+#!/bin/bash
+docker stop webtop
+docker rm webtop
+docker run -d \
+    --name=webtop \
+    --security-opt seccomp=unconfined \
+    -e PUID=0 \
+    -e PGID=0 \
+    -e TZ=Europe/Paris \
+    -e SUBFOLDER=/ \
+    -e KEYBOARD=fr-fr-azerty \
+    -e AUTO_LOGIN=false \
+    -p 80:3000 \
+    -v /root/webtop_data/:/config \
+    -v /var/run/docker.sock:/var/run/docker.sock \
+    --shm-size="8gb" \
+    --cap-add=NET_ADMIN \
+    --privileged \
+    --restart unless-stopped \
+    --sysctl net.ipv6.conf.all.disable_ipv6=0 \
+    lscr.io/linuxserver/webtop:ubuntu-xfce
diff --git a/terraform/main.tf b/terraform/main.tf
new file mode 100644
index 0000000000000000000000000000000000000000..26561465b58c0c207d9c50f14f6fa1f8fe4530c9
--- /dev/null
+++ b/terraform/main.tf
@@ -0,0 +1,123 @@
+############
+# Terraform SSH key
+############
+
+resource "scaleway_account_ssh_key" "ssh_key" {
+  name       = "FORGE alpha_project_manager"
+  public_key = var.SCW_SSH_PUB_KEY
+}
+
+############
+# Public IP
+############
+
+resource "scaleway_instance_ip" "public_ip" {
+  count      = var.INSTANCES_COUNT
+  project_id = var.SCW_PROJECT_ID
+}
+
+################
+# DOMAIN RECORD
+################
+
+resource "scaleway_domain_record" "subdomain_record" {
+  count    = var.INSTANCES_COUNT
+  dns_zone = "daag.alpha.grandlyon.com"
+  name     = "lab-${count.index}-daag-${var.ENVIRONMENT}"
+  type     = "A"
+  data     = scaleway_instance_ip.public_ip[count.index].address
+  ttl      = 3600
+}
+
+resource "scaleway_domain_record" "host_subdomain_record" {
+  count    = var.INSTANCES_COUNT
+  dns_zone = "daag.alpha.grandlyon.com"
+  name     = "*.lab-${count.index}-daag-${var.ENVIRONMENT}"
+  type     = "A"
+  data     = scaleway_instance_ip.public_ip[count.index].address
+  ttl      = 3600
+}
+
+##################################
+## Security group - Allowed ports
+##################################
+
+resource "scaleway_instance_security_group" "www" {
+  project_id              = var.SCW_PROJECT_ID
+  name                    = "security-group-daag-lab-${var.ENVIRONMENT}"
+  inbound_default_policy  = "drop"
+  outbound_default_policy = "accept"
+
+  inbound_rule {
+    action = "accept"
+    port   = "22"
+  }
+
+  inbound_rule {
+    action = "accept"
+    port   = "80"
+  }
+
+  inbound_rule {
+    action = "accept"
+    port   = "8080"
+  }
+
+  inbound_rule {
+    action = "accept"
+    port   = "443"
+  }
+}
+
+##############################
+## VM Instance - User Machine
+##############################
+
+resource "scaleway_instance_server" "user_instance_server" {
+  count             = var.INSTANCES_COUNT
+  project_id        = var.SCW_PROJECT_ID
+  name              = "instance-${count.index}-daag-lab-${var.ENVIRONMENT}"
+  type              = "DEV1-L"
+  image             = "ubuntu_jammy"
+  ip_id             = scaleway_instance_ip.public_ip[count.index].id
+  security_group_id = scaleway_instance_security_group.www.id
+
+  depends_on = [
+    scaleway_account_ssh_key.ssh_key,
+    scaleway_instance_security_group.www
+  ]
+}
+
+resource "null_resource" "provisioner" {
+  count      = var.INSTANCES_COUNT
+  depends_on = [
+    scaleway_instance_server.user_instance_server
+  ]
+
+  connection {
+    host        = element(scaleway_instance_ip.public_ip.*.address, count.index)
+    type        = "ssh"
+    user        = "root"
+    private_key = var.SCW_SSH_PRIVATE_KEY
+    timeout     = "2m"
+  }
+
+  // Install Rust
+  provisioner "remote-exec" {
+    inline = [
+      "apt-get update -y'",
+      "curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y'",
+      "source \"$HOME/.cargo/env\"",
+    ]
+  }
+
+  // Install Code-server
+  provisioner "remote-exec" {
+    inline = [
+      "curl -fsSL https://code-server.dev/install.sh | sh",
+      "mkdir -p  /root/.config/code-server/",
+      "echo 'bind-addr: 0.0.0.0:8080\nauth: password\npassword: yfB4W23G\ncert: false\n' > /root/.config/code-server/config.yaml",
+      "systemctl enable --now code-server@$USER"
+    ]
+  }
+}
\ No newline at end of file
diff --git a/terraform/output.tf b/terraform/output.tf
new file mode 100644
index 0000000000000000000000000000000000000000..62ee373c49d70cad84fd21fef9798cf3cec78f41
--- /dev/null
+++ b/terraform/output.tf
@@ -0,0 +1,8 @@
+#################
+# Public IP List
+#################
+
+output "public_ip_address" {
+  value     = scaleway_instance_ip.public_ip[*].address
+  sensitive = false
+}
\ No newline at end of file
diff --git a/terraform/provider.tf b/terraform/provider.tf
new file mode 100644
index 0000000000000000000000000000000000000000..e6337d76cda3f78b354b4401fdb56c7828a7aef1
--- /dev/null
+++ b/terraform/provider.tf
@@ -0,0 +1,19 @@
+terraform {
+  required_providers {
+    scaleway = {
+      source = "scaleway/scaleway"
+    }
+  }
+
+  backend "http" {}
+
+  required_version = ">= 0.13"
+}
+
+provider "scaleway" {
+  zone       = "fr-par-1"
+  region     = "fr-par"
+  access_key = var.SCW_ACCESS_KEY
+  secret_key = var.SCW_SECRET_KEY
+  project_id = var.SCW_PROJECT_ID
+}
\ No newline at end of file
diff --git a/terraform/variables-gitlab.tf b/terraform/variables-gitlab.tf
new file mode 100644
index 0000000000000000000000000000000000000000..5648602b9abf3899469de3818f4b354e31a3c51f
--- /dev/null
+++ b/terraform/variables-gitlab.tf
@@ -0,0 +1,41 @@
+### Gitlab CI variables
+
+variable "SCW_PROJECT_ID" {
+  type        = string
+  sensitive   = true
+  description = "Project ID from a scaleway project"
+}
+
+variable "SCW_ACCESS_KEY" {
+  type      = string
+  sensitive = true
+  description = "Scaleway access key"
+}
+
+variable "SCW_SECRET_KEY" {
+  type      = string
+  sensitive = true
+  description = "Scaleway secret key"
+}
+
+variable "SCW_SSH_PUB_KEY" {
+  type        = string
+  sensitive   = true
+  description = "SSH public key from Gitlab agent installed on scaleway"
+}
+
+variable "SCW_SSH_PRIVATE_KEY" {
+  type        = string
+  sensitive   = true
+  description = "SSH private key from Gitlab agent for remote-exec"
+}
+
+variable "INSTANCES_COUNT" {
+  type        = number
+  description = "Number of instances to create"
+}
+
+variable "ENVIRONMENT" {
+  type        = string
+  description = "The type of lab to create, ex: devrust, pentest..."
+}
diff --git a/terraform/variables-local.tf b/terraform/variables-local.tf
new file mode 100644
index 0000000000000000000000000000000000000000..f322a9e71df20fe0364a1ec7002ea3ee46bf2414
--- /dev/null
+++ b/terraform/variables-local.tf
@@ -0,0 +1,19 @@
+## Terraform local execution
+
+variable "FORGE_PROJECT_ID" {
+  type        = string
+  description = "Forge Project ID"
+  sensitive   = true
+}
+
+variable "FORGE_USERNAME" {
+  type        = string
+  description = "Forge Username"
+  sensitive   = true
+}
+
+variable "FORGE_ACCESS_TOKEN" {
+  type        = string
+  description = "Forge Access Token"
+  sensitive   = true
+}
diff --git a/terraform/variables-local.tfvars b/terraform/variables-local.tfvars
new file mode 100644
index 0000000000000000000000000000000000000000..8a4a791a092cc862df4cc9dd787da0e617ce3b4b
--- /dev/null
+++ b/terraform/variables-local.tfvars
@@ -0,0 +1,14 @@
+### SCW variables
+
+SCW_PROJECT_ID         = "c260d8c4-3ab6-41c2-ae56-c72bfa13b5f8"
+SCW_ACCESS_KEY         = "SCWEHMDTK4QSVBQRM5HJ"
+SCW_SECRET_KEY         = "5850fa82-d42a-469c-88a4-76c176760d5a"
+SCW_SSH_PUB_KEY        = ""
+SCW_SSH_PRIVATE_KEY    = ""
+INSTANCES_COUNT        = "2"
+ENVIRONMENT            = "devrust"
+
+### FORGE variables
+FORGE_PROJECT_ID = "875"
+FORGE_USERNAME="[\"Nathan Rodet\"]"
+FORGE_ACCESS_TOKEN = "R00tR00t"
\ No newline at end of file