No description
  • TypeScript 66%
  • Makefile 18.6%
  • Shell 15.4%
Find a file
Skander Mejdi 3fb7b10ec9 1.0.0
2026-01-13 13:27:00 +01:00
.github Create default issue template 2019-08-13 21:59:55 -06:00
src 1.0.0 2026-01-13 13:27:00 +01:00
.env.example init 2025-12-18 14:44:37 +01:00
.eslintignore samples/smarthome/nodejs: use gts 2020-11-11 09:06:24 +09:00
.eslintrc.json init 2025-12-18 14:44:37 +01:00
.firebaserc init 2025-12-18 14:44:37 +01:00
.gitignore init 2025-12-18 14:44:37 +01:00
.prettierrc.js samples/smarthome/nodejs: use gts 2020-11-11 09:06:24 +09:00
CONTRIBUTING.md Update CONTRIBUTING.md 2017-07-20 16:08:32 -04:00
firebase.json init 2025-12-18 14:44:37 +01:00
init-smarthome.sh init 2025-12-18 14:44:37 +01:00
LICENSE Initial checkin. 2017-05-14 15:56:59 -07:00
Makefile init 2025-12-18 14:44:37 +01:00
package-lock.json init 2025-12-18 14:44:37 +01:00
package.json init 2025-12-18 14:44:37 +01:00
QUICKSTART.md init 2025-12-18 14:44:37 +01:00
README.md init 2025-12-18 14:44:37 +01:00
test-fulfillment.sh init 2025-12-18 14:44:37 +01:00
tsconfig.json init 2025-12-18 14:44:37 +01:00

Toggle Virtuel Google Home pour Homelab TrueNAS

Ce projet permet de contrôler votre homelab TrueNAS via Google Home avec un switch virtuel.

Fonctionnalités

  • Allumage : Wake-on-LAN (WOL) pour démarrer le serveur
  • Extinction : Appel HTTP vers une API personnalisée pour arrêter le serveur
  • Vérification d'état : Ping HTTP pour connaître l'état réel du serveur
  • Sécurité : Variables d'environnement Firebase pour les informations sensibles

Prérequis

  • Node.js >= 18
  • Firebase CLI : npm install -g firebase-tools
  • Un projet Firebase créé
  • Proxy WOL configuré (si vous utilisez depuis le cloud)
  • Endpoint HTTP pour vérifier l'état du serveur (optionnel mais recommandé)

Installation

# Cloner le projet
git clone <votre-repo>
cd smart-home-nodejs

# Installer les dépendances
npm install

# Se connecter à Firebase
firebase login

# Sélectionner votre projet Firebase
firebase use homelab-f227c

Configuration

1. Variables d'environnement Firebase

Configurez les variables d'environnement pour votre serveur :

# Configuration WOL (obligatoire)
firebase functions:config:set \
  wol.mac="XX:XX:XX:XX:XX:XX" \
  wol.broadcast="192.168.1.255" \
  wol.port="9"

# Configuration ping/health check (recommandé)
firebase functions:config:set \
  ping.method="http" \
  ping.url="https://votre-domaine.com/health" \
  ping.timeout="2000"

# Configuration shutdown (optionnel pour l'instant)
firebase functions:config:set \
  shutdown.url="https://votre-domaine.com/api/shutdown" \
  shutdown.method="POST" \
  shutdown.token="votre-token-secret-32-caracteres"

Notes importantes :

  • wol.mac : Adresse MAC de votre serveur TrueNAS (format XX:XX:XX:XX:XX:XX ou XX-XX-XX-XX-XX-XX)
  • wol.broadcast : Adresse broadcast de votre réseau local (généralement X.X.X.255)
  • ping.url : URL pour vérifier si le serveur est allumé (voir options ci-dessous)
  • shutdown.token : Token d'authentification pour l'API de shutdown (à générer aléatoirement)

2. Configuration locale pour les tests

Pour tester localement, créez un fichier .runtimeconfig.json :

firebase functions:config:get > .runtimeconfig.json

Ou créez-le manuellement :

