Self-Hosting et Cloud Hybride : Mon Infrastructure Perso avec Gitea et Scaleway

Self-Hosting et Cloud Hybride : Mon Infrastructure Perso avec Gitea et Scaleway

20 novembre 2025·
Damien

Retour d’expĂ©rience sur la construction de mon infrastructure personnelle : migration de GitHub vers Gitea auto-hĂ©bergĂ©, et dĂ©ploiement de labs rĂ©seau Ă©phĂ©mĂšres sur Scaleway. Le tout avec Proxmox et Wireguard.

Contexte et Motivations

En tant qu’ingĂ©nieur rĂ©seau travaillant dans le domaine de l’automatisation et de l’orchestration, j’ai toujours eu besoin d’un environnement pour expĂ©rimenter et apprendre. Jusqu’Ă  rĂ©cemment, j’utilisais GitHub pour mon code et ContainerLab en local/AWS via DevPod pour mes simulations rĂ©seau.

Mais plusieurs envies ont émergé :

  • Apprentissage : DĂ©ployer et gĂ©rer un serveur Git complet avec CI/CD
  • SouverainetĂ© : HĂ©berger mes donnĂ©es en France (Ă  minima en Europe), contrĂŽler mon infrastructure
  • FlexibilitĂ© : Pouvoir lancer des labs rĂ©seau Ă  la demande sans saturer ma machine locale
  • Automatisation : Scripter le provisionnement complet de mes environnements

L’Architecture Globale

Architecture

Stack Technique

Homelab :

  • Proxmox VE : Hyperviseur pour VMs et LXC
  • LXC Containers : Gitea, runners, services divers
  • Ansible : Gestion des configurations et mises Ă  jour
  • Grafana/Prometheus/Loki : Monitoring et supervision

Exposition publique :

  • Dedibox Scaleway : Instance dĂ©diĂ©e avec IP fixe
  • Nginx Proxy Manager : Reverse proxy avec SSL automatique
  • Wireguard VPN : Tunnel sĂ©curisĂ© entre Scaleway et homelab

Cloud Scaleway :

  • Object Storage : HĂ©bergement du blog Hugo (S3-compatible)
  • Instances : Labs rĂ©seau Ă©phĂ©mĂšres provisionnĂ©s Ă  la demande
  • Scaleway CLI : Automatisation complĂšte

Partie 1 : Migration GitHub → Gitea Auto-HĂ©bergĂ©

Pourquoi Gitea ?

Gitea est un serveur Git leger, parfait pour du self-hosting :

  • LĂ©ger : IdĂ©al pour un LXC sur Proxmox
  • Compatible GitHub Actions : Migration des workflows sans réécriture
  • Complet : Issues, PRs, CI/CD, webhooks
  • Open-source : CommunautĂ© active

Déploiement avec Proxmox Helper Scripts

PlutĂŽt que de tout configurer manuellement, j’utilise les excellents Proxmox Helper Scripts qui automatisent la crĂ©ation de LXC prĂ©configurĂ©s.

Installation de Gitea :

# Sur le nƓud Proxmox, exĂ©cuter le script
bash -c "$(wget -qLO - https://github.com/community-scripts/ProxmoxVE/raw/main/ct/gitea.sh)"

Le script :

  • CrĂ©e un LXC Debian 12
  • Installe Gitea et sqlite
  • Configure les services systemd
  • PrĂ©pare l’environnement avec les bonnes permissions

Configuration post-installation :

  • AccĂšs web : http://<IP_LXC>:3000
  • Configuration initiale via l’interface
  • URL du site : https://gitea.arnodo.fr

Architecture Réseau : Wireguard + Nginx Proxy Manager

Le problÚme : Gitea tourne dans mon homelab (IP privée), mais je veux y accéder depuis Internet.

La solution :

  1. Dedibox Scaleway avec IP publique fixe et Nginx Proxy Manager
  2. Wireguard VPN entre la Dedibox et le homelab
  3. Le reverse proxy route gitea.arnodo.fr vers l’IP privĂ©e du LXC via le tunnel

