APmanageur Wi-Fi V1.0 : conteneur Debian + Apache
This commit is contained in:
1 parent
c705504e5d
commit
2d3f8d8b3c
5 files changed
+63
-44
No files matched your search
+5
-2
@@ -20,16 +20,19 @@ COPY ap.py /app/ap.py
|
|||||||
ARG HTML_FILE=index.html
|
ARG HTML_FILE=index.html
|
||||||
COPY ${HTML_FILE} /app/index.html
|
COPY ${HTML_FILE} /app/index.html
|
||||||
COPY ${HTML_FILE} /var/www/html/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 apache-ap.conf /etc/apache2/sites-available/000-default.conf
|
||||||
COPY entrypoint.sh /entrypoint.sh
|
COPY entrypoint.sh /entrypoint.sh
|
||||||
RUN chmod +x /entrypoint.sh && rm -f /var/www/html/index.html.orig \
|
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 \
|
ENV AP_DB_FILE=/data/ap-dashboard.sqlite3 \
|
||||||
AP_CONNECTION_FILE=/data/connection \
|
AP_CONNECTION_FILE=/data/connection \
|
||||||
AP_UPTIME_FILE=/data/uptime
|
AP_UPTIME_FILE=/data/uptime
|
||||||
|
|
||||||
VOLUME ["/data", "/etc/NetworkManager/system-connections", "/var/lib/NetworkManager"]
|
VOLUME ["/data", "/etc/NetworkManager/system-connections", "/var/lib/NetworkManager"]
|
||||||
EXPOSE 1001 8080
|
ENV AP_WEB_PORT=1001
|
||||||
|
EXPOSE 1001
|
||||||
|
|
||||||
ENTRYPOINT ["/entrypoint.sh"]
|
ENTRYPOINT ["/entrypoint.sh"]
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
#!/usr/bin/env python3
|
#!/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
|
from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer
|
||||||
|
|
||||||
INTERFACE = os.environ.get('AP_INTERFACE', 'wls16b1')
|
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__))
|
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'))
|
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'))
|
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
|
except Exception: pass
|
||||||
time.sleep(2)
|
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__':
|
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
@@ -1,6 +1,6 @@
|
|||||||
ServerName localhost
|
ServerName localhost
|
||||||
|
|
||||||
<VirtualHost *:1001>
|
<VirtualHost *:${AP_WEB_PORT}>
|
||||||
DocumentRoot /var/www/html
|
DocumentRoot /var/www/html
|
||||||
DirectoryIndex index.html
|
DirectoryIndex index.html
|
||||||
|
|
||||||
@@ -12,8 +12,8 @@ ServerName localhost
|
|||||||
# L'API Python lit l'IP réelle du client dans X-Real-IP
|
# L'API Python lit l'IP réelle du client dans X-Real-IP
|
||||||
RequestHeader set X-Real-IP "expr=%{REMOTE_ADDR}"
|
RequestHeader set X-Real-IP "expr=%{REMOTE_ADDR}"
|
||||||
ProxyPreserveHost On
|
ProxyPreserveHost On
|
||||||
ProxyPass /api http://127.0.0.1:8080/api
|
ProxyPass /api unix:/run/ap-api.sock|http://localhost/api
|
||||||
ProxyPassReverse /api http://127.0.0.1:8080/api
|
ProxyPassReverse /api http://localhost/api
|
||||||
|
|
||||||
ErrorLog /dev/stderr
|
ErrorLog /dev/stderr
|
||||||
CustomLog /dev/stdout combined
|
CustomLog /dev/stdout combined
|
||||||
|
|||||||
+12
-25
@@ -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:
|
services:
|
||||||
ap-wifi:
|
AP-Manageur:
|
||||||
build: .
|
image: gitea.yoann-nas.fr/yoannmultigaming/apmanageur.git:latest
|
||||||
container_name: ap-wifi
|
container_name: ap-manageur
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
ports:
|
network_mode: host # accès direct à la carte Wi-Fi de l'hôte (Apache sur le port 1001)
|
||||||
- "1001:1001" # interface web (Apache)
|
|
||||||
- "8080:8080" # API (le HTML l'appelle sur ce port)
|
|
||||||
privileged: true # NetworkManager interne : rfkill, NAT, sysctl
|
privileged: true # NetworkManager interne : rfkill, NAT, sysctl
|
||||||
environment:
|
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:
|
volumes:
|
||||||
- ap-data:/data
|
- /path/to/APmanageur/data:/data
|
||||||
- nm-connections:/etc/NetworkManager/system-connections
|
- /path/to/APmanageur/nm-connections:/etc/NetworkManager/system-connections
|
||||||
- nm-state:/var/lib/NetworkManager
|
- /path/to/APmanageur/nm-state:/var/lib/NetworkManager
|
||||||
- /run/udev:/run/udev:ro # NetworkManager reconnaît ainsi la carte USB
|
- /run/udev:/run/udev:ro # NetworkManager reconnaît ainsi la carte USB
|
||||||
|
|
||||||
volumes:
|
|
||||||
ap-data:
|
|
||||||
nm-connections:
|
|
||||||
nm-state:
|
|
||||||
+26
-11
@@ -3,18 +3,33 @@ set -euo pipefail
|
|||||||
|
|
||||||
log() { echo "[ap-wifi] $*"; }
|
log() { echo "[ap-wifi] $*"; }
|
||||||
|
|
||||||
# 1. Interface Wi-Fi (Netgear) --------------------------------------------------
|
# Port d'écoute d'Apache (défini dans docker-compose.yml)
|
||||||
IFACE="${AP_INTERFACE:-}"
|
AP_WEB_PORT="${AP_WEB_PORT:-1001}"
|
||||||
mapfile -t FOUND < <(iw dev 2>/dev/null | awk '$1=="Interface"{print $2}')
|
if ! [[ "$AP_WEB_PORT" =~ ^[0-9]+$ ]] || (( AP_WEB_PORT < 1 || AP_WEB_PORT > 65535 )); then
|
||||||
if [[ -z "$IFACE" ]]; then
|
log "ERREUR : AP_WEB_PORT invalide ('$AP_WEB_PORT'), attendu un nombre entre 1 et 65535"
|
||||||
if [[ ${#FOUND[@]} -eq 1 ]]; then
|
|
||||||
IFACE="${FOUND[0]}"
|
|
||||||
else
|
|
||||||
log "ERREUR : précisez AP_INTERFACE. Interfaces Wi-Fi détectées : ${FOUND[*]:-aucune}"
|
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
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
|
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"
|
export AP_INTERFACE="$IFACE"
|
||||||
log "Interface utilisée : $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
|
nmcli device set "$IFACE" managed yes 2>/dev/null || true
|
||||||
log "NetworkManager prêt"
|
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 &
|
python3 /app/ap.py &
|
||||||
API_PID=$!
|
API_PID=$!
|
||||||
apache2ctl -D FOREGROUND &
|
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
|
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
|
wait -n
|
||||||
log "Un service s'est arrêté, fermeture du conteneur"
|
log "Un service s'est arrêté, fermeture du conteneur"
|
||||||
kill "$WEB_PID" "$API_PID" "$NM_PID" 2>/dev/null || true
|
kill "$WEB_PID" "$API_PID" "$NM_PID" 2>/dev/null || true
|
||||||
|
|||||||
Reference in new issue
Block a user