Compare commits

30 Commits

Author SHA1 Message Date
e41c25b64f feat: secure docker image removal
All checks were successful
Blog Deployment / Check-Rebuild (push) Successful in 6s
Blog Deployment / Build (push) Has been skipped
Blog Deployment / Deploy-Staging (push) Successful in 35s
Blog Deployment / Test-Staging (push) Successful in 2s
Blog Deployment / Merge (push) Successful in 8s
Blog Deployment / Deploy-Production (push) Successful in 35s
Blog Deployment / Test-Production (push) Successful in 2s
Blog Deployment / Clean (push) Has been skipped
Blog Deployment / Notify (push) Successful in 2s
2026-05-25 13:47:56 +00:00
ce1c7e36bb feat: reduce the sleep to 30s
Some checks failed
Blog Test / Check-Rebuild (push) Successful in 6s
Blog Test / Build (push) Successful in 7s
Blog Test / Deploy-Test (push) Successful in 36s
Blog Test / Test (push) Successful in 2s
Blog Deployment / Check-Rebuild (push) Successful in 5s
Blog Deployment / Build (push) Successful in 7s
Blog Deployment / Deploy-Staging (push) Successful in 35s
Blog Deployment / Test-Staging (push) Successful in 2s
Blog Deployment / Merge (push) Successful in 8s
Blog Deployment / Deploy-Production (push) Successful in 34s
Blog Deployment / Test-Production (push) Successful in 2s
Blog Deployment / Clean (push) Failing after 2s
Blog Deployment / Notify (push) Successful in 3s
2026-05-25 13:30:26 +00:00
6a4fdcb6ff fix: corrected new sleep timer to 60 for test pipeline
All checks were successful
Blog Test / Check-Rebuild (push) Successful in 6s
Blog Test / Build (push) Successful in 8s
Blog Test / Deploy-Test (push) Successful in 1m3s
Blog Test / Test (push) Successful in 2s
2026-05-25 13:27:35 +00:00
07ce7c58ef feat: remove deprecation workaround
Some checks failed
Blog Test / Check-Rebuild (push) Successful in 6s
Blog Test / Build (push) Successful in 36s
Blog Test / Deploy-Test (push) Successful in 8s
Blog Test / Test (push) Failing after 3s
2026-05-25 13:18:04 +00:00
Gitea Actions
bd121d794c Auto-update blog content from Obsidian: 2026-05-24 21:07:44
Some checks failed
Blog Deployment / Check-Rebuild (push) Successful in 6s
Blog Deployment / Build (push) Has been skipped
Blog Deployment / Deploy-Staging (push) Successful in 1m3s
Blog Deployment / Test-Staging (push) Successful in 2s
Blog Deployment / Merge (push) Successful in 7s
Blog Deployment / Deploy-Production (push) Successful in 1m3s
Blog Deployment / Test-Production (push) Successful in 2s
Blog Deployment / Clean (push) Has been skipped
Blog Deployment / Notify (push) Successful in 2s
Blog Test / Check-Rebuild (push) Successful in 7s
Blog Test / Build (push) Has been skipped
Blog Test / Deploy-Test (push) Failing after 4s
Blog Test / Test (push) Has been skipped
2026-05-24 21:07:44 +00:00
Gitea Actions
19258d081c Auto-update blog content from Obsidian: 2026-05-24 20:58:30
All checks were successful
Blog Deployment / Check-Rebuild (push) Successful in 7s
Blog Deployment / Build (push) Has been skipped
Blog Deployment / Deploy-Staging (push) Successful in 1m4s
Blog Deployment / Test-Staging (push) Successful in 2s
Blog Deployment / Merge (push) Successful in 8s
Blog Deployment / Deploy-Production (push) Successful in 1m4s
Blog Deployment / Test-Production (push) Successful in 2s
Blog Deployment / Clean (push) Has been skipped
Blog Deployment / Notify (push) Successful in 2s
2026-05-24 20:58:30 +00:00
Gitea Actions
40ec16e974 Auto-update blog content from Obsidian: 2026-05-24 20:12:49
All checks were successful
Blog Deployment / Merge (push) Successful in 6s
Blog Deployment / Deploy-Production (push) Successful in 1m3s
Blog Deployment / Test-Production (push) Successful in 3s
Blog Deployment / Clean (push) Has been skipped
Blog Deployment / Notify (push) Successful in 2s
Blog Deployment / Check-Rebuild (push) Successful in 6s
Blog Deployment / Build (push) Has been skipped
Blog Deployment / Deploy-Staging (push) Successful in 1m3s
Blog Deployment / Test-Staging (push) Successful in 2s
2026-05-24 20:12:49 +00:00
Gitea Actions
8e4e4601d7 Auto-update blog content from Obsidian: 2026-05-24 19:12:42
All checks were successful
Blog Deployment / Check-Rebuild (push) Successful in 6s
Blog Deployment / Build (push) Has been skipped
Blog Deployment / Deploy-Staging (push) Successful in 1m4s
Blog Deployment / Test-Staging (push) Successful in 3s
Blog Deployment / Merge (push) Successful in 7s
Blog Deployment / Deploy-Production (push) Successful in 1m5s
Blog Deployment / Test-Production (push) Successful in 2s
Blog Deployment / Clean (push) Has been skipped
Blog Deployment / Notify (push) Successful in 3s
2026-05-24 19:12:42 +00:00
Gitea Actions
8facd6010b Auto-update blog content from Obsidian: 2026-05-24 14:31:31
All checks were successful
Blog Deployment / Check-Rebuild (push) Successful in 8s
Blog Deployment / Build (push) Has been skipped
Blog Deployment / Deploy-Production (push) Successful in 1m4s
Blog Deployment / Test-Production (push) Successful in 2s
Blog Deployment / Deploy-Staging (push) Successful in 1m4s
Blog Deployment / Test-Staging (push) Successful in 2s
Blog Deployment / Merge (push) Successful in 9s
Blog Deployment / Clean (push) Has been skipped
Blog Deployment / Notify (push) Successful in 3s
2026-05-24 14:31:31 +00:00
Gitea Actions
49631bbabc Auto-update blog content from Obsidian: 2026-05-24 13:31:24
All checks were successful
Blog Deployment / Check-Rebuild (push) Successful in 8s
Blog Deployment / Build (push) Has been skipped
Blog Deployment / Deploy-Staging (push) Successful in 1m4s
Blog Deployment / Test-Staging (push) Successful in 2s
Blog Deployment / Merge (push) Successful in 9s
Blog Deployment / Deploy-Production (push) Successful in 1m5s
Blog Deployment / Test-Production (push) Successful in 3s
Blog Deployment / Clean (push) Has been skipped
Blog Deployment / Notify (push) Successful in 3s
2026-05-24 13:31:24 +00:00
Gitea Actions
0e81ddf7ed Auto-update blog content from Obsidian: 2026-05-24 12:30:51
All checks were successful
Blog Deployment / Check-Rebuild (push) Successful in 8s
Blog Deployment / Build (push) Has been skipped
Blog Deployment / Deploy-Staging (push) Successful in 1m5s
Blog Deployment / Test-Staging (push) Successful in 3s
Blog Deployment / Merge (push) Successful in 8s
Blog Deployment / Deploy-Production (push) Successful in 1m4s
Blog Deployment / Test-Production (push) Successful in 3s
Blog Deployment / Clean (push) Has been skipped
Blog Deployment / Notify (push) Successful in 3s
2026-05-24 12:30:51 +00:00
a01f4dcf4e fix: typo
All checks were successful
Blog Deployment / Check-Rebuild (push) Successful in 8s
Blog Deployment / Build (push) Has been skipped
Blog Deployment / Deploy-Staging (push) Successful in 1m4s
Blog Deployment / Test-Staging (push) Successful in 2s
Blog Deployment / Merge (push) Successful in 9s
Blog Deployment / Deploy-Production (push) Successful in 1m4s
Blog Deployment / Test-Production (push) Successful in 2s
Blog Deployment / Clean (push) Has been skipped
Blog Deployment / Notify (push) Successful in 2s
2026-05-02 17:09:10 +00:00
8d88e5c87f change: wait 60s before showing logs
All checks were successful
Blog Deployment / Check-Rebuild (push) Successful in 6s
Blog Deployment / Build (push) Successful in 7s
Blog Deployment / Deploy-Staging (push) Successful in 1m3s
Blog Deployment / Test-Staging (push) Successful in 3s
Blog Deployment / Merge (push) Successful in 8s
Blog Deployment / Deploy-Production (push) Successful in 1m3s
Blog Deployment / Test-Production (push) Successful in 3s
Blog Deployment / Clean (push) Successful in 2s
Blog Deployment / Notify (push) Successful in 2s
2026-04-30 10:52:02 +00:00
7728af1cdb change: wait 15s before showing logs
Some checks failed
Blog Deployment / Check-Rebuild (push) Successful in 6s
Blog Deployment / Deploy-Staging (push) Successful in 9s
Blog Deployment / Build (push) Successful in 7s
Blog Deployment / Test-Staging (push) Failing after 3s
Blog Deployment / Merge (push) Has been skipped
Blog Deployment / Deploy-Production (push) Has been skipped
Blog Deployment / Test-Production (push) Has been skipped
Blog Deployment / Clean (push) Has been skipped
Blog Deployment / Notify (push) Successful in 2s
2026-04-30 10:43:39 +00:00
ab9a714b3e change: wait 10s before showing logs
Some checks failed
Blog Deployment / Check-Rebuild (push) Successful in 7s
Blog Deployment / Build (push) Successful in 9s
Blog Deployment / Deploy-Staging (push) Successful in 10s
Blog Deployment / Test-Staging (push) Failing after 3s
Blog Deployment / Merge (push) Has been skipped
Blog Deployment / Deploy-Production (push) Has been skipped
Blog Deployment / Test-Production (push) Has been skipped
Blog Deployment / Clean (push) Has been skipped
Blog Deployment / Notify (push) Successful in 2s
2026-04-30 10:39:30 +00:00
2a1debc648 add: i18n pagination 2026-04-30 10:38:27 +00:00
ec54ddd1c3 fix: Locale
Some checks failed
Blog Deployment / Check-Rebuild (push) Successful in 11s
Blog Deployment / Build (push) Successful in 25s
Blog Deployment / Deploy-Staging (push) Successful in 28s
Blog Deployment / Test-Staging (push) Failing after 6s
Blog Deployment / Merge (push) Has been skipped
Blog Deployment / Deploy-Production (push) Has been skipped
Blog Deployment / Test-Production (push) Has been skipped
Blog Deployment / Clean (push) Has been skipped
Blog Deployment / Notify (push) Successful in 26s
2026-04-29 22:20:45 +00:00
2b14785ea4 test: replace site by hugo
Some checks failed
Blog Deployment / Check-Rebuild (push) Successful in 11s
Blog Deployment / Build (push) Successful in 16s
Blog Deployment / Deploy-Staging (push) Successful in 23s
Blog Deployment / Test-Staging (push) Failing after 15s
Blog Deployment / Merge (push) Has been skipped
Blog Deployment / Deploy-Production (push) Has been skipped
Blog Deployment / Test-Production (push) Has been skipped
Blog Deployment / Clean (push) Has been skipped
Blog Deployment / Notify (push) Successful in 20s
2026-04-29 22:15:24 +00:00
b5612b24ee add: workaround for rss.xml
Some checks failed
Blog Deployment / Check-Rebuild (push) Successful in 11s
Blog Deployment / Test-Staging (push) Failing after 17s
Blog Deployment / Build (push) Successful in 49s
Blog Deployment / Deploy-Staging (push) Successful in 48s
Blog Deployment / Merge (push) Has been skipped
Blog Deployment / Deploy-Production (push) Has been skipped
Blog Deployment / Test-Production (push) Has been skipped
Blog Deployment / Clean (push) Has been skipped
Blog Deployment / Notify (push) Successful in 17s
2026-04-29 22:07:00 +00:00
14f9160c3d add: workaround for LanguageCode
Some checks failed
Blog Deployment / Check-Rebuild (push) Successful in 33s
Blog Deployment / Build (push) Successful in 27s
Blog Deployment / Deploy-Staging (push) Successful in 27s
Blog Deployment / Test-Staging (push) Failing after 6s
Blog Deployment / Merge (push) Has been skipped
Blog Deployment / Deploy-Production (push) Has been skipped
Blog Deployment / Test-Production (push) Has been skipped
Blog Deployment / Clean (push) Has been skipped
Blog Deployment / Notify (push) Successful in 8s
2026-04-29 22:02:00 +00:00
88cbc90fca add: workaround for LanguageDirection
Some checks failed
Blog Deployment / Check-Rebuild (push) Successful in 11s
Blog Deployment / Build (push) Successful in 22s
Blog Deployment / Deploy-Staging (push) Successful in 33s
Blog Deployment / Test-Staging (push) Failing after 20s
Blog Deployment / Merge (push) Has been skipped
Blog Deployment / Deploy-Production (push) Has been skipped
Blog Deployment / Test-Production (push) Has been skipped
Blog Deployment / Clean (push) Has been skipped
Blog Deployment / Notify (push) Successful in 11s
2026-04-29 21:56:55 +00:00
fb06ae4e93 update: stack theme
Some checks failed
Blog Deployment / Test-Staging (push) Failing after 5s
Blog Deployment / Merge (push) Has been skipped
Blog Deployment / Deploy-Production (push) Has been skipped
Blog Deployment / Test-Production (push) Has been skipped
Blog Deployment / Clean (push) Has been skipped
Blog Deployment / Notify (push) Successful in 6s
Blog Deployment / Check-Rebuild (push) Successful in 8s
Blog Deployment / Build (push) Has been skipped
Blog Deployment / Deploy-Staging (push) Successful in 11s
2026-04-29 21:27:21 +00:00
6403ffd8ba change: languageName by label
Some checks failed
Blog Deployment / Build (push) Has been skipped
Blog Deployment / Notify (push) Successful in 3s
Blog Deployment / Check-Rebuild (push) Successful in 5s
Blog Deployment / Deploy-Staging (push) Successful in 8s
Blog Deployment / Test-Staging (push) Failing after 3s
Blog Deployment / Merge (push) Has been skipped
Blog Deployment / Deploy-Production (push) Has been skipped
Blog Deployment / Test-Production (push) Has been skipped
Blog Deployment / Clean (push) Has been skipped
2026-04-29 20:54:16 +00:00
3fb76c0caf change: languageCode by locale
Some checks failed
Blog Deployment / Deploy-Staging (push) Successful in 9s
Blog Deployment / Test-Staging (push) Failing after 4s
Blog Deployment / Merge (push) Has been skipped
Blog Deployment / Test-Production (push) Has been skipped
Blog Deployment / Clean (push) Has been skipped
Blog Deployment / Deploy-Production (push) Has been skipped
Blog Deployment / Notify (push) Successful in 3s
Blog Deployment / Check-Rebuild (push) Successful in 6s
Blog Deployment / Build (push) Has been skipped
2026-04-29 20:52:34 +00:00
18c318f31e delete: img folder in static
Some checks failed
Blog Deployment / Test-Staging (push) Failing after 3s
Blog Deployment / Check-Rebuild (push) Successful in 5s
Blog Deployment / Build (push) Has been skipped
Blog Deployment / Deploy-Staging (push) Successful in 8s
Blog Deployment / Merge (push) Has been skipped
Blog Deployment / Deploy-Production (push) Has been skipped
Blog Deployment / Test-Production (push) Has been skipped
Blog Deployment / Clean (push) Has been skipped
Blog Deployment / Notify (push) Successful in 3s
2026-04-29 20:48:39 +00:00
Gitea Actions
4143724c86 Auto-update blog content from Obsidian: 2026-04-29 20:40:29
Some checks failed
Blog Deployment / Notify (push) Successful in 3s
Blog Deployment / Check-Rebuild (push) Successful in 6s
Blog Deployment / Build (push) Has been skipped
Blog Deployment / Deploy-Staging (push) Successful in 9s
Blog Deployment / Test-Staging (push) Failing after 3s
Blog Deployment / Merge (push) Has been skipped
Blog Deployment / Test-Production (push) Has been skipped
Blog Deployment / Clean (push) Has been skipped
Blog Deployment / Deploy-Production (push) Has been skipped
2026-04-29 20:40:29 +00:00
Gitea Actions
5936475f99 Auto-update blog content from Obsidian: 2026-04-29 19:59:52
Some checks failed
Blog Deployment / Check-Rebuild (push) Successful in 8s
Blog Deployment / Build (push) Successful in 31s
Blog Deployment / Deploy-Staging (push) Successful in 9s
Blog Deployment / Test-Staging (push) Failing after 3s
Blog Deployment / Merge (push) Has been skipped
Blog Deployment / Deploy-Production (push) Has been skipped
Blog Deployment / Test-Production (push) Has been skipped
Blog Deployment / Clean (push) Has been skipped
Blog Deployment / Notify (push) Successful in 3s
2026-04-29 19:59:52 +00:00
c731b7eaf5 fix: refactor removal of old docker images
All checks were successful
Blog Test / Check-Rebuild (push) Successful in 6s
Blog Test / Build (push) Has been skipped
Blog Test / Deploy-Test (push) Successful in 9s
Blog Test / Test (push) Successful in 2s
Blog Deployment / Check-Rebuild (push) Successful in 6s
Blog Deployment / Build (push) Has been skipped
Blog Deployment / Deploy-Staging (push) Successful in 10s
Blog Deployment / Test-Staging (push) Successful in 2s
Blog Deployment / Merge (push) Successful in 9s
Blog Deployment / Deploy-Production (push) Successful in 8s
Blog Deployment / Test-Production (push) Successful in 2s
Blog Deployment / Clean (push) Has been skipped
Blog Deployment / Notify (push) Successful in 2s
2026-04-10 15:38:28 +02:00
4cc467b0db Merge branch 'main' into preview
All checks were successful
Blog Test / Check-Rebuild (push) Successful in 8s
Blog Test / Build (push) Has been skipped
Blog Test / Deploy-Test (push) Successful in 10s
Blog Test / Test (push) Successful in 2s
Blog Deployment / Check-Rebuild (push) Successful in 16s
Blog Deployment / Build (push) Successful in 39s
Blog Deployment / Deploy-Staging (push) Successful in 9s
Blog Deployment / Test-Staging (push) Successful in 34s
Blog Deployment / Merge (push) Successful in 9s
Blog Deployment / Deploy-Production (push) Successful in 10s
Blog Deployment / Test-Production (push) Successful in 2s
Blog Deployment / Clean (push) Successful in 3s
Blog Deployment / Notify (push) Successful in 2s
2026-04-03 12:45:14 +00:00
1712356889 fix: no-redirect (#12)
Some checks failed
Blog Deployment / Check-Rebuild (push) Successful in 7s
Blog Deployment / Build (push) Has been skipped
Blog Deployment / Deploy-Staging (push) Successful in 12s
Blog Deployment / Test-Staging (push) Successful in 3s
Blog Deployment / Merge (push) Failing after 8s
Blog Deployment / Deploy-Production (push) Has been skipped
Blog Deployment / Test-Production (push) Has been skipped
Blog Deployment / Clean (push) Has been skipped
Blog Deployment / Notify (push) Successful in 3s
Reviewed-on: #12
2026-04-03 14:43:06 +02:00
217 changed files with 901 additions and 621 deletions

View File

@@ -108,7 +108,7 @@ jobs:
cd /blog
docker compose down ${CONTAINER_NAME}
docker compose up -d ${CONTAINER_NAME}
sleep 5
sleep 30
echo "- Displaying container logs"
docker compose logs ${CONTAINER_NAME}
@@ -163,7 +163,7 @@ jobs:
cd /blog
docker compose down ${CONTAINER_NAME}
docker compose up -d ${CONTAINER_NAME}
sleep 5
sleep 30
echo "- Displaying container logs"
docker compose logs ${CONTAINER_NAME}
@@ -194,7 +194,10 @@ jobs:
steps:
- name: Remove Old Docker Image
run: |
docker image rm ${{ needs.Check-Rebuild.outputs.current_docker_image }} --force
IMAGE_IDS=$(docker image ls "${DOCKER_IMAGE}" 2>/dev/null | awk '$NF != "U" && NR>1 {print $2}')
if [ -n "$IMAGE_IDS" ]; then
docker image rm $IMAGE_IDS
fi
Notify:
needs: [Check-Rebuild, Build, Deploy-Staging, Test-Staging, Merge, Deploy-Production, Test-Production, Clean]

View File

@@ -109,7 +109,7 @@ jobs:
cd /blog
docker compose down ${CONTAINER_NAME}
BLOG_TEST_BRANCH=${{ gitea.ref_name }} docker compose up -d ${CONTAINER_NAME}
sleep 5
sleep 30
echo "- Displaying container logs"
docker compose logs ${CONTAINER_NAME}

View File

Before

Width:  |  Height:  |  Size: 386 KiB

After

Width:  |  Height:  |  Size: 386 KiB

View File

Before

Width:  |  Height:  |  Size: 295 KiB

After

Width:  |  Height:  |  Size: 295 KiB

View File

Before

Width:  |  Height:  |  Size: 568 KiB

After

Width:  |  Height:  |  Size: 568 KiB

View File

@@ -122,9 +122,9 @@ La meilleure solution que j'ai trouvée a été de percer deux trous de 40 mm a
Voici à quoi ça ressemble :
![Front view of my homelab with legend](img/homelab-rack-legend.png)
![Vue de face de mon homelab avec légende](images/homelab-rack-legend.png)
![Different views of my homelab with open and closed enclosure](img/homelab-enclore-open-closed.png)
![Différentes vues de mon homelab avec armoire ouverte et fermée](images/homelab-enclore-open-closed.png)
---
## Stack Logicielle
@@ -183,7 +183,7 @@ Cette configuration de proxy à deux couches centralise la gestion des certifica
Pour un accès distant sécurisé, j'ai configuré **WireGuard** sur OPNsense. Ce VPN léger fournit une connectivité chiffrée à mon lab où que je sois, permettant ainsi de gérer tous mes services sans les exposer directement à Internet.
#### Schéma Réseau
![Diagram of my home network ](img/homelab-network-schema.png)
![Schéma de mon réseau domestique](images/homelab-network-schema.png)
### Application

View File

@@ -121,9 +121,9 @@ Inside the rack, I also added two 80mm fans to help with airflow. To keep everyt
Here what is look like:
![Front view of my homelab with legend](img/homelab-rack-legend.png)
![Front view of my homelab with legend](images/homelab-rack-legend.png)
![Different views of my homelab with open and closed enclosure](img/homelab-enclore-open-closed.png)
![Different views of my homelab with open and closed enclosure](images/homelab-enclore-open-closed.png)
---
@@ -184,7 +184,7 @@ This two-layer proxy setup centralizes SSL certificate management in **Caddy** w
For secure remote access, I configured **WireGuard** on OPNsense. This lightweight VPN provides encrypted connectivity to my lab from anywhere, allowing management of all my services without exposing them all directly to the internet.
#### Network Diagram
![Diagram of my home network ](img/homelab-network-schema.png)
![Diagram of my home network ](images/homelab-network-schema.png)
### Application
Let's dive into the fun part! What started as a modest setup meant to serve a few personal needs quickly turned into a full ecosystem of open source services, each solving a specific need or just satisfying curiosity.

View File

Before

Width:  |  Height:  |  Size: 108 KiB

After

Width:  |  Height:  |  Size: 108 KiB

View File

@@ -32,7 +32,7 @@ Tout d'abord, nous devons télécharger une image compatible cloud-init. Bien qu
Trouvez des images compatibles cloud dans le [Guide des images OpenStack](https://docs.openstack.org/image-guide/obtain-images.html).
Dans Proxmox, accédez à **Storage > ISO Images > Upload** pour uploader l'image téléchargée.
![Download window for ISO images in Proxmox](img/proxmox-download-iso-img.png)
![Fenêtre de téléchargement pour images ISO dans Proxmox](images/proxmox-download-iso-img.png)
## Créer la VM
Ensuite, on crée une VM en utilisant la ligne de commande (CLI) depuis le nœud Proxmox avec la commande suivantes :

View File

@@ -32,7 +32,7 @@ First, we need to download an image with cloud-init support. Although Rocky Linu
Find cloud-ready images from the [OpenStack Image Guide](https://docs.openstack.org/image-guide/obtain-images.html).
In Proxmox, navigate to **Storage > ISO Images > Upload** to upload the downloaded image.
![Download window for ISO images in Proxmox](img/proxmox-download-iso-img.png)
![Download window for ISO images in Proxmox](images/proxmox-download-iso-img.png)
## Create the VM

Binary file not shown.

After

Width:  |  Height:  |  Size: 295 KiB

View File

Before

Width:  |  Height:  |  Size: 44 KiB

After

Width:  |  Height:  |  Size: 44 KiB

View File

@@ -21,7 +21,7 @@ Ce genre dexercice est la pire chose que vous souhaitez voir arriver, parce q
Ma box OPNsense tournait parfaitement depuis des mois. Routeur, pare-feu, DNS, DHCP, VLANs, VPN, reverse proxy et même contrôleur UniFi : toutes les pièces de mon homelab passe par elle. Mais pas seulement, elle fournit aussi Internet à la maison.
![Diagram of my home network ](img/homelab-network-schema.png)
![Le schéma réseau de mon Homelab](images/homelab-network-schema.png)
Cette box est le cœur de mon réseau, sans elle, je ne peux quasiment rien faire. Jai détaillé son fonctionnement dans ma section [Homelab]({{< ref "page/homelab" >}}). Tout “fonctionnait juste”, et je ne men inquiétait pas. Jétais confiant, sa sauvegarde vivait uniquement à lintérieur de la machine…
@@ -61,7 +61,7 @@ pkg: sqlite error while executing iterator in file pkgdb_iterator.c:1110: databa
```
🚨 Mon alarme interne s'est déclenchée. Jai pensé aux sauvegardes et jai immédiatement téléchargé la dernière :
![Backup configuration in OPNsense](img/opnsense-download-backup.png)
![Sauvegarde de configuration dans OPNsense](images/opnsense-download-backup.png)
En cliquant sur le bouton `Download configuration`, jai récupéré le `config.xml` en cours dutilisation. Je pensais que ça suffirait.

View File

@@ -21,7 +21,7 @@ This kind of exercise is the worst thing you want to happen because it's never f
My OPNsense box had been running smoothly for months. Router, firewall, DNS, DHCP, VLANs, VPN, reverse proxy and even UniFi controller: all the pieces of my homelab run through it. but not only, it is also serving internet at home.
![Diagram of my home network ](img/homelab-network-schema.png)
![My Homelab network diagram](images/homelab-network-schema.png)
This box is the heart of my network, without it, I can hardly do anything. I have detailed how this is working in my [Homelab]({{< ref "page/homelab" >}}) section. It was “just working,” and I wasnt worried about it. I felt confident, its backup was living only inside the machine...
@@ -62,7 +62,7 @@ pkg: sqlite error while executing iterator in file pkgdb_iterator.c:1110: databa
```
🚨 My internal alarm sensor triggered, I wondered about backups, I immediately decided to download the latest backup:
![Backup configuration in OPNsense](img/opnsense-download-backup.png)
![Backup configuration in OPNsense](images/opnsense-download-backup.png)
Clicking the `Download configuration` button, I downloaded the current `config.xml` in use my the instance, I though it was enough.

View File

Before

Width:  |  Height:  |  Size: 77 KiB

After

Width:  |  Height:  |  Size: 77 KiB

View File

Before

Width:  |  Height:  |  Size: 190 KiB

After

Width:  |  Height:  |  Size: 190 KiB

View File

Before

Width:  |  Height:  |  Size: 44 KiB

After

Width:  |  Height:  |  Size: 44 KiB

View File

Before

Width:  |  Height:  |  Size: 45 KiB

After

Width:  |  Height:  |  Size: 45 KiB

View File

Before

Width:  |  Height:  |  Size: 29 KiB

After

Width:  |  Height:  |  Size: 29 KiB

View File

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 25 KiB

View File

@@ -13,7 +13,7 @@ categories:
## Intro
Quand jai construit mon cluster **Proxmox VE 8** pour la première fois, le réseau nétait pas ma priorité. Je voulais simplement remplacer rapidement un vieux serveur physique, alors jai donné la même configuration de base à chacun de mes trois nœuds, créé le cluster et commencé à créer des VM :
![Configuration réseau dun nœud Proxmox](img/proxmox-node-network-configuration.png)
![Configuration réseau dun nœud Proxmox](images/proxmox-node-network-configuration.png)
Cela a bien fonctionné pendant un moment. Mais comme je prévois de virtualiser mon routeur **OPNsense**, jai besoin de quelque chose de plus structuré et cohérent. Cest là que la fonctionnalité **S**oftware-**D**efined **N**etworking (SDN) de Proxmox entre en jeu.
@@ -21,7 +21,7 @@ Cela a bien fonctionné pendant un moment. Mais comme je prévois de virtualiser
## Mon Réseau Homelab
Par défaut, chaque nœud Proxmox dispose de sa propre zone locale, appelée `localnetwork`, qui contient le pont Linux par défaut (`vmbr0`) comme VNet :
![Proxmox default `localnetwork` zones](img/proxmox-default-localnetwork-zone.png)
![Zones `localnetwork` par défaut dans Proxmox](images/proxmox-default-localnetwork-zone.png)
Cest suffisant pour des configurations isolées, mais rien nest coordonné au niveau du cluster.
@@ -61,29 +61,29 @@ Proxmox prend en charge plusieurs types de zones :
- **EVPN** : VXLAN avec BGP pour du routage L3 dynamique
Comme mon réseau domestique utilise déjà des VLAN, jai créé une **zone VLAN** appelée `homelan`, en utilisant `vmbr0` comme pont et en lappliquant à tout le cluster :
![Create a VLAN zone in the Proxmox SDN](img/proxmox-create-vlan-zone-homelan.png)
![Création dune zone VLAN dans Proxmox SDN](images/proxmox-create-vlan-zone-homelan.png)
### VNets
Un **VNet** est un réseau virtuel à lintérieur dune zone. Dans une zone VLAN, chaque VNet correspond à un ID VLAN spécifique.
Jai commencé par créer `vlan55` dans la zone `homelan` pour mon réseau DMZ :
![Create a VNet for VLAN 55 in the homelan zone](img/proxmox-create-vlan-vnet-homelan.png)
![Création dun VNet pour le VLAN 55 dans la zone homelan](images/proxmox-create-vlan-vnet-homelan.png)
Puis jai ajouté les VNets correspondant à la plupart de mes VLAN, puisque je prévois de les rattacher à une VM OPNsense :
![All my VLANs created in the Proxmox SDN](img/proxmox-sdn-all-vlan-homelan.png)
![Tous mes VLANs créés dans le Proxmox SDN](images/proxmox-sdn-all-vlan-homelan.png)
Enfin, jai appliqué la configuration dans **Datacenter → SDN** :
![Application de la configuration SDN dans Proxmox](img/proxmox-apply-sdn-homelan-configuration.png)
![Application de la configuration SDN dans Proxmox](images/proxmox-apply-sdn-homelan-configuration.png)
---
## Test de la Configuration Réseau
Dans une vieille VM que je n'utilise plus, je remplace l'actuel `vmbr0` avec le VLAN tag 66 par mon nouveau VNet `vlan66`:
![Change the network bridge in a VM](img/proxmox-change-vm-nic-vlan-vnet.png)
![Changement du pont réseau dans une VM](images/proxmox-change-vm-nic-vlan-vnet.png)
Après l'avoir démarrée, la VM obtient une IP du DHCP d'OPNsense sur ce VLAN, ce qui est super. J'essaye également de ping une autre machine et ça fonctionne :
![Ping another machine in the same VLAN](img/proxmox-console-ping-vm-vlan-66.png)
![Ping dune autre machine dans le même VLAN](images/proxmox-console-ping-vm-vlan-66.png)
---
## Mise à jour de Cloud-Init et Terraform
@@ -92,7 +92,7 @@ Pour aller plus loin, jai mis à jour le pont réseau utilisé dans mon **tem
Comme avec la VM précédente, jai remplacé `vmbr0` et le tag VLAN 66 par le nouveau VNet `vlan66`.
Jai aussi adapté mon code **Terraform** pour refléter ce changement :
![Mise à jour du code Terraform pour vlan66](img/terraform-code-update-vlan66.png)
![Mise à jour du code Terraform pour vlan66](images/terraform-code-update-vlan66.png)
Ensuite, jai validé quaucune régression nétait introduite en déployant une VM de test :
```bash
@@ -129,7 +129,7 @@ vm_ip = "192.168.66.181"
```
La création sest déroulée sans problème, tout est bon :
![VM déployée par Terraform sur vlan66](img/proxmox-terraform-test-deploy-vlan66.png)
![VM déployée par Terraform sur vlan66](images/proxmox-terraform-test-deploy-vlan66.png)
---
## Conclusion

View File

@@ -13,7 +13,7 @@ categories:
## Intro
When I first built my **Proxmox VE 8** cluster, networking wasnt my main concern. I just wanted to replace an old physical server quickly, so I gave each of my three nodes the same basic config, created the cluster, and started running VMs:
![Configuration réseau dun nœud Proxmox](img/proxmox-node-network-configuration.png)
![Proxmox node network configuration](images/proxmox-node-network-configuration.png)
That worked fine for a while. But as I plan to virtualize my **OPNsense** router, I need something more structured and consistent. This is where Proxmox **S**oftware-**D**efined **N**etworking (SDN) feature comes in.
@@ -21,7 +21,7 @@ That worked fine for a while. But as I plan to virtualize my **OPNsense** router
## My Homelab Network
By default, every Proxmox node comes with its own local zone, called `localnetwork`, which contains the default Linux bridge (`vmbr0`) as a VNet:
![Proxmox default `localnetwork` zones](img/proxmox-default-localnetwork-zone.png)
![Proxmox default `localnetwork` zones](images/proxmox-default-localnetwork-zone.png)
Thats fine for isolated setups, but at the cluster level nothing is coordinated.
@@ -61,29 +61,29 @@ Proxmox supports several zone types:
- **EVPN**: VXLAN with BGP to establish Layer 3 routing
Since my home network already relies on VLANs, I created a **VLAN Zone** named `homelan`, using `vmbr0` as the bridge and applying it cluster-wide:
![Create a VLAN zone in the Proxmox SDN](img/proxmox-create-vlan-zone-homelan.png)
![Create a VLAN zone in the Proxmox SDN](images/proxmox-create-vlan-zone-homelan.png)
### VNets
A **VNet** is a virtual network inside a zone. In a VLAN zone, each VNet corresponds to a specific VLAN ID.
I started by creating `vlan55` in the `homelan` zone for my DMZ network:
![Create a VNet for VLAN 55 in the homelan zone](img/proxmox-create-vlan-vnet-homelan.png)
![Create a VNet for VLAN 55 in the homelan zone](images/proxmox-create-vlan-vnet-homelan.png)
Then I added VNets for most of my VLANs, since I plan to attach them to an OPNsense VM:
![All my VLANs created in the Proxmox SDN](img/proxmox-sdn-all-vlan-homelan.png)
![All my VLANs created in the Proxmox SDN](images/proxmox-sdn-all-vlan-homelan.png)
Finally, I applied the configuration in **Datacenter → SDN**:
![Application de la configuration SDN dans Proxmox](img/proxmox-apply-sdn-homelan-configuration.png)
![Apply SDN configuration in Proxmox](images/proxmox-apply-sdn-homelan-configuration.png)
---
## Test the Network Configuration
In a old VM which I don't use anymore, I replace the current `vmbr0` with VLAN tag 66 to my new VNet `vlan66`:
![Change the network bridge in a VM](img/proxmox-change-vm-nic-vlan-vnet.png)
![Change the network bridge in a VM](images/proxmox-change-vm-nic-vlan-vnet.png)
After starting it, the VM gets an IP from the DHCP on OPNsense on that VLAN, which sounds good. I also try to ping another machine and it works:
![Ping another machine in the same VLAN](img/proxmox-console-ping-vm-vlan-66.png)
![Ping another machine in the same VLAN](images/proxmox-console-ping-vm-vlan-66.png)
---
## Update Cloud-Init Template and Terraform
@@ -91,7 +91,7 @@ After starting it, the VM gets an IP from the DHCP on OPNsense on that VLAN, whi
To go further, I update the bridge used in my **cloud-init** template, which I detailed the creation in that [post]({{< ref "post/1-proxmox-cloud-init-vm-template" >}}). Pretty much the same thing I've done with the VM, I replace the current `vmbr0` with VLAN tag 66 with my new VNet `vlan66`.
I also update the **Terrafom** code to take this change into account:
![Mise à jour du code Terraform pour vlan66](img/terraform-code-update-vlan66.png)
![Terraform code change for the vlan66](images/terraform-code-update-vlan66.png)
I quicky check if I don't have regression and can still deploy a VM with Terraform:
```bash
@@ -128,7 +128,7 @@ vm_ip = "192.168.66.181"
```
The VM is deploying without any issue, everything is OK:
![VM déployée par Terraform sur vlan66](img/proxmox-terraform-test-deploy-vlan66.png)
![VM hardware in Proxmox deployed by Terraform](images/proxmox-terraform-test-deploy-vlan66.png)
---
## Conclusion

View File

Before

Width:  |  Height:  |  Size: 148 KiB

After

Width:  |  Height:  |  Size: 148 KiB

View File

Before

Width:  |  Height:  |  Size: 139 KiB

After

Width:  |  Height:  |  Size: 139 KiB

View File

Before

Width:  |  Height:  |  Size: 136 KiB

After

Width:  |  Height:  |  Size: 136 KiB

View File

Before

Width:  |  Height:  |  Size: 39 KiB

After

Width:  |  Height:  |  Size: 39 KiB

View File

@@ -29,7 +29,7 @@ Au sommet de mon installation, mon modem FAI, une _Freebox_ en mode bridge, reli
Ce switch relie également mes trois nœuds Proxmox, chacun sur un port trunk avec le même VLAN natif. Chaque nœud dispose de deux cartes réseau : une pour le trafic général, et lautre dédiée au réseau de stockage Ceph, connecté à un switch séparé de 2,5 Gbps.
Depuis le crash dOPNsense, jai simplifié larchitecture en supprimant le lien LACP, qui napportait pas de réelle valeur :
![Current homelab network diagram](img/homelan-current-physical-layout.png)
![Schéma réseau du homelab actuel](images/homelan-current-physical-layout.png)
Jusquà récemment, le réseau Proxmox de mon cluster était très basique : chaque nœud était configuré individuellement sans véritable logique commune. Cela a changé après la découverte du SDN Proxmox, qui ma permis de centraliser les définitions de VLAN sur lensemble du cluster. Jai décrit cette étape dans [cet article]({{< ref "post/11-proxmox-cluster-networking-sdn" >}}).
@@ -43,7 +43,7 @@ Place au lab. Voici les étapes principales :
4. Configurer la haute disponibilité
5. Tester la bascule
![Diagram of the POC for OPNsense high availability](img/poc-opnsense-diagram.png)
![Schéma du POC pour OPNsense en haute disponibilité](images/poc-opnsense-diagram.png)
### Ajouter des VLANs dans mon homelab
@@ -53,7 +53,7 @@ Pour cette expérimentation, je crée trois nouveaux VLANs :
- **VLAN 103** : _POC pfSync_
Dans linterface Proxmox, je vais dans `Datacenter` > `SDN` > `VNets` et je clique sur `Create` :
![Create POC VLANs in the Proxmox SDN](img/proxmox-sdn-create-poc-vlans.png)
![Création des VLANs POC dans le SDN Proxmox](images/proxmox-sdn-create-poc-vlans.png)
Une fois les trois VLANs créés, japplique la configuration.
@@ -114,7 +114,7 @@ La VM `fake-freebox` est maintenant prête à fournir du DHCP sur le VLAN 101, a
### Construire les VMs OPNsense
Je commence par télécharger lISO dOPNsense et je lupload sur un de mes nœuds Proxmox :
![Upload de lISO OPNsense dans Proxmox](img/proxmox-upload-opnsense-iso.png)
![Upload de lISO OPNsense dans Proxmox](images/proxmox-upload-opnsense-iso.png)
#### Création de la VM
@@ -128,69 +128,69 @@ Je crée la première VM `poc-opnsense-1` avec les paramètres suivants :
1. VLAN 101 (_POC WAN_)
2. VLAN 102 (_POC LAN_)
3. VLAN 103 (_POC pfSync_)
![OPNsense VM settings in Proxmox](img/proxmox-create-poc-vm-opnsense.png)
![Paramètres de la VM OPNsense dans Proxmox](images/proxmox-create-poc-vm-opnsense.png)
Avant de la démarrer, je clone cette VM pour préparer la seconde : `poc-opnsense-2`
Au premier démarrage, je tombe sur une erreur “access denied”. Pour corriger, jentre dans le BIOS, **Device Manager > Secure Boot Configuration**, je décoche _Attempt Secure Boot_ et je redémarre :
![Disable Secure Boot in Proxmox BIOS](img/proxmox-disable-secure-boot-option.png)
![Désactiver Secure Boot dans le BIOS de Proxmox](images/proxmox-disable-secure-boot-option.png)
#### Installation dOPNsense
La VM démarre sur lISO, je ne touche à rien jusquà lécran de login :
![OPNsense CLI login screen in LiveCD](img/opnsense-vm-installation-welcome.png)
![Écran de login OPNsense en mode LiveCD](images/opnsense-vm-installation-welcome.png)
Je me connecte avec `installer` / `opnsense` et je lance linstallateur. Je sélectionne le disque QEMU de 20 Go comme destination et je démarre linstallation :
![Barre de progression de linstallation OPNsense](img/opnsense-vm-installation-progress-bar.png)
![Barre de progression de linstallation OPNsense](images/opnsense-vm-installation-progress-bar.png)
Une fois terminé, je retire lISO du lecteur et je redémarre la machine.
#### Configuration de Base dOPNsense
Au redémarrage, je me connecte avec `root` / `opnsense` et jarrive au menu CLI :
![Menu CLI après une installation fraîche dOPNsense](img/opnsense-vm-installation-cli-menu.png)
![Menu CLI après une installation fraîche dOPNsense](images/opnsense-vm-installation-cli-menu.png)
Avec loption 1, je réassigne les interfaces :
![Configuration des interfaces dans OPNsense via le CLI](img/opnsense-vm-installation-assign-interfaces.png)
![Configuration des interfaces dans OPNsense via le CLI](images/opnsense-vm-installation-assign-interfaces.png)
Linterface WAN récupère bien `10.101.0.150/24` depuis la `fake-freebox`. Je configure le LAN sur `10.102.0.2/24` et jajoute un pool DHCP de `10.102.0.10` à `10.102.0.99` :
![Interface WAN OPNsense recevant une IP depuis la VM `fake-freebox`](img/opnsense-vm-installation-interfaces-configured.png)
![Interface WAN OPNsense recevant une IP depuis la VM `fake-freebox`](images/opnsense-vm-installation-interfaces-configured.png)
✅ La première VM est prête, je reproduis lopération pour la seconde OPNsense `poc-opnsense-2`, qui aura lIP `10.102.0.3`.
### Configurer OPNsense en Haute Disponibilité
Avec les deux VMs OPNsense opérationnelles, il est temps de passer à la configuration via le WebGUI. Pour y accéder, jai connecté une VM Windows au VLAN _POC LAN_ et ouvert lIP de lOPNsense sur le port 443 :
![OPNsense WebGUI depuis une VM Windows](img/opnsense-vm-webgui-from-poc-lan.png)
![OPNsense WebGUI depuis une VM Windows](images/opnsense-vm-webgui-from-poc-lan.png)
#### Ajouter lInterface pfSync
La troisième carte réseau (`vtnet2`) est assignée à linterface _pfSync_. Ce réseau dédié permet aux deux firewalls de synchroniser leurs états via le VLAN _POC pfSync_ :
![Add pfSync interface in OPNsense](img/opnsense-vm-assign-pfsync-interface.png)
![Ajouter linterface pfSync dans OPNsense](images/opnsense-vm-assign-pfsync-interface.png)
Jactive linterface sur chaque instance et je leur attribue une IP statique :
- **poc-opnsense-1** : `10.103.0.2/24`
- **poc-opnsense-2** : `10.103.0.3/24`
Puis, jajoute une règle firewall sur chaque nœud pour autoriser tout le trafic provenant de ce réseau sur linterface _pfSync_ :
![Create new firewall rule on pfSync interface to allow any traffic in that network](img/opnsense-vm-firewall-allow-pfsync.png)
![Règle firewall pour autoriser tout le trafic pfSync](images/opnsense-vm-firewall-allow-pfsync.png)
#### Configurer la Haute Disponibilité
Direction `System` > `High Availability` > `Settings`.
- Sur le master (`poc-opnsense-1`), je configure les `General Settings` et les `Synchronization Settings`.
- Sur le backup (`poc-opnsense-2`), seuls les `General Settings` suffisent (on ne veut pas quil écrase la config du master).
![OPNsense High Availability settings](img/opnsense-vm-high-availability-settings.png)
![Paramètres de Haute Disponibilité dans OPNsense](images/opnsense-vm-high-availability-settings.png)
Une fois appliqué, je vérifie la synchro dans longlet `Status` :
![OPNsense High Availability status](img/opnsense-vm-high-availability-status.png)
![Statut de la Haute Disponibilité OPNsense](images/opnsense-vm-high-availability-status.png)
#### Créer une IP Virtuelle
Pour fournir une passerelle partagée aux clients, je crée une IP virtuelle (VIP) en **CARP** (Common Address Redundancy Protocol) sur linterface LAN. LIP est portée par le nœud actif et bascule automatiquement en cas de failover.
Menu : `Interfaces` > `Virtual IPs` > `Settings` :
![Create CARP virtual IP in OPNsense](img/opnsense-vm-create-vip-carp.png)
![Création dune VIP CARP dans OPNsense](images/opnsense-vm-create-vip-carp.png)
Je réplique ensuite la config depuis `System > High Availability > Status` avec le bouton `Synchronize and reconfigure all`.
@@ -205,7 +205,7 @@ Sur le master :
- `DHCP ranges` : cocher aussi `Disable HA sync`
- `DHCP options` : ajouter loption `router [3]` avec la valeur `10.102.0.1` (VIP LAN)
- `DHCP options` : cloner la règle pour `dns-server [6]` vers la même VIP.
![Edit DHCP options for Dnsmasq in OPNsense](img/opnsense-vm-dnsmasq-add-option.png)
![Options DHCP dans Dnsmasq](images/opnsense-vm-dnsmasq-add-option.png)
Sur le backup :
- `Services` > `Dnsmasq DNS & DHCP` > `General` : cocher `Disable HA sync`
@@ -262,7 +262,7 @@ if ($type === "MASTER") {
Passons aux tests !
OPNsense propose un _CARP Maintenance Mode_. Avec le master actif, seul lui avait son WAN monté. En activant le mode maintenance, les rôles basculent : le master devient backup, son WAN est désactivé et celui du backup est activé :
![Mode maintenance CARP dans OPNsense](img/opnsense-vm-carp-status.png)
![Mode maintenance CARP dans OPNsense](images/opnsense-vm-carp-status.png)
Pendant mes pings vers lextérieur, aucune perte de paquets au moment du basculement.

View File

@@ -29,7 +29,7 @@ On top of my setup, my ISP modem, a *Freebox* in bridge mode, connects directly
The switch also connects my three Proxmox nodes, each on trunk ports with the same native VLAN. Every node has two NICs: one for general networking and the other dedicated to the Ceph storage network, which runs through a separate 2.5 Gbps switch.
Since the OPNsense crash, Ive simplified things by removing the LACP link, it wasnt adding real value:
![Current homelab network diagram](img/homelan-current-physical-layout.png)
![Current homelab network diagram](images/homelan-current-physical-layout.png)
Until recently, Proxmox networking on my cluster was very basic: each node was configured individually with no real overlay logic. That changed after I explored Proxmox SDN, where I centralized VLAN definitions across the cluster. I described that step in [this article]({{< ref "post/11-proxmox-cluster-networking-sdn" >}}).
@@ -44,7 +44,7 @@ Time to move into the lab. Here are the main steps:
4. Configure high availability
5. Test failover
![Diagram of the POC for OPNsense high availability](img/poc-opnsense-diagram.png)
![Diagram of the POC for OPNsense high availability](images/poc-opnsense-diagram.png)
### Add VLANs in my Homelab
@@ -54,7 +54,7 @@ For this experiment, I create 3 new VLANs:
- **VLAN 103**: *POC pfSync*
In the Proxmox UI, I navigate to `Datacenter` > `SDN` > `VNets` and I click `Create`:
![Create POC VLANs in the Proxmox SDN](img/proxmox-sdn-create-poc-vlans.png)
![Create POC VLANs in the Proxmox SDN](images/proxmox-sdn-create-poc-vlans.png)
Once the 3 new VLAN have been created, I apply the configuration.
@@ -115,7 +115,7 @@ The `fake-freebox` VM is now ready to serve DHCP on VLAN 101 and serve only one
### Build OPNsense VMs
First I download the OPNsense ISO and upload it to one of my Proxmox nodes:
![Upload de lISO OPNsense dans Proxmox](img/proxmox-upload-opnsense-iso.png)
![Upload the OPNsense ISO into Proxmox](images/proxmox-upload-opnsense-iso.png)
#### VM Creation
@@ -129,69 +129,69 @@ I create the first VM `poc-opnsense-1`, with the following settings:
1. VLAN 101 (POC WAN)
2. VLAN 102 (POC LAN)
3. VLAN 103 (POC pfSync)
![OPNsense VM settings in Proxmox](img/proxmox-create-poc-vm-opnsense.png)
![OPNsense VM settings in Proxmox](images/proxmox-create-poc-vm-opnsense.png)
Before booting it, I clone this VM to prepare the second one: `poc-opnsense-2`
On first boot, I hit an “access denied” error. To fix this, I enter the BIOS, go to **Device Manager > Secure Boot Configuration**, uncheck _Attempt Secure Boot_, and restart the VM:
![Disable Secure Boot in Proxmox BIOS](img/proxmox-disable-secure-boot-option.png)
![Disable Secure Boot in Proxmox BIOS](images/proxmox-disable-secure-boot-option.png)
#### OPNsense Installation
The VM boots on the ISO, I touch nothing until I get into the login screen:
![OPNsense CLI login screen in LiveCD](img/opnsense-vm-installation-welcome.png)
![OPNsense CLI login screen in LiveCD](images/opnsense-vm-installation-welcome.png)
I log in as `installer` / `opnsense` and launch the installer. I select the QEMU hard disk of 20GB as destination and launch the installation:
![Barre de progression de linstallation OPNsense](img/opnsense-vm-installation-progress-bar.png)
![OPNsense installation progress bar](images/opnsense-vm-installation-progress-bar.png)
Once the installation is finished, I remove the ISO from the drive and restart the machine.
#### OPNsense Basic Configuration
After reboot, I log in as `root` / `opnsense` and get into the CLI menu:
![Menu CLI après une installation fraîche dOPNsense](img/opnsense-vm-installation-cli-menu.png)
![OPNsense CLI login screen after fresh installation](images/opnsense-vm-installation-cli-menu.png)
Using option 1, I reassigned interfaces:
![Configuration des interfaces dans OPNsense via le CLI](img/opnsense-vm-installation-assign-interfaces.png)
![OPNsense interface configuration using CLI](images/opnsense-vm-installation-assign-interfaces.png)
The WAN interface successfully pulled `10.101.0.150/24` from the `fake-freebox`. I set the LAN interface to `10.102.0.2/24` and configured a DHCP pool from `10.102.0.10` to `10.102.0.99`:
![Interface WAN OPNsense recevant une IP depuis la VM `fake-freebox`](img/opnsense-vm-installation-interfaces-configured.png)
![OPNsense WAN interface getting IP from `fake-freebox` VM](images/opnsense-vm-installation-interfaces-configured.png)
✅ The first VM is ready, I start over for the second OPNsense VM, `poc-opnsense-2` which will have the IP `10.102.0.3`
### Configure OPNsense Highly Available
With both OPNsense VMs operational, its time to configure them from the WebGUI. To access the interface, I connected a Windows VM into the _POC LAN_ VLAN and browsed to the OPNsense IP on port 443:
![OPNsense WebGUI depuis une VM Windows](img/opnsense-vm-webgui-from-poc-lan.png)
![OPNsense WebGUI from Windows VM](images/opnsense-vm-webgui-from-poc-lan.png)
#### Add pfSync Interface
The third NIC (`vtnet2`) is assigned to the _pfSync_ interface. This dedicated network allows the two firewalls to synchronize states on the VLAN *POC pfSync*:
![Add pfSync interface in OPNsense](img/opnsense-vm-assign-pfsync-interface.png)
![Add pfSync interface in OPNsense](images/opnsense-vm-assign-pfsync-interface.png)
I enable the interface on each instance and configure it with a static IP address:
- **poc-opnsense-1**: `10.103.0.2/24`
- **poc-opnsense-2**: `10.103.0.3/24`
Then, I add a firewall rule on each node to allow all traffic coming from this network on that *pfSync* interface:
![Create new firewall rule on pfSync interface to allow any traffic in that network](img/opnsense-vm-firewall-allow-pfsync.png)
![Create new firewall rule on pfSync interface to allow any traffic in that network](images/opnsense-vm-firewall-allow-pfsync.png)
#### Setup High Availability
Next, in `System` > `High Availability` > `Settings`.
- On the master (`poc-opnsense-1`), I configure both the `General Settings` and the `Synchronization Settings`.
- On the backup (`poc-opnsense-2`), only `General Settings` are needed, you don't want your backup overwrite the master config.
![OPNsense High Availability settings](img/opnsense-vm-high-availability-settings.png)
![OPNsense High Availability settings](images/opnsense-vm-high-availability-settings.png)
Once applied, I verify synchronization on the `Status` page:
![OPNsense High Availability status](img/opnsense-vm-high-availability-status.png)
![OPNsense High Availability status](images/opnsense-vm-high-availability-status.png)
#### Create Virtual IP Address
To provide a shared gateway for clients, I create a CARP Virtual IP (VIP) on the LAN interface. It is using the Common Address Redundancy Protocol. This IP is claimed by the active node and automatically fails over.
Navigate to `Interfaces` > `Virtual IPs` > `Settings`:
![Create CARP virtual IP in OPNsense](img/opnsense-vm-create-vip-carp.png)
![Create CARP virtual IP in OPNsense](images/opnsense-vm-create-vip-carp.png)
To replicate the config, I go to `System > High Availability > Status` and click the button next to `Synchronize and reconfigure all`.
@@ -206,7 +206,7 @@ On the master:
- `DHCP ranges`: also tick the `Disable HA sync` box
- `DHCP options`: add the option `router [3]` with the value `10.102.0.1` (LAN VIP)
- `DHCP options`: clone the rule for `router [6]` pointing to the same VIP.
![Edit DHCP options for Dnsmasq in OPNsense](img/opnsense-vm-dnsmasq-add-option.png)
![Edit DHCP options for Dnsmasq in OPNsense](images/opnsense-vm-dnsmasq-add-option.png)
On the backup:
- `Services` > `Dnsmasq DNS & DHCP` > `General`: also tick the `Disable HA sync` box
@@ -264,7 +264,7 @@ if ($type === "MASTER") {
Time for the real test!
OPNsense provides a _CARP Maintenance Mode_. With the master active, WAN was enabled only on that node. Entering maintenance mode flipped the roles: the master became backup, its WAN disabled, while the backup enabled its WAN:
![Mode maintenance CARP dans OPNsense](img/opnsense-vm-carp-status.png)
![OPNsense CARP maintenance mode](images/opnsense-vm-carp-status.png)
While pinging outside the network, I observed zero packet loss during the failover.

View File

Before

Width:  |  Height:  |  Size: 123 KiB

After

Width:  |  Height:  |  Size: 123 KiB

View File

Before

Width:  |  Height:  |  Size: 176 KiB

After

Width:  |  Height:  |  Size: 176 KiB

View File

Before

Width:  |  Height:  |  Size: 111 KiB

After

Width:  |  Height:  |  Size: 111 KiB

View File

Before

Width:  |  Height:  |  Size: 143 KiB

After

Width:  |  Height:  |  Size: 143 KiB

View File

Before

Width:  |  Height:  |  Size: 155 KiB

After

Width:  |  Height:  |  Size: 155 KiB

View File

Before

Width:  |  Height:  |  Size: 115 KiB

After

Width:  |  Height:  |  Size: 115 KiB

View File

Before

Width:  |  Height:  |  Size: 108 KiB

After

Width:  |  Height:  |  Size: 108 KiB

View File

@@ -84,7 +84,7 @@ Il est temps de mettre à jour, dans `System` > `Firmware` > `Status`, je v
Une fois mis à jour et redémarré, je vais dans `System` > `Firmware` > `Plugins`, je coche l'option pour afficher les plugins communautaires. J'installe que le **QEMU Guest Agent**, `os-qemu-guest-agent`, pour permettre la communication entre la VM et l'hôte Proxmox.
Cela nécessite un arrêt. Dans Proxmox, j'active le `QEMU Guest Agent` dans les options de la VM :
![Options d'une VM Proxmox avec QEMU Guest Agent activé](img/proxmox-opnsense-enable-qemu-guest-agent.png)
![Options d'une VM Proxmox avec QEMU Guest Agent activé](images/proxmox-opnsense-enable-qemu-guest-agent.png)
Finalement je redémarre la VM. Une fois démarrée, depuis la WebGUI de Proxmox, je peux voir les IPs de la VM ce qui confirme que le guest agent fonctionne.
@@ -92,7 +92,7 @@ Finalement je redémarre la VM. Une fois démarrée, depuis la WebGUI de Proxmox
## Interfaces
Sur les deux parefeu, j'assigne les NIC restantes à de nouvelles interfaces en ajoutant une description. Les VMs ont 7 interfaces, je compare attentivement les adresses MAC pour éviter de mélanger les interfaces :
![Assign interfaces menu in OPNsense](img/opnsense-assign-interfaces.png)
![Assignement des interfaces dans OPNsense](images/opnsense-assign-interfaces.png)
Au final, la configuration des interfaces ressemble à ceci :
@@ -160,13 +160,13 @@ La HA est configurée dans `System` > `High Availability` > `Settings`
### Statut de la HA
Dans `System` > `High Availability` > `Status`, je peux vérifier si la synchronisation fonctionne. Sur cette page je peux répliquer un ou tous les services du master vers le nœud backup :
![OPNsense high availability status page](img/opnsense-high-availability-status.png)
![Page de statut de la haute disponibilité dans OPNsense](images/opnsense-high-availability-status.png)
---
## IPs Virtuelles
Maintenant que la HA est configurée, je peux attribuer à mes réseaux une IP virtuelle partagée entre mes nœuds. Dans `Interfaces` > `Virtual IPs` > `Settings`, je crée un VIP pour chacun de mes réseaux en utilisant **CARP** (Common Address Redundancy Protocol). L'objectif est de réutiliser les adresses IP utilisées par mon instance OPNsense actuelle, mais comme elle route encore mon réseau, j'utilise des IP différentes pour la phase de configuration :
![Liste des IPs virtuelles dans OPNsense](img/opnsense-interface-virtual-ips.png)
![Liste des IPs virtuelles dans OPNsense](images/opnsense-interface-virtual-ips.png)
OPNsense permet CARP par défaut, aucune règle de parefeu spéciale requise
@@ -242,7 +242,7 @@ Pour commencer, dans `Firewall` > `Groups`, je crée 2 zones pour regrouper m
### Network Aliases
Ensuite, dans `Firewall` > `Aliases`, je crée un alias `InternalNetworks` pour regrouper tous mes réseaux internes :
![Création d'alias pour les réseaux locaux dansOPNsense](img/opnsense-create-alias-internalnetworks.png)
![Création d'alias pour les réseaux locaux dansOPNsense](images/opnsense-create-alias-internalnetworks.png)
### Règles de Pare-feu Rules
@@ -345,17 +345,17 @@ Sur le nœud backup, je le configure de la même manière, la seule différence
### Plages DHCP
Ensuite je configure les plages DHCP. Les deux parefeu auront des plages différentes, le nœud backup aura des plages plus petites (10 baux devraient suffire). Sur le master, elles sont configurées comme suit :
![OPNsense DHCP ranges in Dnsmasq](img/opnsense-dnsmasq-dhcp-ranges.png)
![Plages DHCP de Dnsmasq dans OPNsense](images/opnsense-dnsmasq-dhcp-ranges.png)
### Options DHCP
Puis je définis quelques options DHCP pour chaque domaine : le `router`, le `dns-server` et le `domain-name`. Je pointe les adresses IP vers la VIP de l'interface :
![OPNsense DHCP options in Dnsmasq](img/opnsense-dnsmasq-dhcp-options.png)
![Options DHCP de Dnsmasq dans OPNsense](images/opnsense-dnsmasq-dhcp-options.png)
### Hôtes
Enfin, dans l'onglet `Hosts`, je définis des mappings DHCP statiques mais aussi des IP statiques non gérées par le DHCP, pour qu'elles soient enregistrées dans le DNS :
![Hôtes DHCP de Dnsmasq dans OPNsense](img/opnsense-dnsmasq-dhcp-hosts.png)
![Hôtes DHCP de Dnsmasq dans OPNsense](images/opnsense-dnsmasq-dhcp-hosts.png)
---
## DNS
@@ -372,7 +372,7 @@ Unbound est le résolveur récursif, pour les zones locales j'effectue un forwar
### Paramètres Généraux d'Unbound
Configurons-le, dans `Services` > `Unbound DNS` > `General` :
![OPNsense Unbound DNS general settings](img/opnsense-unbound-general-settings.png)
![Paramètres généraux d'Unbound DNS dans OPNsense](images/opnsense-unbound-general-settings.png)
### Liste de Blocage DNS
@@ -383,7 +383,7 @@ Pour maintenir le service à jour, dans `System` > `Settings` > `Cron`, j'a
### Transfert de Requêtes
Enfin je configure le transfert de requêtes pour mes domaines locaux vers Dnsmasq. Dans `Services` > `Unbound DNS` > `Query Forwarding`, j'ajoute chacun de mes domaines locaux avec leurs reverse lookups (enregistrements PTR) :
![Configuration du transfert de requêtes d'Unbound DNS dans OPNsense](img/opnsense-unbound-dns-query-forwarding.png)
![Configuration du transfert de requêtes d'Unbound DNS dans OPNsense](images/opnsense-unbound-dns-query-forwarding.png)
---
## VPN

View File

@@ -92,7 +92,7 @@ Finally I restart the VM. Once started, from the Proxmox WebGUI, I can see the I
## Interfaces
On both firewalls, I assign the remaining NICs to new interfaces adding a description. The VMs have 7 interfaces, I carefully compare MAC addresses to avoid mixing interfaces:
![Assign interfaces menu in OPNsense](img/opnsense-assign-interfaces.png)
![Assign interfaces menu in OPNsense](images/opnsense-assign-interfaces.png)
In the end, the interfaces configuration looks like this:
@@ -157,13 +157,13 @@ The HA is setup in `System` > `High Availability` > `Settings`
### HA Status
In the section `System` > `High Availability` > `Status`, I can verify if the synchronization is working. On this page I can replicate any or all services from my master to my backup node:
![OPNsense high availability status page](img/opnsense-high-availability-status.png)
![OPNsense high availability status page](images/opnsense-high-availability-status.png)
---
## Virtual IPs
Now that HA is configured, I can give my networks a virtual IP shared across my nodes. In `Interfaces` > `Virtual IPs` > `Settings`, I create one VIP for each of my networks using **CARP** (Common Address Redundancy Protocol). The target is to reuse the IP addresses used by my current OPNsense instance, but as it is still routing my network, I use different IPs for the configuration phase:
![Liste des IPs virtuelles dans OPNsense](img/opnsense-interface-virtual-ips.png)
![OPNsense virtual IPs list](images/opnsense-interface-virtual-ips.png)
OPNsense allows CARP by default, no special firewall rule required
@@ -239,7 +239,7 @@ To begin, in `Firewall` > `Groups`, I create 2 zones to regroup my interfaces:
### Network Aliases
Next, in `Firewall` > `Aliases`, I create an alias `InternalNetworks` to regroup all my internal networks:
![Création d'alias pour les réseaux locaux dansOPNsense](img/opnsense-create-alias-internalnetworks.png)
![OPNsense alias creation for internal networks ](images/opnsense-create-alias-internalnetworks.png)
### Firewall Rules
@@ -343,17 +343,17 @@ On the backup node, I configure it the same, the only difference will be the **D
### DHCP Ranges
Next I configure the DHCP ranges. Both firewalls will have different ranges, the backup node will have smaller ones (only 10 leases should be enough). On the master, they are configured as follow:
![OPNsense DHCP ranges in Dnsmasq](img/opnsense-dnsmasq-dhcp-ranges.png)
![OPNsense DHCP ranges in Dnsmasq](images/opnsense-dnsmasq-dhcp-ranges.png)
### DHCP Options
Then I set some DHCP options for each domain: the `router`, the `dns-server` and the `domain-name`. I'm pointing the IP addresses to the interface's VIP:
![OPNsense DHCP options in Dnsmasq](img/opnsense-dnsmasq-dhcp-options.png)
![OPNsense DHCP options in Dnsmasq](images/opnsense-dnsmasq-dhcp-options.png)
### Hosts
Finally in in the `Hosts` tab, I define static DHCP mappings but also static IP not managed by the DHCP, to have them registered in the DNS:
![Hôtes DHCP de Dnsmasq dans OPNsense](img/opnsense-dnsmasq-dhcp-hosts.png)
![OPNsense DHCP hosts in Dnsmasq](images/opnsense-dnsmasq-dhcp-hosts.png)
---
## DNS
@@ -370,7 +370,7 @@ Unbound is the recursive resolver, for local zones I forward queries to Dnsmasq.
### Unbound General Settings
Let's configure it, in `Services` > `Unbound DNS` > `General`:
![OPNsense Unbound DNS general settings](img/opnsense-unbound-general-settings.png)
![OPNsense Unbound DNS general settings](images/opnsense-unbound-general-settings.png)
### DNS Blocklist
@@ -381,7 +381,7 @@ To maintain the service up to date, in `System` > `Settings` > `Cron`, I add my
### Query Forwarding
Finally I configure query forwarding for my local domains to Dnsmasq. In `Services` > `Unbound DNS` > `Query Forwarding`, I add each of my local domains with their reverse lookup (PTR record):
![Configuration du transfert de requêtes d'Unbound DNS dans OPNsense](img/opnsense-unbound-dns-query-forwarding.png)
![OPNsense Unbound DNS query forwarding configuration](images/opnsense-unbound-dns-query-forwarding.png)
---
## VPN

View File

Before

Width:  |  Height:  |  Size: 73 KiB

After

Width:  |  Height:  |  Size: 73 KiB

View File

@@ -108,7 +108,7 @@ apt full-upgrade -y
```
Après la mise à niveau sur le premier nœud, la version Ceph affiche maintenant `19.2.3`, je peux voir mes OSD apparaître comme obsolètes, les moniteurs nécessitent soit une mise à niveau soit un redémarrage :
![Ceph storage status in Proxmox after first node Ceph package udpate](img/proxmox-ceph-version-upgrade.png)
![État du stockage Ceph dans Proxmox après la mise à jour des paquets Ceph du premier nœud](images/proxmox-ceph-version-upgrade.png)
Je poursuis et mets à niveau les paquets sur les 2 autres nœuds.
@@ -132,7 +132,7 @@ systemctl restart ceph-osd.target
```
Je surveille le statut Ceph avec la WebGUI Proxmox. Après le redémarrage, elle affiche quelques couleurs fancy. Jattends juste que les PG redeviennent verts, cela prend moins dune minute :
![Ceph storage status in Proxmox during the first OSD restart](img/proxmox-ceph-status-osd-restart.png)
![État du stockage Ceph dans Proxmox lors du premier redémarrage d'un OSD](images/proxmox-ceph-status-osd-restart.png)
Un avertissement apparaît : `HEALTH_WARN: all OSDs are running squid or later but require_osd_release < squid`

View File

@@ -108,7 +108,7 @@ apt full-upgrade -y
```
After the upgrade on the first node, the Ceph version now shows `19.2.3`, I can see my OSDs appear as outdated, the monitors need either an upgrade or a restart:
![Ceph storage status in Proxmox after first node Ceph package udpate](img/proxmox-ceph-version-upgrade.png)
![Ceph storage status in Proxmox after first node Ceph package udpate](images/proxmox-ceph-version-upgrade.png)
I carry on and upgrade the packages on the 2 other nodes.
@@ -132,7 +132,7 @@ systemctl restart ceph-osd.target
```
I monitor the Ceph status with the Proxmox WebGUI. After the restart, it is showing some fancy colors. I'm just waiting for the PGs to be back to green, it takes less than a minute:
![Ceph storage status in Proxmox during the first OSD restart](img/proxmox-ceph-status-osd-restart.png)
![Ceph storage status in Proxmox during the first OSD restart](images/proxmox-ceph-status-osd-restart.png)
A warning shows up: `HEALTH_WARN: all OSDs are running squid or later but require_osd_release < squid`

View File

Before

Width:  |  Height:  |  Size: 47 KiB

After

Width:  |  Height:  |  Size: 47 KiB

View File

Before

Width:  |  Height:  |  Size: 118 KiB

After

Width:  |  Height:  |  Size: 118 KiB

View File

Before

Width:  |  Height:  |  Size: 197 KiB

After

Width:  |  Height:  |  Size: 197 KiB

View File

Before

Width:  |  Height:  |  Size: 92 KiB

After

Width:  |  Height:  |  Size: 92 KiB

View File

Before

Width:  |  Height:  |  Size: 114 KiB

After

Width:  |  Height:  |  Size: 114 KiB

View File

Before

Width:  |  Height:  |  Size: 233 KiB

After

Width:  |  Height:  |  Size: 233 KiB

View File

@@ -34,12 +34,12 @@ D'abord, je configure mon réseau de couche 2 qui est géré par UniFi. Là, je
- _pfSync_ (44), communication entre mes nœuds OPNsense.
Dans le contrôleur UniFi, dans `Paramètres` > `Réseaux`, j'ajoute un `New Virtual Network`. Je le nomme `WAN` et lui donne l'ID VLAN 20 :
![Creation of the WAN VLAN in the UniFi Controller](img/unifi-add-vlan-for-wan.png)
![Création du VLAN WAN dans le contrôleur UniFi](images/unifi-add-vlan-for-wan.png)
Je fais la même chose pour le VLAN `pfSync` avec l'ID VLAN 44.
Je prévois de brancher ma box FAI sur le port 15 de mon switch, qui est désactivé pour l'instant. Je l'active, définis le VLAN natif sur le nouveau `WAN (20)` et désactive le trunking :
![Configuration du port du switch UniFi pour la liaison WAN](img/unifi-enable-port-wan-vlan.png)
![Configuration du port du switch UniFi pour la liaison WAN](images/unifi-enable-port-wan-vlan.png)
Une fois ce réglage appliqué, je m'assure que seules les ports où sont connectés mes nœuds Proxmox propagent ces VLANs sur leur trunk.
@@ -50,7 +50,7 @@ J'ai fini la configuration UniFi.
Maintenant que le VLAN peut atteindre mes nœuds, je veux le gérer dans le SDN de Proxmox. J'ai configuré le SDN dans [cet article]({{< ref "post/11-proxmox-cluster-networking-sdn" >}}).
Dans `Datacenter` > `SDN` > `VNets`, je crée un nouveau VNet, je l'appelle `vlan20` pour suivre ma propre convention de nommage, je lui donne l'alias _WAN_ et j'utilise le tag (ID VLAN) 20 :
![Creation of the VNet for the WAN in the Proxmox SDN](img/proxmox-sdn-new-vnet-wan.png)
![Création du VNet pour le WAN dans le SDN Proxmox](images/proxmox-sdn-new-vnet-wan.png)
Je crée aussi le `vlan44` pour le VLAN _pfSync_, puis j'applique cette configuration et nous avons terminé avec le SDN.
@@ -75,7 +75,7 @@ La première VM s'appelle `cerbere-head1` (je ne vous l'ai pas dit ? Mon firew
6. `vlan55` _(DMZ)_
7. `vlan66` _(Lab)_
![Hardware settings of the OPNsense VM in Proxmox](img/proxmox-cerbere-vm-settings.png)
![Paramètres matériels de la VM OPNsense dans Proxmox](images/proxmox-cerbere-vm-settings.png)
Maintenant je clone cette VM pour créer `cerbere-head2`, puis je procède à l'installation d'OPNsense. Je ne veux pas entrer trop dans les détails de l'installation d'OPNsense, je l'ai déjà documentée dans le [proof of concept]({{< ref "post/12-opnsense-virtualization-highly-available" >}}).
@@ -117,7 +117,7 @@ Dans Proxmox VE 8, il était possible de créer des groupes HA, en fonction de l
Le cluster Proxmox est capable de fournir de la HA pour les ressources, mais vous devez définir les règles.
Dans `Datacenter` > `HA`, vous pouvez voir le statut et gérer les ressources. Dans le panneau `Resources` je clique sur `Add`. Je dois choisir la ressource à configurer en HA dans la liste, ici `cerbere-head1` avec l'ID 122. Puis dans l'infobulle je peux définir le maximum de redémarrages et de relocations, je laisse `Failback` activé et l'état demandé à `started` :
![Create HA resource in Proxmox](img/proxmox-add-vm-ha.png)
![Créer une ressource HA dans Proxmox](images/proxmox-add-vm-ha.png)
Le cluster Proxmox s'assurera maintenant que cette VM est démarrée. Je fais de même pour l'autre VM OPNsense, `cerbere-head2`.
@@ -126,7 +126,7 @@ Le cluster Proxmox s'assurera maintenant que cette VM est démarrée. Je fais de
Super, mais je ne veux pas qu'elles tournent sur le même nœud. C'est là qu'intervient la nouvelle fonctionnalité des règles d'affinité HA de Proxmox VE 9. Proxmox permet de créer des règles d'affinité de nœud et de ressource. Peu m'importe sur quel nœud elles tournent, mais je ne veux pas qu'elles soient ensemble. J'ai besoin d'une règle d'affinité de ressource.
Dans `Datacenter` > `HA` > `Affinity Rules`, j'ajoute une nouvelle règle d'affinité de ressource HA. Je sélectionne les deux VMs et choisis l'option `Keep Separate` :
![Create HA resource affinity in Proxmox](img/proxmox-ha-resource-affinity-rule.png)
![Créer une affinité de ressource HA dans Proxmox](images/proxmox-ha-resource-affinity-rule.png)
✅ Mes VMs OPNsense sont maintenant entièrement prêtes !
@@ -393,7 +393,7 @@ En entrant manuellement en mode maintenance CARP depuis l'interface WebGUI, aucu
Pour simuler un failover, je tue la VM OPNsense active. Ici j'observe une seule perte de paquet. Génial.
![Ping test during OPNsense CARP failover](img/opnsense-ping-failover.png)
![Test de ping pendant le CARP failover d'OPNsense](images/opnsense-ping-failover.png)
3. **Reprise après sinistre**

View File

@@ -33,12 +33,12 @@ First, I configure my layer 2 network which is managed by UniFi. There I need to
- *pfSync* (44), communication between my OPNsense nodes.
In the UniFi controller, in `Settings` > `Networks`, I add a `New Virtual Network`. I name it `WAN` and give it the VLAN ID 20:
![Creation of the WAN VLAN in the UniFi Controller](img/unifi-add-vlan-for-wan.png)
![Creation of the WAN VLAN in the UniFi Controller](images/unifi-add-vlan-for-wan.png)
I do the same thing again for the `pfSync` VLAN with the VLAN ID 44.
I plan to plug my ISP box on the port 15 of my switch, which is disabled for now. I set it as active, set the native VLAN on the newly created one `WAN (20)` and disable trunking:
![Configuration du port du switch UniFi pour la liaison WAN](img/unifi-enable-port-wan-vlan.png)
![Configuration of the UniFi switch port for the WAN uplink](images/unifi-enable-port-wan-vlan.png)
Once this setting applied, I make sure that only the ports where are connected my Proxmox nodes propagate these VLAN on their trunk.
@@ -49,7 +49,7 @@ I'm done with UniFi configuration.
Now that the VLAN can reach my nodes, I want to handle it in the Proxmox SDN. I've configured the SDN in [that article]({{< ref "post/11-proxmox-cluster-networking-sdn" >}}).
In `Datacenter` > `SDN` > `VNets`, I create a new VNet, call it `vlan20` to follow my own naming convention, give it the *WAN* alias and use the tag (VLAN ID) 20:
![Creation of the VNet for the WAN in the Proxmox SDN](img/proxmox-sdn-new-vnet-wan.png)
![Creation of the VNet for the WAN in the Proxmox SDN](images/proxmox-sdn-new-vnet-wan.png)
I also create the `vlan44` for the *pfSync* VLAN, then I apply this configuration and we are done with the SDN.
@@ -74,7 +74,7 @@ The first VM is named `cerbere-head1` (I didn't tell you? My current firewall is
6. `vlan55` *(DMZ)*
7. `vlan66` *(Lab)*
![Hardware settings of the OPNsense VM in Proxmox](img/proxmox-cerbere-vm-settings.png)
![Hardware settings of the OPNsense VM in Proxmox](images/proxmox-cerbere-vm-settings.png)
Now I clone that VM to create `cerbere-head2`, then I proceed with OPNsense installation. I don't want to go into much details about OPNsense installation, I already documented it in the [proof of concept]({{< ref "post/12-opnsense-virtualization-highly-available" >}}).
@@ -115,7 +115,7 @@ In Proxmox VE 8, It was possible to create HA groups, depending of their resourc
The Proxmox cluster is able to provide HA for the resources, but you need to define the rules.
In `Datacenter` > `HA`, you can see the status and manage the resources. In the `Resources` panel I click on `Add`. I need to pick the resource to configure as HA in the list, here `cerbere-head1` with ID 122. Then in the tooltip I can define the maximum of restart and relocate, I keep `Failback` enabled and the requested state to `started`:
![Create HA resource in Proxmox](img/proxmox-add-vm-ha.png)
![Create HA resource in Proxmox](images/proxmox-add-vm-ha.png)
The Proxmox cluster will now make sure this VM is started. I do the same for the other OPNsense VM, `cerbere-head2`.
@@ -124,7 +124,7 @@ The Proxmox cluster will now make sure this VM is started. I do the same for the
Great, but I don't want them on the same node. This is when the new feature HA affinity rules, of Proxmox VE 9, come in. Proxmox allows to create node affinity and resource affinity rules. I don't mind on which node they run, but I don't want them together. I need a resource affinity rule.
In `Datacenter` > `HA` > `Affinity Rules`, I add a new HA resource affinity rule. I select both VMs and pick the option `Keep Separate`:
![Create HA resource affinity in Proxmox](img/proxmox-ha-resource-affinity-rule.png)
![Create HA resource affinity in Proxmox](images/proxmox-ha-resource-affinity-rule.png)
✅ My OPNsense VMs are now fully ready!
@@ -390,7 +390,7 @@ When manually entering CARP maintenance mode from the WebGUI interface, no packe
To simulate a failover, I kill the active OPNsense VM. Here I observe only one packet dropped. Awesome.
![Ping test during OPNsense CARP failover](img/opnsense-ping-failover.png)
![Ping test during OPNsense CARP failover](images/opnsense-ping-failover.png)
3. **Disaster Recovery**

View File

Before

Width:  |  Height:  |  Size: 159 KiB

After

Width:  |  Height:  |  Size: 159 KiB

View File

Before

Width:  |  Height:  |  Size: 149 KiB

After

Width:  |  Height:  |  Size: 149 KiB

View File

Before

Width:  |  Height:  |  Size: 96 KiB

After

Width:  |  Height:  |  Size: 96 KiB

View File

Before

Width:  |  Height:  |  Size: 80 KiB

After

Width:  |  Height:  |  Size: 80 KiB

View File

Before

Width:  |  Height:  |  Size: 114 KiB

After

Width:  |  Height:  |  Size: 114 KiB

View File

@@ -109,23 +109,23 @@ Avec Semaphore en fonctionnement, faisons rapidement le tour de l'UI et connecto
## Discovery
Après avoir démarré la stack, je peux atteindre la page de connexion à l'URL :
![Page de connexion de Semaphore UI](img/semaphore-login-page.png)
![Page de connexion de Semaphore UI](images/semaphore-login-page.png)
Pour me connecter, j'utilise les identifiants définis par `SEMAPHORE_ADMIN_NAME`/`SEMAPHORE_ADMIN_PASSWORD`.
Au premier accès, Semaphore me demande de créer un projet. J'ai créé le projet Homelab :
![Page de création de projet de Semaphore UI](img/semaphore-create-project.png)
![Page de création de projet de Semaphore UI](images/semaphore-create-project.png)
La première chose que je veux faire est d'ajouter mon dépôt _homelab_ (vous pouvez trouver son miroir sur Github [ici](https://github.com/Vezpi/homelab)). Dans `Repository`, je clique sur le bouton `New Repository`, et j'ajoute l'URL du repo. Je ne spécifie pas d'identifiants car le dépôt est public :
![Page d'ajout de dépôt de Semaphore UI](img/semaphore-add-repository.png)
![Page d'ajout de dépôt de Semaphore UI](images/semaphore-add-repository.png)
Avant de continuer, je déploie 3 VM à des fins de test : `sem01`, `sem02` et `sem03`. Je les ai créées avec Terraform via [ce projet](https://github.com/Vezpi/Homelab/tree/main/terraform/projects/semaphore-vms).
Pour interagir avec ces VM, je dois configurer des identifiants. Dans le `Key Store`, j'ajoute la première donnée d'identification, une clé SSH pour mon utilisateur :
![Page d'ajout d'une nouvelle clé de Semaphore UI](img/semaphore-create-new-ssh-key.png)
![Page d'ajout d'une nouvelle clé de Semaphore UI](images/semaphore-create-new-ssh-key.png)
Ensuite je crée un nouvel `Inventory`. J'utilise le format d'inventaire Ansible (le seul disponible). Je sélectionne la clé SSH créée précédemment et choisis le type `Static`. Dans les champs je renseigne les 3 hôtes créés avec leur FQDN :
![Page de création d'un inventaire statique de Semaphore UI](img/semaphore-create-new-static-inventory.png)
![Page de création d'un inventaire statique de Semaphore UI](images/semaphore-create-new-static-inventory.png)
✅ Avec un projet, un repo, des identifiants et un inventaire en place, je peux avancer et tester l'exécution d'un playbook Ansible.
@@ -172,20 +172,20 @@ Je veux tester quelque chose de simple : installer un serveur web avec une page
```
Dans Semaphore UI, je peux maintenant créer mon premier `Task Template` pour un playbook Ansible. Je lui donne un nom, le chemin du playbook (depuis le dossier racine du repo), le dépôt et sa branche :
![Nouveau template de tâche Ansible dans Semaphore UI](img/semaphore-create-new-ansible-task-template.png)
![Nouveau template de tâche Ansible dans Semaphore UI](images/semaphore-create-new-ansible-task-template.png)
Il est temps de lancer le playbook ! Dans la liste des task templates, je clique sur le bouton ▶️ :
![Lancement du template de tâche Ansible dans Semaphore UI](img/semaphore-run-test-playbook.png)
![Lancement du template de tâche Ansible dans Semaphore UI](images/semaphore-run-test-playbook.png)
Le playbook se lance et je peux suivre la sortie en temps réel :
![Semaphore UI Ansible task output](img/semaphore-ui-ansible-task-output.png)
![Sortie de la tâche Ansible dans Semaphore UI](images/semaphore-ui-ansible-task-output.png)
Je peux aussi consulter les exécutions précédentes :
![Liste des exécutions de tâches dans Semaphore UI](img/semaphore-ui-task-template-run-list.png)
![Liste des exécutions de tâches dans Semaphore UI](images/semaphore-ui-task-template-run-list.png)
✅ Enfin, je peux confirmer que le travail est fini en vérifiant l'URL sur le port 80 (http) :
![Test de l'URL après application du playbook sur les hôtes](img/semaphore-ui-test-nginx-page-playbook.png)
![Test de l'URL après application du playbook sur les hôtes](images/semaphore-ui-test-nginx-page-playbook.png)
Gérer des playbooks Ansible dans Semaphore UI est assez simple et vraiment pratique. L'interface est très soignée.
@@ -233,19 +233,19 @@ Avec cela en place, le playbook a réussi et j'ai pu créer l'utilisateur :
```
Ensuite je crée un variable group `pve_vm`. Un variable group me permet de définir plusieurs variables et secrets ensemble :
![Nouveau groupe de variables dans Semaphore UI](img/semaphore-ui-create-variable-group.png)
![Nouveau groupe de variables dans Semaphore UI](images/semaphore-ui-create-variable-group.png)
Puis je crée un nouveau task template, cette fois de type Terraform Code. Je lui donne un nom, le chemin du projet Terraform, un workspace, le dépôt avec sa branche et le variable group :
![Nouveau template de tâche Terraform dans Semaphore UI](img/semaphore-task-template-terraform.png)
![Nouveau template de tâche Terraform dans Semaphore UI](images/semaphore-task-template-terraform.png)
Lancer le template me donne quelques options supplémentaires liées à Terraform :
![Options d'exécution Terraform dans Semaphore UI](img/semaphore-running-terraform-code-options.png)
![Options d'exécution Terraform dans Semaphore UI](images/semaphore-running-terraform-code-options.png)
Après le plan Terraform, il me propose d'appliquer, d'annuler ou d'arrêter :
![Plan Terraform dans Semaphore UI](img/semaphore-terraform-task-working.png)
![Plan Terraform dans Semaphore UI](images/semaphore-terraform-task-working.png)
Enfin, après avoir cliqué sur ✅ pour appliquer, j'ai pu regarder Terraform construire les VM, comme avec le CLI. À la fin, les VM ont été déployées avec succès sur Proxmox :
![Déploiement Terraform terminé dans Semaphore UI](img/semaphore-ui-deploy-with-terraform.png)
![Déploiement Terraform terminé dans Semaphore UI](images/semaphore-ui-deploy-with-terraform.png)
---
## Conclusion

View File

@@ -109,23 +109,23 @@ With Semaphore running, lets take a quick tour of the UI and wire it up to a
## Discovery
After starting the stack, I can reach the login page at the URL:
![Page de connexion de Semaphore UI](img/semaphore-login-page.png)
![Semaphore UI login page](images/semaphore-login-page.png)
To log in, I use the credentials defined by `SEMAPHORE_ADMIN_NAME`/`SEMAPHORE_ADMIN_PASSWORD`.
On first login, Semaphore prompt me to create a project. I created the Homelab project:
![Page de création de projet de Semaphore UI](img/semaphore-create-project.png)
![Semaphore UI new project page](images/semaphore-create-project.png)
The first thing I want to do is to add my *homelab* repository (you can find its mirror on Github [here](https://github.com/Vezpi/homelab)). In `Repository`, I click the `New Repository` button, and add the repo URL. I don't specify credentials because the repo is public:
![Page d'ajout de dépôt de Semaphore UI](img/semaphore-add-repository.png)
![Semaphore UI new repository page](images/semaphore-add-repository.png)
Before continue, I deploy 3 VMs for testing purpose: `sem01`, `sem02` and `sem03`. I created them using Terraform with [this project](https://github.com/Vezpi/Homelab/tree/main/terraform/projects/semaphore-vms).
To interact with these VMs I need to configure credentials. In the the `Key Store`, I add the first credential, a SSH key for my user:
![Page d'ajout d'une nouvelle clé de Semaphore UI](img/semaphore-create-new-ssh-key.png)
![Semaphore UI new key page](images/semaphore-create-new-ssh-key.png)
Then I create a new `Inventory`. I'm using the Ansible inventory format (the only one available). I select the SSH key previously created and select the type as `Static`. In the fields I enter the 3 hosts created with their FQDN:
![Page de création d'un inventaire statique de Semaphore UI](img/semaphore-create-new-static-inventory.png)
![Semaphore UI new inventory page](images/semaphore-create-new-static-inventory.png)
✅ With a project, repo, credentials, and inventory in place, I can move forward and test to run an Ansible playbook.
@@ -172,20 +172,20 @@ I want to test something simple, install a web server with a custom page on thes
```
In Semaphore UI, I can now create my first `Task Template` for Ansible playbook. I give it a name, the playbook path (from the root folder of the repo), the repository and its branch:
![Nouveau template de tâche Ansible dans Semaphore UI](img/semaphore-create-new-ansible-task-template.png)
![Semaphore UI new Ansible task template](images/semaphore-create-new-ansible-task-template.png)
Time to launch the playbook! In the task templates list, I click on the ▶️ button:
![Lancement du template de tâche Ansible dans Semaphore UI](img/semaphore-run-test-playbook.png)
![Semaphore UI launch Ansible task template](images/semaphore-run-test-playbook.png)
The playbook launches and I can follow the output in real time:
![Semaphore UI Ansible task output](img/semaphore-ui-ansible-task-output.png)
![Semaphore UI Ansible task output](images/semaphore-ui-ansible-task-output.png)
I can also review previous runs:
![Liste des exécutions de tâches dans Semaphore UI](img/semaphore-ui-task-template-run-list.png)
![Semaphore UI tasks runs list](images/semaphore-ui-task-template-run-list.png)
✅ Finally I can confirm the job is done by checking the URL on port 80 (http):
![Test de l'URL après application du playbook sur les hôtes](img/semaphore-ui-test-nginx-page-playbook.png)
![Testing URL after applying playbook on hosts ](images/semaphore-ui-test-nginx-page-playbook.png)
Managing Ansible playbooks in Semaphore UI is pretty simple and really convenient. The interface is really sleek.
@@ -233,19 +233,19 @@ With that in place, the playbook succeeded and I could create the user:
```
Next I create a variable group `pve_vm`. A variable group let me define multiple variables and secrets together:
![Nouveau groupe de variables dans Semaphore UI](img/semaphore-ui-create-variable-group.png)
![Semaphore UI new variable group](images/semaphore-ui-create-variable-group.png)
Then I create a new task template, this time with the kind Terraform Code. I give it a name, the path of the terraform [project](https://github.com/Vezpi/Homelab/tree/main/terraform/projects/semaphore-vms), a workspace, the repository along with its branch and. the variable group:
![Nouveau template de tâche Terraform dans Semaphore UI](img/semaphore-task-template-terraform.png)
![Semaphore UI new Terraform task template](images/semaphore-task-template-terraform.png)
Running the template gives me some additional options related to Terraform:
![Options d'exécution Terraform dans Semaphore UI](img/semaphore-running-terraform-code-options.png)
![Semaphore UI run Terraform task](images/semaphore-running-terraform-code-options.png)
After the Terraform plan, I'm proposed to apply, cancel or stop:
![Plan Terraform dans Semaphore UI](img/semaphore-terraform-task-working.png)
![Semaphore UI task Terraform plan](images/semaphore-terraform-task-working.png)
Finally after hitting ✅ to apply, I could watch Terraform build the VMs, just like using the CLI. At the end, the VMs were successfully deployed on Proxmox:
![Déploiement Terraform terminé dans Semaphore UI](img/semaphore-ui-deploy-with-terraform.png)
![Semaphore UI Terraform deploy complete](images/semaphore-ui-deploy-with-terraform.png)
---
## Conclusion

View File

Before

Width:  |  Height:  |  Size: 507 KiB

After

Width:  |  Height:  |  Size: 507 KiB

View File

Before

Width:  |  Height:  |  Size: 213 KiB

After

Width:  |  Height:  |  Size: 213 KiB

View File

Before

Width:  |  Height:  |  Size: 86 KiB

After

Width:  |  Height:  |  Size: 86 KiB

View File

Before

Width:  |  Height:  |  Size: 58 KiB

After

Width:  |  Height:  |  Size: 58 KiB

View File

Before

Width:  |  Height:  |  Size: 48 KiB

After

Width:  |  Height:  |  Size: 48 KiB

View File

Before

Width:  |  Height:  |  Size: 120 KiB

After

Width:  |  Height:  |  Size: 120 KiB

View File

Before

Width:  |  Height:  |  Size: 59 KiB

After

Width:  |  Height:  |  Size: 59 KiB

View File

Before

Width:  |  Height:  |  Size: 127 KiB

After

Width:  |  Height:  |  Size: 127 KiB

Some files were not shown because too many files have changed in this diff Show More