Configuration Wireguard (cÎté homelab) :

[Interface]
Address = 10.0.0.1/24
PrivateKey = <private_key>
ListenPort = 51820

[Peer]
# Dedibox Scaleway
PublicKey = <dedibox_public_key>
AllowedIPs = 10.0.0.2/32
Endpoint = <dedibox_public_ip>:51820
PersistentKeepalive = 25

Nginx Proxy Manager :

  • Proxy Host : gitea.arnodo.fr
  • Forward Hostname/IP : 10.0.0.x (IP du LXC Gitea via Wireguard)
  • Forward Port : 3000
  • SSL : Let’s Encrypt automatique
  • Websockets : ActivĂ©s

Gestion avec Ansible

Pour maintenir Gitea Ă  jour et gĂ©rer les configurations, j’utilise Ansible.

Playbook de mise Ă  jour (update-gitea.yml) :

---
- name: Update Gitea
  hosts: gitea
  become: yes
  tasks:
    - name: Update apt cache
      apt:
        update_cache: yes
        cache_valid_time: 3600

    - name: Upgrade Gitea and system packages
      apt:
        upgrade: dist
        autoremove: yes
        autoclean: yes

    - name: Restart Gitea service
      systemd:
        name: gitea
        state: restarted
        enabled: yes

    - name: Check Gitea version
      command: gitea --version
      register: gitea_version

    - debug:
        msg: "{{ gitea_version.stdout }}"

Exécution :

ansible-playbook -i inventory.ini update-gitea.yml

Monitoring avec Grafana

