2178 mots · 11 min de lecture

Table of contents
Raspberry Pi Zero avec hat 4G

Et si vous pouviez faire tourner un blog sur 1W de puissance, servi en 4G depuis un Raspberry Pi Zero alimenté par un panneau solaire ?

En tant qu’ingénieurs logiciel, nous passons la plupart de notre temps dans un monde de ressources cloud virtuellement infinies, où les limites physiques ont été remplacées par des factures élastiques et des couches d’abstraction (IaaS, PaaS, SaaS) qui nous tiennent éloignés du matériel. Il est facile d’oublier ce qui est possible avec très peu.

C’est une expérience pour faire plus avec moins. Suivez-moi dans cette aventure.

Ceci est la Partie 1 d’une série en 2 parties. La Partie 1 (cet article) couvre la construction et le service du blog en 4G via un tunnel Cloudflare. La Partie 2 va plus loin hors réseau : alimenter l’ensemble avec un panneau solaire et un chapeau batterie, le maintenir en marche la nuit, configurer le module GPS du hat, et quelques astuces pour tirer le meilleur parti de chaque milliwatt du Pi.

Prérequis

Prérequis avant de commencer :

  • Un nom de domaine ajouté à Cloudflare (plan gratuit) — voir la documentation Cloudflare
  • Une paire de clés SSH sur votre machine (~/.ssh/id_rsa)
  • Tout au long de ce tutoriel, remplacez <user> par votre nom d’utilisateur choisi (ex. thylong) et <hostname> par votre nom d’hôte choisi (ex. solar)

Matériel

ComposantCoût
Raspberry Pi Zero 2 W (le Zero 2 W est recommandé — il supporte les OS 32 et 64 bits ; le Zero W original est 32 bits uniquement)18€
Waveshare SIM7600G-H 4G hat75€
Carte Micro-SD (min. 8Go) + adaptateur MicroSD vers SD (pour flasher depuis un ordinateur portable)5€
Panneau solaire 10W 5V USB-C25€
Pi Sugar 3 Plus chapeau batterie 1200 mAh — configuration couverte dans la Partie 234€
Nano SIM avec abonnement mobileÀ partir de 1€/mois
Total150€ + 1€/mois
Raspberry Pi Zero assemblé avec hat 4G

Notes : De nombreuses alternatives à ce hat 4G sont possibles pour des budgets plus serrés, idem pour la batterie.

Logiciel

ComposantCoût
Configuration du domaine sur Cloudflare~
Tunnel CloudflareGratuit

Étapes

Montage du matériel

  • Éteignez le Raspberry
  • Branchez le hat sur le Raspberry Pi 0, ça devrait ressembler à ceci :
Hat 4G monté sur Raspberry Pi Zero
  • Insérez une nano SIM dans le hat 4G

Configuration logicielle

Installer l’OS

Téléchargez Raspberry Pi Imager : https://www.raspberrypi.com/software/

Flashez Raspberry Pi OS Lite (32 bits pour Zero W, 64 bits pour Zero 2 W) sur votre carte MicroSD.

Dans les Options avancées de l’imager (l’icône engrenage), avant d’écrire :

  • Définissez le hostname (ex. solar) — c’est comme ça que vous vous connecterez en SSH avec ssh <user>@solar
  • Définissez votre nom d’utilisateur et mot de passe (ex. thylong)
  • Activez SSH avec votre clé publique
  • Ajoutez vos identifiants WiFi — le Pi a besoin d’un accès internet au premier démarrage pour activer Raspberry Pi Connect

Note : Si vous n’avez ni clavier ni écran pour vous connecter au Raspberry, assurez-vous de fournir des identifiants WiFi valides et d’activer Raspberry Pi Connect pour pouvoir utiliser le partage d’écran.

Il peut falloir quelques minutes pour que le Raspberry se connecte au service. Si après 5 minutes l’appareil n’apparaît toujours pas, il n’a probablement pas réussi à se connecter au WiFi et/ou à internet. Vous devrez refaire la phase de flashage de la carte SD.

Erreurs courantes : un mauvais SSID WiFi, une erreur de mot de passe, ou une clé d’authentification invalide.

Configurer le hat 4G/LTE

Démarrez le Raspberry Pi.

Vérifier le branchement du hat

Assurez-vous que les LED du hat sont :

  • La LED PWR est allumée
  • La LED NET clignote ainsi :
    • Clignotement lent (1s allumé / 1s éteint) = recherche de réseau
    • Clignotement rapide (100ms) = enregistré et connecté ✓

