Skip to content

Talos Linux et déploiement d'un Homelab

Introduction à Talos Linux

Talos Linux est un système d'exploitation minimaliste et immutable conçu spécifiquement pour Kubernetes. Contrairement aux distributions Linux traditionnelles, Talos n'a pas de shell, pas de SSH, et se configure entièrement via une API.

Pourquoi Talos plutôt que kubeadm ?

AspectkubeadmTalos
ComplexitéConfiguration manuelle, nombreuses étapesDéclaratif, fichier de config unique
SécuritéOS complet avec surface d'attaque largeImmutable, pas de shell, API only
MaintenanceUpdates OS + K8s séparésUpdates atomiques OS + K8s
DebugSSH disponiblePas de SSH (API + talosctl)
Philosophie"Pets" (serveurs à maintenir)"Cattle" (jetable et reproductible)

Caractéristiques principales

-> Immutable

Le système de fichiers racine est en lecture seule. Pas de modification possible à runtime, ce qui élimine le drift de configuration.

-> Secure by default

  • Pas de SSH
  • Pas de shell
  • Pas de package manager
  • API mutuelle TLS uniquement

-> API-driven

Toute la configuration se fait via talosctl ou des fichiers YAML. Parfait pour l'Infrastructure as Code.

-> Minimal

~80MB d'image, boot en quelques secondes, surface d'attaque réduite.

Architecture du cluster

Pour ce TP, nous allons déployer un cluster minimal sur VirtualBox :

┌─────────────────────────────────────────────────────────┐
│                     Votre PC                             │
│                                                          │
│  ┌─────────────────────────────────────────────────────┐│
│  │                   VirtualBox                         ││
│  │                                                      ││
│  │  ┌─────────────┐    ┌─────────────┐                 ││
│  │  │ talos-cp-1  │    │ talos-wk-1  │                 ││
│  │  │  (control)  │◄──►│  (worker)   │                 ││
│  │  │  2CPU/2GB   │    │  2CPU/2GB   │                 ││
│  │  └─────────────┘    └─────────────┘                 ││
│  │        │                                             ││
│  │        │ API (6443)                                  ││
│  │        ▼                                             ││
│  │  ┌─────────────┐                                    ││
│  │  │  talosctl   │                                    ││
│  │  │  kubectl    │                                    ││
│  │  └─────────────┘                                    ││
│  └─────────────────────────────────────────────────────┘│
└─────────────────────────────────────────────────────────┘

Configuration minimale requise :

  • 2 VMs (1 control plane + 1 worker)
  • 2 CPU et 2 GB RAM par VM
  • 20 GB de disque par VM
  • Total : 4 CPU, 4 GB RAM, 40 GB disque

Installation sur VirtualBox

Prérequis