Gitea expose des métriques Prometheus (https://docs.gitea.com/administration/config-cheat-sheet#metrics-metrics)
Configuration :

Dans Gitea (app.ini) :

[metrics]
ENABLED = true
TOKEN = <secret_token>

Prometheus scrape config :

scrape_configs:
  - job_name: 'gitea'
    metrics_path: /metrics
    bearer_token: '<secret_token>'
    static_configs:
      - targets: ['<gitea_lxc_ip>:3000']

Dashboard Grafana (https://grafana.com/docs/grafana-cloud/monitor-infrastructure/integrations/integration-reference/integration-gitea/#gitea-integration-for-grafana-cloud) :

  • Nombre de repositories, utilisateurs
  • RequĂȘtes HTTP (rate, latence)
  • État des runners CI/CD
  • Utilisation CPU/RAM du LXC

Migration du Code depuis GitHub

Simple et rapide :
Utiliser la fonction d’import de Gitea (Settings > New Migration > GitHub) qui migre aussi les issues et releases.

CI/CD : Déploiement Hugo vers Scaleway Object Storage

Mon blog Hugo se déploie automatiquement sur Scaleway Object Storage à chaque push.

Installation de Gitea Runner (https://docs.gitea.com/usage/actions/act-runner)

CrĂ©er l’utilisateur systĂšme runner :

useradd -r -m -d /var/lib/gitea-runner -s /bin/bash gitea-runner

Voici un petit script qui peut aider Ă  installer le runner directement dans un LXC:

sudo apt install -y jq curl tar # si pas déjà

LATEST=$(curl -s 'https://gitea.com/api/v1/repos/gitea/act_runner/releases' | jq -r '.[0].tag_name')
echo "Latest act_runner: $LATEST"

# construire URL de binaire (nommage used: act_runner-<os>-<arch>)
OS=$(uname -s | tr '[:upper:]' '[:lower:]')
ARCH=$(uname -m)
# Certains serveurs distribuent binaire sans tar; adapter si archive
URL="https://gitea.com/gitea/act_runner/releases/download/${LATEST}/act_runner-${LATEST#v}-${OS}-${ARCH}"

# essayer télécharger binaire
curl -fL "$URL" -o /tmp/act_runner || {
  echo "TĂ©lĂ©chargement direct Ă©chouĂ© — vĂ©rifier le nom exact sur la page release." >&2
  exit 1
}

sudo mv /tmp/act_runner /usr/local/bin/act_runner
sudo chmod +x /usr/local/bin/act_runner

et pour valider

/usr/local/bin/act_runner --version

Note

Il est important d’enregistrer le runner pour qu’il soit reconnu par Gitea.
Pour plus d’informations sur la configuration du runner, consultez la documentation officielle de Gitea.
https://docs.gitea.io/fr/docs/usage/actions/runner/

Workflow Gitea Actions (.gitea/workflows/deploy.yml) :

name: Build and Deploy Hugo

on:
  pull_request:
    types: [closed]
    branches:
      - main

jobs:
  build_and_deploy:
    if: github.event.pull_request.merged == true
    name: Deploy Hugo Website
    runs-on: self-hosted

    container:
      image: debian:bookworm-slim

    steps:
      - name: Install dependencies
        run: |
          apt-get update
          apt-get install -y git curl ca-certificates wget

      - name: Install Hugo
        run: |
          wget https://github.com/gohugoio/hugo/releases/download/v0.152.2/hugo_extended_withdeploy_0.152.2_linux-amd64.deb -O /tmp/hugo.deb
          dpkg -i /tmp/hugo.deb

      - name: Checkout code
        run: |
          git clone --recurse-submodules https://gitea.arnodo.fr/Damien/Notebook.git /tmp/workspace
          cd /tmp/workspace
          git checkout ${{ github.sha }}

      - name: Build site
        run: /usr/local/bin/hugo
        working-directory: /tmp/workspace

      - name: Deploy to Scaleway
        run: /usr/local/bin/hugo deploy --force --maxDeletes -1
        working-directory: /tmp/workspace
        env:
          AWS_ACCESS_KEY_ID: ${{ secrets.SCW_ACCESS_KEY }}
          AWS_SECRET_ACCESS_KEY: ${{ secrets.SCW_SECRET_KEY }}

Configuration Hugo (hugo.yaml) :

deployment:
  targets:
    - name: "notebook-arnodo-fr"
      URL: "s3://notebook-arnodo-fr?endpoint=https://s3.fr-par.scw.cloud&region=fr-par"

Configuration Scaleway Object Storage :

  1. Créer un bucket notebook-arnodo-fr
  2. Activer le mode “Static Website Hosting”
  3. Générer les credentials API (Access Key + Secret Key)
  4. Les ajouter comme secrets dans Gitea (Settings > Secrets > Actions)

Déploiement :

git add .
git commit -m "New blog post"
git push origin main

Le workflow se déclenche automatiquement, Hugo génÚre le site, et le déploie sur Scaleway Object Storage. Le site est accessible instantanément via le CDN.

Partie 2 : Labs Réseau sur Scaleway

Le ProblĂšme

ContainerLab avec plusieurs Arista EOS en local, c’est :

  • Gourmand : 4-8 GB RAM par conteneur cEOS
  • Local : Pas d’accĂšs depuis l’extĂ©rieur
  • Conflits : Avec d’autres services Docker/K8s

La Solution : Instances Scaleway Ă  la Demande

Concept :

  • CrĂ©er une instance Scaleway quand j’ai besoin d’un lab
  • Installer automatiquement ContainerLab/le VPN via cloud-init
  • DĂ©truire l’instance aprĂšs utilisation
  • Facturation Ă  l’heure (< 1€ pour quelques heures de lab)

Script d’Automatisation : Scaleway CLI

J’ai dĂ©veloppĂ© un script Bash qui gĂšre tout le cycle de vie d’une instance de lab.

Fonctionnalités :

  • CrĂ©ation : Instance + Security Group (SSH depuis mon IP uniquement)
  • Start/Stop : Gestion de l’instance
  • Suppression : Nettoyage complet (instance, volumes, IP, SG)

Structure du script (scaleway-instance.sh) :

#!/bin/bash
# Configuration
INSTANCE_NAME="NetLab"
ZONE="fr-par-1"
IMAGE="debian_bookworm"
VOLUME_SIZE=20  # GB
USER_DATA_FILE="user_data.txt"
SECURITY_GROUP_NAME="${INSTANCE_NAME}-SG"

# Détecte l'IP publique actuelle
get_public_ip() {
  curl -4 -s ifconfig.me
}

# Crée un Security Group limitant SSH à l'IP publique
create_or_update_security_group() {
  PUBLIC_IP=$(get_public_ip)
  # Crée le SG avec inbound SSH uniquement depuis PUBLIC_IP/32
  # ...
}

# Actions : create, start, stop, delete
case "$1" in
  start)
    # Démarre l'instance existante
    scw instance server start "$INSTANCE_ID" --wait
    ;;
  stop)
    # ArrĂȘte l'instance
    scw instance server stop "$INSTANCE_ID" --wait
    ;;
  delete)
    # Supprime instance + volumes + IP + SG
    scw instance server terminate "$INSTANCE_ID" --with-ip --with-block
    scw instance security-group delete "$SG_ID"
    ;;
  *)
    # Crée une nouvelle instance
    create_instance "$1"  # Type d'instance (DEV1-S, GP1-XS, ...)
    ;;