Si la LED NET est éteinte ou clignote lentement après 30 secondes, le hat n’est pas correctement connecté physiquement au Raspberry Pi Zero ou la SIM n’est pas reconnue.

SIM7600 Hat 4G vue du dessus et du dessous

Vérifier la connectivité du hat depuis le Raspberry

Connectez-vous à Raspberry Pi Connect

Installez les paquets nécessaires :

sudo apt update && sudo apt install -y minicom modemmanager network-manager

Ouvrez un terminal et assurez-vous que ces deux lignes sont présentes dans /boot/firmware/config.txt :

enable_uart=1
dtoverlay=disable-bt

Ces deux lignes libèrent les broches UART de l’en-tête GPIO, que le modem utilise pour la communication série. Sans elles, le hat peut ne pas être détecté correctement.

Si vous faites des modifications, redémarrez pour les appliquer (sudo reboot).

Puis exécutez ls /dev/ttyU* pour lister les ttys, le Raspberry devrait avoir détecté le hat via USB et afficher :

/dev/ttyUSB0 /dev/ttyUSB1 /dev/ttyUSB2 /dev/ttyUSB3 /dev/ttyUSB4

Voici une correspondance simple des ttys :

PortFonction
/dev/ttyUSB0Diagnostique
/dev/ttyUSB1GPS/NMEA
/dev/ttyUSB2Commandes AT ← utilisez celui-ci
/dev/ttyUSB3PPP / données
/dev/ttyUSB4Audio/autre

Vous pouvez tester la communication via le port de commandes AT :

sudo minicom -D /dev/ttyUSB2 -b 115200

Puis :

  1. Appuyez sur Ctrl+A puis E pour activer l’écho
    1. Tapez AT + Entrée
    2. → devrait retourner OK
  2. Puis vérifiez la SIM :
    1. Tapez AT+CPIN?
    2. → devrait retourner +CPIN: READY
  3. Puis vérifiez le réseau
    1. Tapez AT+COPS?
    2. → devrait afficher les détails Orange (si vous utilisez la multi-SIM Orange)

Autres commandes AT de test pour les curieux :

Commande ATDescriptionRetour
ATCommande de test ATOK
ATEATE1 : Echo activé, ATE0 : Echo désactivéOK
AT+CGMIIdentification du fabricantOK
AT+CGMMIdentification du modèleOK
AT+CGSNIdentification du numéro de sérieOK
AT+CSUBVersion du produitOK
AT+CGMRVersion du firmwareOK
AT+IPREXConfiguration du débit du modèle+IPREX:OK
AT+CRESETRéinitialisation du modèleOK
AT+CSQQualité du signalOK
AT+CPIN?Statut de la carte SIM+CPIN:READY
AT+COPS?Informations sur l’opérateur+COPS:OK
AT+CREG?Statut d’enregistrement réseau+CREG: OK
AT+CPSI?Informations système UE
AT+CNMPSélection du mode réseauOK

Si vous êtes arrivé jusqu’ici, félicitations — le modem est prêt pour la connexion !

Si vous rencontrez des erreurs ou n’avez pas le résultat attendu avec minicom, vérifiez la sortie de mmcli -L, cela vous aidera au débogage.

Pour créer la connexion, exécutez les commandes suivantes :

Nous utilisons l’APN orange (pas orange.fr). L’APN orange.fr est utilisé pour le partage de connexion et désactive l’IPv6 — nous avons besoin de orange pour obtenir une adresse IPv6 publique plus tard.

sudo nmcli connection add type gsm ifname '*' con-name orange-4g apn orange
sudo nmcli connection up orange-4g
sudo nmcli connection modify orange-4g connection.autoconnect yes

Pour tester la connexion, utilisez curl :

curl --interface wwan0 https://ifconfig.me

Si vous voyez votre IP publique, félicitations, vous êtes connecté en 4G !

Activer l’IPv6 et le rendre persistant

La 4G d’Orange bloque les connexions entrantes en IPv4 (CGNAT) et en IPv6 (pare-feu). Cependant, Cloudflare Tunnel doit se connecter en sortie sur le port 7844 — Orange bloque cela en IPv4 mais l’autorise en IPv6. Nous devons donc configurer le double pile IPv4v6 et le rendre persistant après les redémarrages.

# Définir le bearer EPS initial en double pile
sudo mmcli -m 0 --3gpp-set-initial-eps-bearer-settings="apn=orange,ip-type=ipv4v6"