{
  "wol": {
    "mac": "XX:XX:XX:XX:XX:XX",
    "broadcast": "192.168.1.255",
    "port": "9"
  },
  "ping": {
    "method": "http",
    "url": "https://votre-domaine.com/health",
    "timeout": "2000"
  },
  "shutdown": {
    "url": "https://votre-domaine.com/api/shutdown",
    "method": "POST",
    "token": "votre-token-secret"
  }
}

Endpoint de vérification d'état (Health Check)

Pour que Google Home affiche l'état correct du serveur, vous avez plusieurs options :

Option 1 : Nginx/Reverse Proxy Health Check (Recommandé)

Configurez une route /health sur votre reverse proxy qui retourne 200 si TrueNAS est accessible :

location /health {
    access_log off;
    proxy_pass http://truenas-ip/api/v2.0/system/info;
    proxy_connect_timeout 2s;
    proxy_read_timeout 2s;
}

Option 2 : Endpoint personnalisé léger

Créez un endpoint HTTP simple qui répond {"status": "ok"}. Pas besoin d'authentification car il sert uniquement à vérifier si le serveur est allumé.

Option 3 : API TrueNAS

Utilisez l'API TrueNAS existante (ex: /api/v2.0/system/info). Attention : nécessite d'exposer une API key.

Test local

# Compiler le code
npm run build

# Démarrer l'émulateur Firebase
npm run serve

L'émulateur démarrera les fonctions sur http://localhost:5001/homelab-f227c/us-central1/

Testez les endpoints :

# Test fulfillment (nécessite un token d'auth valide)
curl http://localhost:5001/homelab-f227c/us-central1/fulfillment

# Test auth provider
curl http://localhost:5001/homelab-f227c/us-central1/authProvider/fakeauth

Déploiement

# Vérifier la compilation et le linting
npm run build
npm run lint

# Déployer sur Firebase
firebase deploy --only functions

# Noter les URLs générées (exemple) :
# ✔  functions[fulfillment(us-central1)]: https://us-central1-homelab-f227c.cloudfunctions.net/fulfillment
# ✔  functions[authProvider(us-central1)]: https://us-central1-homelab-f227c.cloudfunctions.net/authProvider

Configuration Google Smart Home

1. Créer le projet dans Google Actions Console

  1. Allez sur Actions Console
  2. Créer un nouveau projet
  3. Sélectionner "Smart Home"

2. Configurer Account Linking (OAuth)

Dans la section "Account Linking" :

  • Authorization URL : https://us-central1-homelab-f227c.cloudfunctions.net/authProvider/fakeauth
  • Token URL : https://us-central1-homelab-f227c.cloudfunctions.net/authProvider/faketoken
  • Client ID : n'importe quelle valeur (ex: "client-123")
  • Client Secret : n'importe quelle valeur (ex: "secret-456")
  • Scopes : laisser vide ou mettre "email"

Note : C'est un fake OAuth pour simplifier le développement. En production, utilisez un vrai système OAuth.

3. Configurer Fulfillment

Dans la section "Actions" :

  • Fulfillment URL : https://us-central1-homelab-f227c.cloudfunctions.net/fulfillment

4. Tester

  1. Ouvrez l'app Google Home sur votre téléphone
  2. Appuyez sur "+" puis "Configurer un appareil"
  3. Sélectionnez "Fonctionne avec Google"
  4. Cherchez "[test] Homelab Control" (ou le nom de votre projet)
  5. Liez votre compte (fake OAuth)
  6. Le switch "Serveur Maison" devrait apparaître

5. Utilisation

Commandes vocales :

  • "Ok Google, allume le serveur"
  • "Ok Google, éteins le serveur"
  • "Ok Google, le serveur est allumé ?"

Service Shutdown (à créer sur TrueNAS)

Pour permettre l'extinction sécurisée, créez un service sur votre TrueNAS qui écoute les requêtes HTTP :

Exemple d'implémentation (Python/Flask)

from flask import Flask, request, jsonify
import os
import subprocess
import time
from functools import wraps

app = Flask(__name__)

# Token d'authentification (le même que shutdown.token dans Firebase)
SHUTDOWN_TOKEN = os.getenv('SHUTDOWN_TOKEN', 'votre-token-secret-32-caracteres')

# Rate limiting simple
last_requests = []
MAX_REQUESTS = 3
TIME_WINDOW = 60  # secondes