esac

Cloud-Init : Configuration Automatique

Le fichier user_data.txt contient les instructions cloud-init pour provisionner l’instance automatiquement.

Exemple (user_data.txt) :

#cloud-config
package_update: true
package_upgrade: true

packages:
  - git
  - curl
  - docker.io
  - docker-compose

runcmd:
  # Installation de ContainerLab
  - bash -c "$(curl -sL https://get.containerlab.dev)"
  
  # Clone d'un repo avec des topologies
  - git clone https://gitea.arnodo.fr/Damien/network-labs.git /root/labs
  
  # Démarrage d'une topologie par défaut
  - cd /root/labs && containerlab deploy -t spine-leaf.clab.yml

Utilisation Pratique

Créer un lab :

# Crée une instance DEV1-S avec 20 GB de stockage
./scaleway-instance.sh DEV1-S 20

# Attend quelques minutes pour cloud-init
# RécupÚre l'IP publique
scw instance server list name=NetLab -o json | jq -r '.servers[0].public_ip.address'

# SSH vers l'instance
ssh root@<IP_PUBLIQUE>

# ContainerLab est déjà lancé !
containerlab inspect

Détruire le lab :

./scaleway-instance.sh delete

Intégration avec Raycast

Pour simplifier encore plus, j’ai créé un script Raycast qui me permet de gĂ©rer mes instances directement depuis mon Mac.

Script Raycast :

#!/bin/bash
# @raycast.schemaVersion 1
# @raycast.title Scaleway Instance
# @raycast.mode silent
# @raycast.icon đŸ–„ïž
# @raycast.argument1 { "type": "text", "placeholder": "Action or instance type" }
# @raycast.argument2 { "type": "text", "placeholder": "Volume size", "optional": true }
# @raycast.packageName NetLab

/path/to/scaleway-instance.sh "$1" "$2"

Utilisation :

  • ⌘ + Space → “Scaleway Instance DEV1-S” → CrĂ©e l’instance
  • ⌘ + Space → “Scaleway Instance delete” → Supprime l’instance

Cas d’Usage : Lab BGP/EVPN avec Arista

Topologie ContainerLab (spine-leaf.clab.yml) :

name: evpn-lab

topology:
  nodes:
    spine1:
      kind: ceos
      image: ceos:latest
    spine2:
      kind: ceos
      image: ceos:latest
    leaf1:
      kind: ceos
      image: ceos:latest
    leaf2:
      kind: ceos
      image: ceos:latest

  links:
    - endpoints: ["spine1:eth1", "leaf1:eth1"]
    - endpoints: ["spine1:eth2", "leaf2:eth1"]
    - endpoints: ["spine2:eth1", "leaf1:eth2"]
    - endpoints: ["spine2:eth2", "leaf2:eth2"]

Workflow :

  1. CrĂ©er l’instance Scaleway
  2. Cloud-init déploie la topologie
  3. Configurer BGP/EVPN via Ansible ou manuellement
  4. Tester, expérimenter
  5. DĂ©truire l’instance

