
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
| Composant | Coû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 hat | 75€ |
| Carte Micro-SD (min. 8Go) + adaptateur MicroSD vers SD (pour flasher depuis un ordinateur portable) | 5€ |
| Panneau solaire 10W 5V USB-C | 25€ |
| Pi Sugar 3 Plus chapeau batterie 1200 mAh — configuration couverte dans la Partie 2 | 34€ |
| Nano SIM avec abonnement mobile | À partir de 1€/mois |
| Total | 150€ + 1€/mois |

Notes : De nombreuses alternatives à ce hat 4G sont possibles pour des budgets plus serrés, idem pour la batterie.
Logiciel
| Composant | Coût |
|---|---|
| Configuration du domaine sur Cloudflare | ~ |
| Tunnel Cloudflare | Gratuit |
Étapes
Montage du matériel
- Éteignez le Raspberry
- Branchez le hat sur le Raspberry Pi 0, ça devrait ressembler à ceci :

- 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 avecssh <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.

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 :
| Port | Fonction |
|---|---|
| /dev/ttyUSB0 | Diagnostique |
| /dev/ttyUSB1 | GPS/NMEA |
| /dev/ttyUSB2 | Commandes AT ← utilisez celui-ci |
| /dev/ttyUSB3 | PPP / données |
| /dev/ttyUSB4 | Audio/autre |
Vous pouvez tester la communication via le port de commandes AT :
sudo minicom -D /dev/ttyUSB2 -b 115200
Puis :
- Appuyez sur
Ctrl+ApuisEpour activer l’écho- Tapez
AT+ Entrée - → devrait retourner
OK
- Tapez
- Puis vérifiez la SIM :
- Tapez
AT+CPIN? - → devrait retourner
+CPIN: READY
- Tapez
- Puis vérifiez le réseau
- Tapez
AT+COPS? - → devrait afficher les détails Orange (si vous utilisez la multi-SIM Orange)
- Tapez
Autres commandes AT de test pour les curieux :
| Commande AT | Description | Retour |
|---|---|---|
| AT | Commande de test AT | OK |
| ATE | ATE1 : Echo activé, ATE0 : Echo désactivé | OK |
| AT+CGMI | Identification du fabricant | OK |
| AT+CGMM | Identification du modèle | OK |
| AT+CGSN | Identification du numéro de série | OK |
| AT+CSUB | Version du produit | OK |
| AT+CGMR | Version du firmware | OK |
| AT+IPREX | Configuration du débit du modèle | +IPREX:OK |
| AT+CRESET | Réinitialisation du modèle | OK |
| AT+CSQ | Qualité du signal | OK |
| 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+CNMP | Sélection du mode réseau | OK |
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(pasorange.fr). L’APNorange.frest utilisé pour le partage de connexion et désactive l’IPv6 — nous avons besoin deorangepour 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
cloudflaredse connecte au bord de Cloudflare sur le port 7844 (QUIC). Orange bloque cela en IPv4 mais l’autorise en IPv6. Nous forçonscloudflaredà 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
- Allez dans Cloudflare Zero Trust https://one.dash.cloudflare.com → Networks → Tunnels
- Créez un tunnel (ex.
solar) - Ajoutez un nom d’hôte public :
solar.<votre_domaine>.com→http://localhost:8080 - 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.

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
- Comment configurer un Raspberry Pi Zero W comme routeur 3G/4G
- Manuel du Waveshare SIM7600G-H 4G Hat (B)
- Tutoriel - Hat 4G et GPS pour Raspberry Pi - Waveshare SIM7600X
- Tutoriel vidéo - Hat 4G et GPS pour Raspberry Pi - Waveshare SIM7600X
- Le journal Low Tech alimenté par solaire
- Comment construire un site web low tech : Logiciel & Matériel
- Relayer le trafic vers un auto-hébergement avec CGNAT