-> Sur votre machine hôte :

  1. VirtualBox installé (https://www.virtualbox.org/)
  2. talosctl installé
  3. kubectl installé

Étape 1 : Installer talosctl

sh
# Linux
curl -sL https://talos.dev/install | sh

# Windows (PowerShell en admin)
iwr -useb https://talos.dev/install.ps1 | iex

# Vérifier l'installation
talosctl version --client

Étape 2 : Télécharger l'ISO Talos

Téléchargez l'ISO depuis les releases GitHub :

sh
# Récupérer la dernière version
curl -LO https://github.com/siderolabs/talos/releases/download/v1.6.0/talos-amd64.iso

Ou directement depuis : https://github.com/siderolabs/talos/releases

Étape 3 : Configurer le réseau VirtualBox

Avant de créer les VMs, configurez un réseau Host-Only :

  1. Ouvrez VirtualBox → FichierOutilsNetwork Manager
  2. Cliquez sur Créer pour ajouter un réseau Host-Only
  3. Configurez-le :
    • Adresse IPv4 : 192.168.56.1
    • Masque : 255.255.255.0
    • Serveur DHCP : Désactivé (on utilisera des IPs fixes)

Étape 4 : Créer les VMs

VM Control Plane (talos-cp-1)

  1. Nouvelle VM :

    • Nom : talos-cp-1
    • Type : Linux
    • Version : Other Linux (64-bit)
    • Mémoire : 2048 MB
    • Disque : Créer un disque virtuel, 20 GB, VDI, Dynamically allocated
  2. Configuration (clic droit → Configuration) :

    • Système → Processeur : 2 CPU
    • Stockage → Contrôleur IDE → Ajouter l'ISO talos-amd64.iso
    • Réseau → Adapter 1 :
      • Attached to : Host-only Adapter
      • Name : vboxnet0 (celui créé à l'étape 3)

VM Worker (talos-wk-1)

Répétez les mêmes étapes avec :

  • Nom : talos-wk-1
  • Mêmes specs (2 CPU, 2 GB RAM, 20 GB disque)
  • Même configuration réseau

Étape 5 : Démarrer les VMs et noter les IPs

  1. Démarrez les deux VMs
  2. Au boot, Talos affiche l'IP obtenue (ou waiting for IP si pas de DHCP)

Comme on n'a pas de DHCP, on va assigner les IPs via la configuration Talos. Pour l'instant, notez les MACs des VMs (visibles dans Configuration → Réseau).

Étape 6 : Générer la configuration Talos

sh
# Créer un dossier pour le projet
mkdir ~/talos-homelab && cd ~/talos-homelab

# Générer les fichiers de configuration
# L'IP sera celle du control plane
talosctl gen config homelab https://192.168.56.10:6443

# Fichiers générés :
# - controlplane.yaml
# - worker.yaml
# - talosconfig

Étape 7 : Personnaliser les configurations

Éditez controlplane.yaml pour configurer l'IP statique :

yaml
machine:
  type: controlplane
  network:
    hostname: talos-cp-1
    interfaces:
      - interface: enp0s3
        addresses:
          - 192.168.56.10/24
  install:
    disk: /dev/sda
    image: ghcr.io/siderolabs/installer:v1.6.0
cluster:
  controlPlane:
    endpoint: https://192.168.56.10:6443
  network:
    cni:
      name: flannel

Éditez worker.yaml :

yaml
machine:
  type: worker
  network:
    hostname: talos-wk-1
    interfaces:
      - interface: enp0s3
        addresses:
          - 192.168.56.11/24
  install:
    disk: /dev/sda
    image: ghcr.io/siderolabs/installer:v1.6.0

Étape 8 : Appliquer les configurations

Depuis votre machine hôte :

sh
# Configurer talosctl pour utiliser notre config
export TALOSCONFIG=~/talos-homelab/talosconfig

# Appliquer la config au control plane
# --insecure car le cluster n'est pas encore bootstrappé
talosctl apply-config --insecure \
  --nodes 192.168.56.10 \
  --file controlplane.yaml

# Attendre que la VM redémarre et installe Talos (~2-3 minutes)

# Appliquer la config au worker
talosctl apply-config --insecure \
  --nodes 192.168.56.11 \
  --file worker.yaml

Étape 9 : Bootstrap le cluster

sh
# Bootstrap Kubernetes sur le control plane
talosctl bootstrap --nodes 192.168.56.10

# Attendre ~2-3 minutes que le cluster démarre

# Récupérer le kubeconfig
talosctl kubeconfig --nodes 192.168.56.10 -f ~/.kube/config

# Vérifier le cluster
kubectl get nodes
# NAME         STATUS   ROLES           AGE   VERSION
# talos-cp-1   Ready    control-plane   2m    v1.29.0
# talos-wk-1   Ready    <none>          1m    v1.29.0

Commandes talosctl essentielles

sh
# Voir l'état des services
talosctl services --nodes 192.168.56.10

# Dashboard en temps réel (très utile !)
talosctl dashboard --nodes 192.168.56.10

# Voir les logs d'un service
talosctl logs kubelet --nodes 192.168.56.10

# Redémarrer un noeud
talosctl reboot --nodes 192.168.56.10

# Mettre à jour Talos
talosctl upgrade --nodes 192.168.56.10 \
  --image ghcr.io/siderolabs/installer:v1.6.1

# Mettre à jour Kubernetes
talosctl upgrade-k8s --nodes 192.168.56.10 --to 1.29.1

Stockage persistant

Kubernetes a besoin d'un système de stockage pour les données persistantes (bases de données, fichiers uploadés, etc.). Deux options s'offrent à vous selon vos ressources.

Option 1 : local-path-provisioner (léger)

Pour un cluster avec peu de ressources (notre setup VirtualBox), local-path-provisioner de Rancher est idéal :

sh
kubectl apply -f https://raw.githubusercontent.com/rancher/local-path-provisioner/master/deploy/local-path-storage.yaml

-> Avantages

  • Très léger (~15 MB de RAM)
  • Simple à installer
  • Parfait pour le développement

-> Inconvénients

  • Pas de réplication (données sur un seul nœud)
  • Si le nœud tombe, les données sont perdues
  • Pas de snapshots

-> Vérifier l'installation

sh
kubectl get storageclass
# NAME                   PROVISIONER             RECLAIMPOLICY   VOLUMEBINDINGMODE      ALLOWVOLUMEEXPANSION
# local-path (default)   rancher.io/local-path   Delete          WaitForFirstConsumer   false

Option 2 : Longhorn (production)

Longhorn est un système de stockage distribué cloud-native développé par Rancher/SUSE. Il réplique les données sur plusieurs nœuds et offre des fonctionnalités avancées.

-> Prérequis matériels

RessourceMinimumRecommandé
Nœuds33+
CPU par nœud4 vCPU8 vCPU
RAM par nœud4 GB8 GB
Disque par nœud50 GB100 GB+

WARNING

Longhorn consomme environ 500 MB de RAM par nœud. Pour notre cluster VirtualBox minimal (2 nœuds, 2 GB RAM chacun), préférez local-path-provisioner.

-> Configuration Talos pour Longhorn

Longhorn nécessite des modules kernel et des chemins spécifiques. Modifiez vos fichiers de configuration Talos :

yaml
# controlplane.yaml et worker.yaml
machine:
  kubelet:
    extraMounts:
      - destination: /var/lib/longhorn
        type: bind
        source: /var/lib/longhorn
        options:
          - bind
          - rshared
          - rw
  sysctls:
    vm.max_map_count: "262144"
  kernel:
    modules:
      - name: iscsi_tcp
      - name: nvme_tcp

Appliquez les configurations mises à jour :

sh
talosctl apply-config --nodes 192.168.56.10 --file controlplane.yaml
talosctl apply-config --nodes 192.168.56.11 --file worker.yaml

-> Installation de Longhorn via Helm

sh
# Ajouter le repo Helm
helm repo add longhorn https://charts.longhorn.io
helm repo update

# Installer Longhorn
helm install longhorn longhorn/longhorn \
  --namespace longhorn-system \
  --create-namespace \
  --set defaultSettings.defaultDataPath="/var/lib/longhorn" \
  --set defaultSettings.defaultReplicaCount=2 \
  --set persistence.defaultClassReplicaCount=2

-> Vérifier l'installation

sh
# Attendre que tous les pods soient prêts (~2-3 minutes)
kubectl get pods -n longhorn-system -w

# Vérifier le StorageClass
kubectl get storageclass
# NAME                 PROVISIONER          RECLAIMPOLICY   VOLUMEBINDINGMODE    ALLOWVOLUMEEXPANSION
# longhorn (default)   driver.longhorn.io   Delete          Immediate            true

-> Accéder à l'interface web Longhorn

sh
kubectl port-forward -n longhorn-system svc/longhorn-frontend 8080:80
# Ouvrir http://localhost:8080

L'interface permet de :

  • Voir l'état des volumes et réplicas
  • Créer des snapshots et backups
  • Monitorer l'espace disque
  • Configurer la réplication

Fonctionnalités Longhorn

Réplication automatique

Longhorn réplique automatiquement les données sur plusieurs nœuds :

┌─────────────────────────────────────────────────────────────┐
│                        Volume PVC                            │
│                                                              │
│  ┌─────────────┐    ┌─────────────┐    ┌─────────────┐      │
│  │  Replica 1  │    │  Replica 2  │    │  Replica 3  │      │
│  │  (node-1)   │    │  (node-2)   │    │  (node-3)   │      │
│  └─────────────┘    └─────────────┘    └─────────────┘      │
│         │                 │                  │               │
│         └────────────┬────┴──────────────────┘               │
│                      │                                       │
│              ┌───────▼───────┐                               │
│              │   Longhorn    │                               │
│              │   Engine      │                               │
│              └───────────────┘                               │
└─────────────────────────────────────────────────────────────┘

Si un nœud tombe, Longhorn reconstruit automatiquement les réplicas sur les nœuds restants.

Snapshots et backups

sh
# Créer un snapshot via kubectl
kubectl apply -f - <<EOF
apiVersion: longhorn.io/v1beta2
kind: Snapshot
metadata:
  name: my-snapshot
  namespace: longhorn-system
spec:
  volume: pvc-xxxx-xxxx  # Nom du volume Longhorn
EOF

# Ou via l'interface web : Volume → Take Snapshot

Backup vers S3

Configurez un backup target pour sauvegarder vers S3 (ou MinIO) :

sh
# Via Helm values
helm upgrade longhorn longhorn/longhorn \
  --namespace longhorn-system \
  --set defaultSettings.backupTarget="s3://bucket-name@region/" \
  --set defaultSettings.backupTargetCredentialSecret="longhorn-backup-secret"

Créez le secret avec les credentials S3 :

yaml
apiVersion: v1
kind: Secret
metadata:
  name: longhorn-backup-secret
  namespace: longhorn-system
type: Opaque
stringData:
  AWS_ACCESS_KEY_ID: "your-access-key"
  AWS_SECRET_ACCESS_KEY: "your-secret-key"
  AWS_ENDPOINTS: "https://s3.amazonaws.com"  # ou URL MinIO

ReadWriteMany (RWX)

Longhorn supporte les volumes RWX (accès simultané depuis plusieurs pods) via NFS :

yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: shared-data
spec:
  accessModes:
    - ReadWriteMany  # RWX
  storageClassName: longhorn
  resources:
    requests:
      storage: 5Gi

Comparaison des solutions de stockage

Critèrelocal-pathLonghornRook-Ceph
ComplexitéTrès simpleMoyenneComplexe
RAM utilisée~15 MB~500 MB/nœud~2 GB/nœud
RéplicationNonOuiOui
SnapshotsNonOuiOui
RWXNonOuiOui
Cas d'usageDev, CI/CDHomelab, PMEEnterprise

Migrer de local-path vers Longhorn

Si vous avez commencé avec local-path et voulez migrer vers Longhorn :

  1. Installer Longhorn (voir ci-dessus)

  2. Changer le StorageClass par défaut

sh
# Retirer le défaut de local-path
kubectl patch storageclass local-path -p '{"metadata": {"annotations":{"storageclass.kubernetes.io/is-default-class":"false"}}}'

# Mettre longhorn par défaut
kubectl patch storageclass longhorn -p '{"metadata": {"annotations":{"storageclass.kubernetes.io/is-default-class":"true"}}}'
  1. Pour les PVC existants, vous devrez :
    • Créer un nouveau PVC avec Longhorn
    • Copier les données (via un pod avec les deux PVC montés)
    • Mettre à jour le Deployment pour utiliser le nouveau PVC

Déploiement du Homelab

Maintenant que le cluster et le stockage sont prêts, déployons quelques applications.

Applications du homelab

ApplicationDescriptionRessources
GlanceDashboard avec bookmarks et widgetsTrès léger (~32 MB)
MinifluxLecteur RSS minimalisteLéger (~64 MB)
VaultwardenGestionnaire de mots de passeLéger (~64 MB)

Structure des manifestes

homelab/
├── glance/
│   ├── namespace.yaml
│   ├── configmap.yaml
│   ├── deployment.yaml
│   └── service.yaml
├── miniflux/
│   ├── namespace.yaml
│   ├── postgres.yaml
│   ├── deployment.yaml
│   └── service.yaml
└── vaultwarden/
    ├── namespace.yaml
    ├── secret.yaml
    ├── pvc.yaml
    ├── deployment.yaml
    └── service.yaml

Glance - Dashboard

Glance est un dashboard léger et élégant pour visualiser vos services.

yaml
# glance/namespace.yaml
apiVersion: v1
kind: Namespace
metadata:
  name: glance
---
# glance/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: glance-config
  namespace: glance
data:
  glance.yml: |
    pages:
      - name: Home
        columns:
          - size: small
            widgets:
              - type: clock
                hour-format: "24h"
              - type: weather
                location: Paris, France
          - size: full
            widgets:
              - type: bookmarks
                groups:
                  - title: Homelab
                    links:
                      - title: Vaultwarden
                        url: http://192.168.56.10:30080
                      - title: Miniflux
                        url: http://192.168.56.10:30081
                  - title: Kubernetes
                    links:
                      - title: Documentation K8s
                        url: https://kubernetes.io/docs/
                      - title: Talos Docs
                        url: https://www.talos.dev/docs/
              - type: rss
                limit: 5
                feeds:
                  - url: https://www.reddit.com/r/selfhosted/.rss
                    title: r/selfhosted
---
# glance/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: glance
  namespace: glance
spec:
  replicas: 1
  selector:
    matchLabels:
      app: glance
  template:
    metadata:
      labels:
        app: glance
    spec:
      containers:
      - name: glance
        image: glanceapp/glance:latest
        ports:
        - containerPort: 8080
        volumeMounts:
        - name: config
          mountPath: /app/glance.yml
          subPath: glance.yml
        resources:
          requests:
            memory: "32Mi"
            cpu: "10m"
          limits:
            memory: "128Mi"
            cpu: "100m"
      volumes:
      - name: config
        configMap:
          name: glance-config
---
# glance/service.yaml
apiVersion: v1
kind: Service
metadata:
  name: glance
  namespace: glance
spec:
  type: NodePort
  selector:
    app: glance
  ports:
  - port: 8080
    targetPort: 8080
    nodePort: 30000

-> Déployer Glance

sh
kubectl apply -f glance/
# namespace/glance created
# configmap/glance-config created
# deployment.apps/glance created
# service/glance created

kubectl get pods -n glance
# NAME                      READY   STATUS    RESTARTS   AGE
# glance-xxxxxxxxx-xxxxx    1/1     Running   0          30s

-> Accéder à Glance

Ouvrez votre navigateur : http://192.168.56.10:30000


Vaultwarden - Gestionnaire de mots de passe

Vaultwarden est une implémentation légère et compatible avec Bitwarden.

yaml
# vaultwarden/namespace.yaml
apiVersion: v1
kind: Namespace
metadata:
  name: vaultwarden
---
# vaultwarden/secret.yaml
apiVersion: v1
kind: Secret
metadata:
  name: vaultwarden-secrets
  namespace: vaultwarden
type: Opaque
stringData:
  admin-token: "votre-token-admin-genere"  # openssl rand -hex 32
---
# vaultwarden/pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: vaultwarden-data
  namespace: vaultwarden
spec:
  accessModes:
    - ReadWriteOnce
  storageClassName: local-path
  resources:
    requests:
      storage: 1Gi
---
# vaultwarden/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: vaultwarden
  namespace: vaultwarden
spec:
  replicas: 1
  selector:
    matchLabels:
      app: vaultwarden
  template:
    metadata:
      labels:
        app: vaultwarden
    spec:
      containers:
      - name: vaultwarden
        image: vaultwarden/server:latest
        env:
        - name: DOMAIN
          value: "http://192.168.56.10:30080"
        - name: SIGNUPS_ALLOWED
          value: "true"  # Mettre à false après création du premier compte
        - name: ADMIN_TOKEN
          valueFrom:
            secretKeyRef:
              name: vaultwarden-secrets
              key: admin-token
        ports:
        - containerPort: 80
        volumeMounts:
        - name: data
          mountPath: /data
        resources:
          requests:
            memory: "64Mi"
            cpu: "50m"
          limits:
            memory: "256Mi"
            cpu: "200m"
      volumes:
      - name: data
        persistentVolumeClaim:
          claimName: vaultwarden-data
---
# vaultwarden/service.yaml
apiVersion: v1
kind: Service
metadata:
  name: vaultwarden
  namespace: vaultwarden
spec:
  type: NodePort
  selector:
    app: vaultwarden
  ports:
  - port: 80
    targetPort: 80
    nodePort: 30080

-> Déployer Vaultwarden

sh
# Générer un token admin
openssl rand -hex 32
# Copiez le résultat et mettez-le dans le secret

kubectl apply -f vaultwarden/

-> Accéder à Vaultwarden


Miniflux - Lecteur RSS

Miniflux nécessite PostgreSQL. On va déployer les deux ensemble.

yaml
# miniflux/namespace.yaml
apiVersion: v1
kind: Namespace
metadata:
  name: miniflux
---
# miniflux/postgres.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: postgres-data
  namespace: miniflux
spec:
  accessModes:
    - ReadWriteOnce
  storageClassName: local-path
  resources:
    requests:
      storage: 1Gi
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: postgres
  namespace: miniflux
spec:
  replicas: 1
  selector:
    matchLabels:
      app: postgres
  template:
    metadata:
      labels:
        app: postgres
    spec:
      containers:
      - name: postgres
        image: postgres:15-alpine
        env:
        - name: POSTGRES_USER
          value: "miniflux"
        - name: POSTGRES_PASSWORD
          value: "miniflux123"
        - name: POSTGRES_DB
          value: "miniflux"
        ports:
        - containerPort: 5432
        volumeMounts:
        - name: data
          mountPath: /var/lib/postgresql/data
        resources:
          requests:
            memory: "128Mi"
            cpu: "100m"
          limits:
            memory: "256Mi"
            cpu: "500m"
      volumes:
      - name: data
        persistentVolumeClaim:
          claimName: postgres-data
---
apiVersion: v1
kind: Service
metadata:
  name: postgres
  namespace: miniflux
spec:
  selector:
    app: postgres
  ports:
  - port: 5432
    targetPort: 5432
---
# miniflux/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: miniflux
  namespace: miniflux
spec:
  replicas: 1
  selector:
    matchLabels:
      app: miniflux
  template:
    metadata:
      labels:
        app: miniflux
    spec:
      initContainers:
      - name: wait-for-postgres
        image: busybox
        command: ['sh', '-c', 'until nc -z postgres 5432; do echo waiting for postgres; sleep 2; done']
      containers:
      - name: miniflux
        image: miniflux/miniflux:latest
        env:
        - name: DATABASE_URL
          value: "postgres://miniflux:miniflux123@postgres:5432/miniflux?sslmode=disable"
        - name: RUN_MIGRATIONS
          value: "1"
        - name: CREATE_ADMIN
          value: "1"
        - name: ADMIN_USERNAME
          value: "admin"
        - name: ADMIN_PASSWORD
          value: "admin123"  # Changez ce mot de passe !
        ports:
        - containerPort: 8080
        resources:
          requests:
            memory: "64Mi"
            cpu: "50m"
          limits:
            memory: "256Mi"
            cpu: "500m"
---
# miniflux/service.yaml
apiVersion: v1
kind: Service
metadata:
  name: miniflux
  namespace: miniflux
spec:
  type: NodePort
  selector:
    app: miniflux
  ports:
  - port: 8080
    targetPort: 8080
    nodePort: 30081

-> Déployer Miniflux

sh
kubectl apply -f miniflux/

# Attendre que postgres soit prêt avant miniflux
kubectl get pods -n miniflux -w

-> Accéder à Miniflux


Récapitulatif

URLs des applications

ApplicationURLCredentials
Glancehttp://192.168.56.10:30000-
Vaultwardenhttp://192.168.56.10:30080À créer
Vaultwarden Adminhttp://192.168.56.10:30080/adminToken dans le secret
Minifluxhttp://192.168.56.10:30081admin / admin123

Vérifier l'état du cluster

sh
# Voir tous les pods
kubectl get pods -A

# Voir l'utilisation des ressources
kubectl top nodes
kubectl top pods -A

# Dashboard Talos
talosctl dashboard --nodes 192.168.56.10

Ressources consommées

Avec les 3 applications déployées, vous devriez avoir :

RessourceUtiliséDisponible
CPU~300m4000m
RAM~700Mi4Gi

Il reste de la marge pour expérimenter !

Prochaines étapes

Pour aller plus loin avec votre homelab :

  1. Ajouter plus de RAM aux VMs pour déployer plus d'applications
  2. Configurer un Ingress Controller (Traefik) pour avoir des URLs propres
  3. Ajouter des certificats TLS avec cert-manager
  4. Configurer des backups de vos données
  5. Ajouter du monitoring avec Prometheus et Grafana (si ressources suffisantes)

Nettoyage

Pour supprimer le homelab :

sh
# Supprimer les applications
kubectl delete namespace glance miniflux vaultwarden

# Ou supprimer le cluster entier
talosctl reset --nodes 192.168.56.10,192.168.56.11 --graceful=false

Pour supprimer les VMs VirtualBox, éteignez-les et supprimez-les depuis l'interface VirtualBox.