def rate_limit(f):
    @wraps(f)
    def decorated_function(*args, **kwargs):
        global last_requests
        now = time.time()
        last_requests = [req for req in last_requests if now - req < TIME_WINDOW]

        if len(last_requests) >= MAX_REQUESTS:
            return jsonify({'error': 'rate_limit_exceeded'}), 429

        last_requests.append(now)
        return f(*args, **kwargs)
    return decorated_function

@app.route('/api/shutdown', methods=['POST'])
@rate_limit
def shutdown():
    # Vérifier l'authentification
    auth = request.headers.get('Authorization')
    if not auth or auth != f'Bearer {SHUTDOWN_TOKEN}':
        app.logger.warning(f'Unauthorized shutdown attempt from {request.remote_addr}')
        return jsonify({'error': 'unauthorized'}), 401

    # Logger la requête
    app.logger.info(f'Shutdown requested from {request.remote_addr}')

    try:
        # Arrêter le système
        subprocess.run(['shutdown', '-h', 'now'], check=True)
        return jsonify({'success': True, 'message': 'Shutdown initiated'})
    except Exception as e:
        app.logger.error(f'Shutdown failed: {e}')
        return jsonify({'error': 'shutdown_failed'}), 500

@app.route('/health', methods=['GET'])
def health():
    return jsonify({'status': 'ok', 'timestamp': time.time()})

if __name__ == '__main__':
    # Écouter uniquement sur localhost (exposer via reverse proxy)
    app.run(host='127.0.0.1', port=5000)

Sécurité

Important : Ce service doit être sécurisé car il permet d'arrêter votre serveur :

  1. Token fort : Générer un token aléatoire de 32+ caractères

    openssl rand -hex 32
    
  2. Rate limiting : Limiter à 3-5 requêtes par minute maximum

  3. Logging : Logger toutes les tentatives (succès et échecs)

  4. HTTPS obligatoire : Ne jamais exposer en HTTP

  5. Pas d'exposition directe : Passer par un reverse proxy (Nginx)

  6. Optionnel : Whitelist des IPs Google Cloud Functions

Configuration Nginx pour le service shutdown

location /api/shutdown {
    proxy_pass http://127.0.0.1:5000/api/shutdown;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;

    # Timeout court
    proxy_connect_timeout 5s;
    proxy_read_timeout 5s;

    # Optionnel : Whitelist IPs Google Cloud
    # allow 34.64.0.0/11;
    # deny all;
}

Dépannage

Le serveur ne s'allume pas (WOL)

  • Vérifiez que WOL est activé dans le BIOS
  • Vérifiez l'adresse MAC dans la config
  • Testez WOL manuellement depuis votre réseau local
  • Si vous utilisez un proxy WOL, vérifiez qu'il fonctionne

L'état du serveur est toujours offline

  • Vérifiez que ping.url est configuré et accessible
  • Testez l'URL manuellement : curl https://votre-domaine.com/health
  • Vérifiez les logs Firebase : firebase functions:log
  • Augmentez le timeout : firebase functions:config:set ping.timeout="5000"

Le serveur ne s'éteint pas

  • Le service shutdown n'est peut-être pas encore créé (c'est normal)
  • Vérifiez que shutdown.url et shutdown.token sont configurés
  • Vérifiez les logs du service shutdown sur TrueNAS
  • Testez manuellement :
    curl -X POST https://votre-domaine.com/api/shutdown \
      -H "Authorization: Bearer votre-token"
    

Erreurs de compilation

# Nettoyer et réinstaller
rm -rf node_modules build
npm install
npm run build

Voir les logs Firebase

# Logs en temps réel
firebase functions:log --only fulfillment

# Ou sur la console Firebase
# https://console.firebase.google.com/project/homelab-f227c/functions/logs

Prochaines étapes

  1. Configuration des variables d'environnement
  2. Test local avec l'émulateur
  3. Déploiement sur Firebase
  4. Configuration Google Actions Console
  5. Créer l'endpoint health check sur TrueNAS
  6. Créer le service shutdown sécurisé sur TrueNAS
  7. Tester l'allumage et l'extinction complète

Licence

Apache-2.0