feat(vpn): VPN on-demand Tailscale + agent studioE5 standalone
- Agent studioE5 standalone en Go (console + systray) - VPN on-demand via tailscaled + tailscale up (authkey Headscale) - Resolver/serveur dans le tailnet studioe5 - Caddy on-demand TLS pour les instances - Nouveaux endpoints serveur /api/internal/send-to-node - Suppression des anciens binaires edubox-agent - Suivi dans SUIVI_VPN_ONDEMAND.md
This commit is contained in:
@@ -0,0 +1,148 @@
|
||||
# Suivi – VPN on-demand studioE5 (client A)
|
||||
|
||||
## ✅ Ce qui fonctionne
|
||||
|
||||
1. **Agent standalone (mode console / systray)**
|
||||
- Exécutable : `agent/studioE5-agent`
|
||||
- Config lu depuis `<data-dir>/studioE5-config.json`
|
||||
- Mode console : `-no-tray`
|
||||
|
||||
2. **VPN on-demand dans l'agent**
|
||||
- L’agent ne démarre plus Tailscale au boot.
|
||||
- Le VPN se lance automatiquement à la création/démarrage d’une instance, ou sur commande serveur.
|
||||
- Implémentation basée sur les binaires `tailscaled` + `tailscale up` (pas `tsnet`, car `tsnet` ne loguait pas automatiquement avec une authkey sur un state vierge).
|
||||
|
||||
3. **Commandes serveur → agent**
|
||||
- Endpoint de test : `POST /api/internal/send-to-node`
|
||||
- Actions supportées : `start_vpn`, `stop_vpn`, `start`, `stop`, `reset`, `delete`.
|
||||
|
||||
4. **Resolver/serveur dans le tailnet studioe5**
|
||||
- Service `resolver-vpn` (conteneur Tailscale) partage le netns du `resolver`.
|
||||
- Le resolver peut joindre les IPs Tailscale des nodes (`ping 100.64.0.x` OK).
|
||||
|
||||
5. **Instance WordPress démarrée avec succès**
|
||||
- Le resolver a renvoyé une 302 WordPress via `http://resolver:2020/`.
|
||||
|
||||
## ✅ Blocage levé
|
||||
|
||||
**Rate limit Let’s Encrypt pour `edudeploy.com` est levé.**
|
||||
Le 2026-06-23 vers 09:35 UTC, Caddy a pu obtenir un certificat Let’s Encrypt pour `test-wp-001.studioe5.edudeploy.com` :
|
||||
```
|
||||
tls.obtain: certificate obtained successfully identifier=test-wp-001.studioe5.edudeploy.com issuer=acme-v02.api.letsencrypt.org-directory
|
||||
```
|
||||
|
||||
Le flux complet HTTPS public est désormais validé :
|
||||
```bash
|
||||
curl -sS -I -L https://test-wp-001.studioe5.edudeploy.com/
|
||||
# => HTTP/2 302 -> HTTP/2 200 (WordPress install.php)
|
||||
```
|
||||
|
||||
Le DNS wildcard `*.studioe5.edudeploy.com` est en place. Caddy utilise toujours `tls { on_demand }` et émet un certificat par sous-domaine d’instance.
|
||||
|
||||
## 🎯 Validation du flux HTTPS public
|
||||
|
||||
Le 2026-06-23 09:39 UTC, le flux complet a été validé :
|
||||
|
||||
```text
|
||||
Client (HTTPS) → Caddy (:443) → resolver (:2020) → Tailnet (100.64.0.8) → agent → WordPress (:8001)
|
||||
```
|
||||
|
||||
Résultat :
|
||||
```bash
|
||||
$ curl -sS -I -L https://test-wp-001.studioe5.edudeploy.com/
|
||||
HTTP/2 302
|
||||
location: https://test-wp-001.studioe5.edudeploy.com/wp-admin/install.php
|
||||
...
|
||||
HTTP/2 200
|
||||
```
|
||||
|
||||
- Certificat Let’s Encrypt obtenu automatiquement par Caddy (`tls { on_demand }`).
|
||||
- Le resolver réécrit les en-têtes `Location` et le contenu HTML pour passer de `http://` à `https://`.
|
||||
|
||||
## 📁 Fichiers modifiés (non exhaustif)
|
||||
|
||||
- `agent/tailscale.go` – lancement `tailscaled` + `tailscale up`, gestion start/stop/status.
|
||||
- `agent/websocket.go` – handlers `start_vpn` / `stop_vpn`, `ensureTailscale()`.
|
||||
- `agent/docker.go` – remplacement des placeholders `{PORT}` et `{INSTANCE_ID}` dans les compose.
|
||||
- `docker-compose.yml` – ajout du sidecar `resolver-vpn`, suppression des `cap_add`/`ip route` obsolètes sur `server`/`resolver`.
|
||||
- `Caddyfile` – configuration on-demand TLS pour les instances.
|
||||
- `.env` – clé pré-auth Headscale mise à jour (clé réutilisable).
|
||||
|
||||
## 🧪 Tests / environnement de test actuel
|
||||
|
||||
Agent de test lancé en arrière-plan :
|
||||
- data-dir : `/tmp/studioe5-test-clienta`
|
||||
- node-id : `vps-8fc665eb`
|
||||
- tailnet IP actuelle : `100.64.0.8`
|
||||
- PID : `3151830` (lancé le 2026-06-23 09:36 UTC)
|
||||
|
||||
Instance de test créée :
|
||||
- ID : `test-wp-001`
|
||||
- Node : `vps-8fc665eb`
|
||||
- Port : `8001`
|
||||
- Template : `wordpress-wordpress-latest`
|
||||
- État : WordPress répond sur `http://127.0.0.1:8001` **et en HTTPS public sur `https://test-wp-001.studioe5.edudeploy.com/`**.
|
||||
|
||||
## 🛠️ Commandes utiles pour reprendre
|
||||
|
||||
### Voir l’agent de test
|
||||
```bash
|
||||
pgrep -a studioe5-agent
|
||||
```
|
||||
|
||||
### Relancer l’agent de test (si besoin)
|
||||
```bash
|
||||
mkdir -p /tmp/studioe5-test-clienta
|
||||
cat > /tmp/studioe5-test-clienta/studioE5-config.json <<EOF
|
||||
{
|
||||
"server": "wss://studioe5.edudeploy.com/api/websocket",
|
||||
"headscale_url": "https://headscale.studioe5.edudeploy.com",
|
||||
"headscale_auth_key": "$(grep HEADSCALE_AUTH_KEY /opt/studioe5-client-a/.env | cut -d= -f2)",
|
||||
"node_id": "vps-8fc665eb",
|
||||
"data_dir": "/tmp/studioe5-test-clienta"
|
||||
}
|
||||
EOF
|
||||
cd /opt/studioe5-client-a/agent
|
||||
./studioE5-agent -no-tray -data-dir /tmp/studioe5-test-clienta
|
||||
```
|
||||
|
||||
### Démarrer le VPN manuellement
|
||||
```bash
|
||||
curl -sS -X POST https://studioe5.edudeploy.com/api/internal/send-to-node \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"nodeId":"vps-8fc665eb","message":{"action":"start_vpn"}}'
|
||||
```
|
||||
|
||||
### Voir les nodes Headscale
|
||||
```bash
|
||||
cd /opt/studioe5-client-a
|
||||
docker compose exec -T headscale headscale nodes list studioe5
|
||||
```
|
||||
|
||||
### Tester le resolver (depuis Caddy)
|
||||
```bash
|
||||
cd /opt/studioe5-client-a
|
||||
docker exec studioe5-caddy curl -sS -I -H "Host: test-wp-001.studioe5.edudeploy.com" http://resolver:2020/
|
||||
```
|
||||
|
||||
### Tester en HTTPS public (dès que la limite sera levée)
|
||||
```bash
|
||||
curl -sS -I -L https://test-wp-001.studioe5.edudeploy.com/
|
||||
```
|
||||
|
||||
## 📋 Prochaines étapes à faire
|
||||
|
||||
- [x] ~~Attendre la fin du rate limit Let’s Encrypt~~ (levé le 2026-06-23).
|
||||
- [x] ~~Relancer un test HTTPS sur `https://test-wp-001.studioe5.edudeploy.com/`~~ → **OK** (HTTP/2 200).
|
||||
- [ ] **Nettoyer l’instance test et l’agent test**, puis **committer les modifications** (il reste beaucoup de fichiers modifiés/non suivis ; voir `git status`).
|
||||
- [ ] **Si le wildcard DNS est stable**, envisager d’obtenir un certificat wildcard unique pour `*.studioe5.edudeploy.com` (évite d’émettre un certificat par instance et donc de retomber dans les rate limits). À étudier côté Caddy (`tls { on_demand }` vs certificat wildcard géré manuellement).
|
||||
- [ ] **Tester le flux complet depuis l’interface web** (activation d’un élève, création d’instance via l’UI).
|
||||
- [ ] **Packager les binaires Tailscale pour Windows** dans `agent/tailscale-bin/windows/`.
|
||||
- [ ] **Nettoyer les anciens nodes/volumes Headscale** créés pendant les tests.
|
||||
- [ ] **Documenter la procédure de mise en production** pour le client A (config agent, clés Headscale, ports, etc.).
|
||||
|
||||
## 🔧 Notes techniques
|
||||
|
||||
- Le conteneur `resolver-vpn` utilise `network_mode: service:resolver` pour partager le netns avec le resolver.
|
||||
- L’agent utilise `tailscaled --tun=userspace-networking` ; le resolver-vpn utilise un vrai TUN (`tailscale0`).
|
||||
- Le `Caddyfile` actuel utilise `tls { on_demand }` pour les instances. En cas de nouvelle rate limit, on peut temporairement remettre `tls internal` dans le bloc `:443` pour valider le flux sans certificat public.
|
||||
Reference in New Issue
Block a user