# Reconnecter en double pile
sudo mmcli -m 0 --simple-disconnect && sleep 3 && sudo mmcli -m 0 --simple-connect="apn=orange,ip-type=ipv4v6"

# Lire la config IPv6 du bearer et l'appliquer à wwan0
BEARER=$(mmcli -m 0 --output-json | grep -o "/org/freedesktop/ModemManager1/Bearer/[0-9]*" | tail -1)
IPV6=$(mmcli -b ${BEARER##*/} --output-json | grep -oP '"address"\s*:\s*"\K[0-9a-f:]+(?=")' | head -1)
GW=$(mmcli -b ${BEARER##*/} --output-json | grep -oP '"gateway"\s*:\s*"\K[0-9a-f:]+(?=")' | head -1)
sudo ip -6 addr add ${IPV6}/64 dev wwan0
sudo ip -6 route add default via ${GW} dev wwan0

# Vérifier — devrait retourner votre IPv6 publique
curl -6 -s --interface wwan0 https://ifconfig.me && echo

L’adresse IPv6 attribuée ci-dessus est perdue au redémarrage. Pour la rendre persistante, créez un service systemd oneshot qui la réapplique après chaque connexion du modem :

sudo tee /usr/local/bin/apply-ipv6.sh << 'EOF'
#!/bin/bash
sleep 5
BEARER=$(mmcli -m 0 --output-json | grep -o "/org/freedesktop/ModemManager1/Bearer/[0-9]*" | tail -1)
IPV6=$(mmcli -b ${BEARER##*/} --output-json 2>/dev/null | grep -oP '"address"\s*:\s*"\K[0-9a-f:]+(?=")' | head -1)
GW=$(mmcli -b ${BEARER##*/} --output-json 2>/dev/null | grep -oP '"gateway"\s*:\s*"\K[0-9a-f:]+(?=")' | head -1)
if [ -n "$IPV6" ] && [ -n "$GW" ]; then
    ip -6 addr add ${IPV6}/64 dev wwan0 2>/dev/null || true
    ip -6 route add default via ${GW} dev wwan0 2>/dev/null || true
fi
EOF
sudo chmod +x /usr/local/bin/apply-ipv6.sh
sudo tee /etc/systemd/system/wwan-ipv6.service << 'EOF'
[Unit]
Description=Apply IPv6 to wwan0
After=ModemManager.service network-online.target
Wants=network-online.target

[Service]
Type=oneshot
ExecStart=/usr/local/bin/apply-ipv6.sh
RemainAfterExit=yes

[Install]
WantedBy=multi-user.target
EOF

sudo systemctl daemon-reload && sudo systemctl enable --now wwan-ipv6

Vérifiez que l’IPv6 survit à un redémarrage :

sudo reboot
# après reconnexion :
ip -6 addr show wwan0
# attendu : une adresse IPv6 globale (commençant par 2a01: ou similaire)

Configurer le serveur web

Comme le CGNAT et les pare-feu des opérateurs mobiles bloquent souvent les requêtes entrantes sur leurs réseaux 4G, nous devons utiliser un tunnel inverse. Plusieurs solutions existent : Cloudflare Tunnel, utiliser un VPS pour faire du transfert de trafic, etc.

Nous utiliserons Cloudflare Tunnel pour sa simplicité, son coût et parce qu’il ne nécessite pas de ressources supplémentaires. Dans ce tutoriel, nous supposons que vous avez déjà acquis et configuré votre domaine sur Cloudflare (voir les prérequis ci-dessus).

Déployer le blog Hugo sur le Raspberry Pi avec darkhttpd

Construire le site Hugo localement

Installez Hugo et créez un nouveau site avec un thème :

# Installer Hugo (macOS)
brew install hugo

# Créer un nouveau site
hugo new site myblog && cd myblog

# Ajouter un thème (ex. Ananke)
git init
git submodule add https://github.com/theNewDynamic/gohugo-theme-ananke.git themes/ananke
echo "theme = 'ananke'" >> hugo.toml

# Créer votre premier article
hugo new content posts/hello-world.md
# Éditez content/posts/hello-world.md, mettez draft: false

# Prévisualiser localement
hugo server

Quand vous êtes prêt à déployer, construisez le site de production :

hugo --environment production --minify

Cela génère le site statique dans public/ (tout le HTML, CSS, JS et les assets prêts à être servis).

Synchroniser vers le Pi

Remplacez <user> et <hostname> par les valeurs que vous avez définies dans l’imager.

ssh <user>@<hostname> 'sudo mkdir -p /var/www/myblog && sudo chown <user>:<user> /var/www/myblog'
rsync -avz --delete public/ <user>@<hostname>:/var/www/myblog/
Installer darkhttpd
ssh -t <user>@<hostname> 'sudo apt-get update -qq && sudo apt-get install -y -qq darkhttpd'
Créer le service systemd

Le tunnel sera configuré pour pointer vers http://localhost:8080, donc darkhttpd doit écouter sur le port 8080.

sudo tee /etc/systemd/system/myblog.service << 'EOF'
[Unit]
Description=My blog (darkhttpd)
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
ExecStart=/usr/bin/darkhttpd /var/www/myblog --port 8080
Restart=always
RestartSec=5

[Install]
WantedBy=multi-user.target
EOF
Activer et démarrer
sudo systemctl daemon-reload
sudo systemctl enable --now myblog
sudo systemctl status myblog

Sortie attendue : Active: active (running)

Vérifier localement
curl -s http://localhost:8080/ | head -5

Sortie attendue : les premières lignes du HTML de votre blog. Le blog est maintenant servi sur le port 8080, prêt à ce que le tunnel Cloudflare y redirige le trafic.

Configurer le tunnel Cloudflare

Attention : Orange bloque le port 7844 en IPv4 cloudflared se connecte au bord de Cloudflare sur le port 7844 (QUIC). Orange bloque cela en IPv4 mais l’autorise en IPv6. Nous forçons cloudflared à utiliser l’IPv6 avec --edge-ip-version 6 — c’est pourquoi la configuration de persistance IPv6 ci-dessus est nécessaire avant cette étape.

Créer le tunnel dans Cloudflare
  1. Allez dans Cloudflare Zero Trust https://one.dash.cloudflare.com → Networks → Tunnels
  2. Créez un tunnel (ex. solar)
  3. Ajoutez un nom d’hôte public : solar.<votre_domaine>.com → http://localhost:8080
  4. Copiez le jeton du tunnel
Installer cloudflared sur le Raspberry Pi
curl -fSL -o /tmp/cloudflared https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-arm
sudo mv /tmp/cloudflared /usr/local/bin/cloudflared
sudo chmod +x /usr/local/bin/cloudflared
Stocker le jeton du tunnel
sudo mkdir -p /etc/cloudflared
echo 'TUNNEL_TOKEN=<votre-jeton>' | sudo tee /etc/cloudflared/env
sudo chmod 600 /etc/cloudflared/env
Créer le service systemd
sudo tee /etc/systemd/system/cloudflared.service << 'EOF'
[Unit]
Description=Cloudflare Tunnel
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
ExecStart=/usr/local/bin/cloudflared tunnel --no-autoupdate --edge-ip-version 6 run --token ${TUNNEL_TOKEN}
EnvironmentFile=/etc/cloudflared/env
Restart=always
RestartSec=5

[Install]
WantedBy=multi-user.target
EOF

L’option clé est --edge-ip-version 6 : cela force cloudflared à se connecter à Cloudflare via IPv6, contournant le blocage du port 7844 par Orange en IPv4.

Activer et démarrer
sudo systemctl daemon-reload
sudo systemctl enable --now cloudflared
sudo systemctl status cloudflared

Sortie attendue : Active: active (running)

Vérifier
journalctl -u cloudflared --no-pager -n 10

Cherchez une ligne contenant Connection established ou Registered tunnel connection — cela confirme que le tunnel est actif. Vous verrez également le tunnel marqué comme Healthy dans le tableau de bord Cloudflare Zero Trust.

Tunnel Cloudflare affichant un état sain

Puis depuis n’importe quel appareil : curl https://solar.<votre_domaine>.com/

Et ensuite — Partie 2 : Passer totalement hors réseau

Le blog est en ligne, servi en 4G, tunnelisé via Cloudflare. Mais il est toujours branché au mur.

Dans la Partie 2, nous couperons le cordon entièrement :

  • Panneau solaire — câbler un panneau USB-C 10W pour alimenter le Pi pendant la journée
  • Chapeau batterie (Pi Sugar 3 Plus) — stocker l’énergie pour survivre aux nuits et aux jours nuageux
  • GPS — utiliser le module GPS intégré au hat SIM7600 pour géolocaliser l’appareil
  • Astuces d’énergie — désactiver le matériel inutilisé (HDMI, LEDs, USB) pour économiser chaque milliwatt

Divers

Liens utiles