APmanageur Wi-Fi V1.0 : conteneur Debian + Apache

This commit is contained in:
yoann committed 2026-10-05 01:18:55 +02:00
1 parent c705504e5d
commit 2d3f8d8b3c
5 files changed
+63 -44

No files matched your search

+5 -2
View File
@@ -20,16 +20,19 @@ COPY ap.py /app/ap.py
ARG HTML_FILE=index.html
COPY ${HTML_FILE} /app/index.html
COPY ${HTML_FILE} /var/www/html/index.html
# L'API n'est plus joignable que via Apache : le HTML appelle /api sur le même port (1001)
RUN sed -i 's#const API_URL=[^;]*;#const API_URL="";#' /app/index.html /var/www/html/index.html
COPY apache-ap.conf /etc/apache2/sites-available/000-default.conf
COPY entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh && rm -f /var/www/html/index.html.orig \
&& sed -i 's/^Listen 80$/Listen 1001/; s/^\s*Listen 443$/ Listen 1443/' /etc/apache2/ports.conf
&& sed -i 's/^Listen 80$/Listen ${AP_WEB_PORT}/; s/^\s*Listen 443$/ Listen 1443/' /etc/apache2/ports.conf
ENV AP_DB_FILE=/data/ap-dashboard.sqlite3 \
AP_CONNECTION_FILE=/data/connection \
AP_UPTIME_FILE=/data/uptime
VOLUME ["/data", "/etc/NetworkManager/system-connections", "/var/lib/NetworkManager"]
EXPOSE 1001 8080
ENV AP_WEB_PORT=1001
EXPOSE 1001
ENTRYPOINT ["/entrypoint.sh"]
+17 -3
View File
@@ -1,9 +1,9 @@
#!/usr/bin/env python3
import base64, hashlib, hmac, json, os, re, secrets, socket, sqlite3, subprocess, threading, time, urllib.parse
import base64, hashlib, hmac, json, os, re, secrets, socket, sqlite3, subprocess, threading, time, urllib.parse, socketserver, shutil
from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer
INTERFACE = os.environ.get('AP_INTERFACE', 'wls16b1')
HOST, PORT = '0.0.0.0', 8080
SOCKET_PATH = os.environ.get('AP_SOCKET', '/run/ap-api.sock')
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
DB_FILE = os.environ.get('AP_DB_FILE', os.path.join(BASE_DIR, 'ap-dashboard.sqlite3'))
CONNECTION_FILE = os.environ.get('AP_CONNECTION_FILE', os.path.join(BASE_DIR, 'ap-dashboard-connection'))
@@ -501,5 +501,19 @@ def monitor():
except Exception: pass
time.sleep(2)
class UnixServer(ThreadingHTTPServer):
address_family = socket.AF_UNIX
daemon_threads = True
def server_bind(self):
socketserver.TCPServer.server_bind(self)
self.server_name, self.server_port = 'localhost', 0
if __name__ == '__main__':
db(); threading.Thread(target=monitor,daemon=True).start(); print(f'API AP sur http://0.0.0.0:{PORT}'); ThreadingHTTPServer((HOST,PORT),Handler).serve_forever()
db(); threading.Thread(target=monitor,daemon=True).start()
try: os.remove(SOCKET_PATH)
except OSError: pass
server = UnixServer(SOCKET_PATH, Handler)
os.chmod(SOCKET_PATH, 0o660)
try: shutil.chown(SOCKET_PATH, user='root', group='www-data')
except (LookupError, OSError): os.chmod(SOCKET_PATH, 0o666)
print(f'API AP sur le socket {SOCKET_PATH} (aucun port TCP)'); server.serve_forever()
+3 -3
View File
@@ -1,6 +1,6 @@
ServerName localhost
<VirtualHost *:1001>
<VirtualHost *:${AP_WEB_PORT}>
DocumentRoot /var/www/html
DirectoryIndex index.html
@@ -12,8 +12,8 @@ ServerName localhost
# L'API Python lit l'IP réelle du client dans X-Real-IP
RequestHeader set X-Real-IP "expr=%{REMOTE_ADDR}"
ProxyPreserveHost On
ProxyPass /api http://127.0.0.1:8080/api
ProxyPassReverse /api http://127.0.0.1:8080/api
ProxyPass /api unix:/run/ap-api.sock|http://localhost/api
ProxyPassReverse /api http://localhost/api
ErrorLog /dev/stderr
CustomLog /dev/stdout combined
+12 -25
View File
@@ -1,31 +1,18 @@
# 1. Trouver l'interface de la carte Wi-Fi : iw dev
# 2. Lancer : AP_INTERFACE=wlan0 docker compose up -d --build
# 3. Injecter la carte Wi-Fi dans le conteneur (à refaire à chaque redémarrage du conteneur) :
# sudo ./attach-wifi.sh wlan0
# 4. Ouvrir : http://IP-DE-LA-MACHINE:1001/
#
# Si votre fichier HTML ne s'appelle pas index.html, ajoutez sous "build:"
# args:
# HTML_FILE: ap_dashboard.html
services:
ap-wifi:
build: .
container_name: ap-wifi
AP-Manageur:
image: gitea.yoann-nas.fr/yoannmultigaming/apmanageur.git:latest
container_name: ap-manageur
restart: unless-stopped
ports:
- "1001:1001" # interface web (Apache)
- "8080:8080" # API (le HTML l'appelle sur ce port)
network_mode: host # accès direct à la carte Wi-Fi de l'hôte (Apache sur le port 1001)
privileged: true # NetworkManager interne : rfkill, NAT, sysctl
environment:
AP_INTERFACE: ${AP_INTERFACE:-}
# Laisser vide = détection automatique de la carte Wi-Fi.
# Écrire un nom (ex. "wlan0") = cette interface sera utilisée.
AP_INTERFACE: ""
# Port d'écoute de l'interface web.
AP_WEB_PORT: "1001"
volumes:
- ap-data:/data
- nm-connections:/etc/NetworkManager/system-connections
- nm-state:/var/lib/NetworkManager
- /path/to/APmanageur/data:/data
- /path/to/APmanageur/nm-connections:/etc/NetworkManager/system-connections
- /path/to/APmanageur/nm-state:/var/lib/NetworkManager
- /run/udev:/run/udev:ro # NetworkManager reconnaît ainsi la carte USB
volumes:
ap-data:
nm-connections:
nm-state:
+26 -11
View File
@@ -3,18 +3,33 @@ set -euo pipefail
log() { echo "[ap-wifi] $*"; }
# 1. Interface Wi-Fi (Netgear) --------------------------------------------------
IFACE="${AP_INTERFACE:-}"
mapfile -t FOUND < <(iw dev 2>/dev/null | awk '$1=="Interface"{print $2}')
if [[ -z "$IFACE" ]]; then
if [[ ${#FOUND[@]} -eq 1 ]]; then
IFACE="${FOUND[0]}"
else
log "ERREUR : précisez AP_INTERFACE. Interfaces Wi-Fi détectées : ${FOUND[*]:-aucune}"
# Port d'écoute d'Apache (défini dans docker-compose.yml)
AP_WEB_PORT="${AP_WEB_PORT:-1001}"
if ! [[ "$AP_WEB_PORT" =~ ^[0-9]+$ ]] || (( AP_WEB_PORT < 1 || AP_WEB_PORT > 65535 )); then
log "ERREUR : AP_WEB_PORT invalide ('$AP_WEB_PORT'), attendu un nombre entre 1 et 65535"
exit 1
fi
export AP_WEB_PORT
# 1. Interface Wi-Fi --------------------------------------------------
IFACE="${AP_INTERFACE:-}"
log "Recherche de la carte Wi-Fi…"
FOUND=()
for _ in $(seq 1 180); do
mapfile -t FOUND < <(iw dev 2>/dev/null | awk '$1=="Interface"{print $2}')
if [[ -n "$IFACE" ]]; then
printf '%s\n' "${FOUND[@]:-}" | grep -qx "$IFACE" && break
elif [[ ${#FOUND[@]} -ge 1 ]]; then
IFACE="${FOUND[0]}"
for d in "${FOUND[@]}"; do
p="$(iw dev "$d" info 2>/dev/null | awk '/wiphy/{print "phy"$2}')"
if [[ -n "$p" ]] && iw "$p" info 2>/dev/null | grep -qE '^\s+\* AP$'; then IFACE="$d"; break; fi
done
break
fi
iw dev "$IFACE" info >/dev/null 2>&1 || { log "ERREUR : interface '$IFACE' introuvable (détectées : ${FOUND[*]:-aucune})"; exit 1; }
sleep 1
done
[[ -n "$IFACE" ]] && iw dev "$IFACE" info >/dev/null 2>&1 || { log "ERREUR : interface '${IFACE:-?}' absente après 3 min (détectées : ${FOUND[*]:-aucune})"; exit 1; }
export AP_INTERFACE="$IFACE"
log "Interface utilisée : $IFACE"
@@ -48,7 +63,7 @@ nmcli radio wifi on 2>/dev/null || true
nmcli device set "$IFACE" managed yes 2>/dev/null || true
log "NetworkManager prêt"
# 3. API Python (port 8080) + Apache (port 80) ------------------------------------
# 3. API Python (socket Unix, aucun port) + Apache (port 1001) ------------------------------------
python3 /app/ap.py &
API_PID=$!
apache2ctl -D FOREGROUND &
@@ -56,7 +71,7 @@ WEB_PID=$!
trap 'log "Arrêt"; kill "$WEB_PID" "$API_PID" "$NM_PID" 2>/dev/null || true; exit 0' TERM INT
log "Interface web : http://<ip-de-la-machine>:1001/ (API directe : port 8080)"
log "Interface web : http://<ip-de-la-machine>:${AP_WEB_PORT}/ (API interne par socket, aucun port)"
wait -n
log "Un service s'est arrêté, fermeture du conteneur"
kill "$WEB_PID" "$API_PID" "$NM_PID" 2>/dev/null || true