CoĂ»t : Instance DEV1-S (2 vCPU, 2GB) = ~0.015€/heure. 4 heures de lab = 0.06€.

SouverainetĂ© NumĂ©rique : Pourquoi C’est Important

Cette infrastructure hybride reflÚte une conviction personnelle sur la souveraineté numérique.

Le Contexte

Dans mon travail d’ingĂ©nieur rĂ©seau, je vois l’importance de la maĂźtrise de ses infrastructures.

Choisir Scaleway (groupe Iliad, français) et self-hoster Gitea, c’est :

  • Soutenir l’Ă©cosystĂšme tech europĂ©en
  • Garantir la protection RGPD : Juridiction française
  • RĂ©duire la latence : Datacenters Ă  Paris
  • Comprendre : MaĂźtriser sa chaĂźne complĂšte

Apprentissage par la Pratique

En tant que professionnel du réseau (Arista, BGP/EVPN, automation), self-hoster me permet de :

  • Appliquer les principes Infrastructure as Code
  • Comprendre en profondeur les mĂ©canismes CI/CD
  • ExpĂ©rimenter sans limite
  • Reproduire des environnements professionnels

Bilan

Ce qui Fonctionne Bien

Gitea auto-hébergé :

  • TrĂšs rapide et stable
  • Proxmox Helper Scripts = installation en 5 minutes
  • Ansible gĂšre les mises Ă  jour proprement
  • Grafana surveille tout

Wireguard + Nginx Proxy Manager :

  • Exposition sĂ©curisĂ©e du homelab
  • Performances excellentes
  • Configuration simple

Labs Scaleway :

  • Provisionnement en 3 minutes
  • FlexibilitĂ© totale (taille, durĂ©e)
  • CoĂ»ts prĂ©visibles (facturation Ă  l’heure)

CI/CD Hugo → Scaleway Object Storage :

  • Push to deploy en 2 minutes
  • Gratuit (quelques centimes/mois pour le stockage)
  • CDN intĂ©grĂ© = site ultra rapide

Les Défis

Complexité initiale :

  • Wireguard + reverse proxy = courbe d’apprentissage
  • PremiĂšre configuration Proxmox/LXC = quelques heures

Maintenance :

  • ResponsabilitĂ© des mises Ă  jour (heureusement Ansible aide !)
  • Monitoring Ă  configurer soi-mĂȘme
  • Sauvegardes Ă  automatiser

Dépendances :

  • Si la Dedibox tombe, Gitea n’est plus accessible
  • Solution : Failover avec une 2e Dedibox ou VPS (Ă  venir)

Prochaines Étapes

  • Haute disponibilitĂ© : Seconde Dedibox pour du failover
  • Backup automatique : Scripts pour sauvegarder Gitea vers Scaleway Object Storage
  • Plus d’automatisation : Terraform pour provisionner toute l’infra Scaleway
  • MCP Arista : DĂ©velopper un serveur MCP pour interagir avec les Ă©quipements rĂ©seau via LLM Locaux
  • IntĂ©gration Netbox : Webhook depuis Netbox vers pipeline de validation rĂ©seau

Conclusion

Cette infrastructure hybride (homelab Proxmox + cloud Scaleway) offre le meilleur des deux mondes :

  • ContrĂŽle : DonnĂ©es sensibles (code, configurations) dans le homelab
  • FlexibilitĂ© : Ressources cloud pour les besoins ponctuels
  • Apprentissage : Environnement complet pour expĂ©rimenter
  • SouverainetĂ© : Tout hĂ©bergĂ© en France, chez des acteurs europĂ©ens

Le self-hosting n’est pas qu’une question de coĂ»ts (spoiler : je paie autant qu’avant, voire plus), mais d’apprentissage, de maĂźtrise et de comprĂ©hension profonde des systĂšmes.

Pour un ingĂ©nieur rĂ©seau ou DevOps, c’est l’environnement idĂ©al pour reproduire des cas d’usage professionnels et monter en compĂ©tences.

Ressources

Documentation

Mes Repos

Communauté