#!/bin/bash # setup_wifi_ap.sh — Configure a Raspberry Pi as a WiFi AP + captive portal # for the eSIM provisioning system. # Run as root: sudo bash scripts/setup_wifi_ap.sh set -euo pipefail [ "$(id -u)" = "0" ] || { echo "ERROR: Must run as root (sudo)."; exit 1; } SSID="${ESIM_SSID:-Emergency-5G}" CHANNEL="${ESIM_CHANNEL:-6}" AP_IP="${ESIM_AP_IP:-192.168.4.1}" DHCP_RANGE="${ESIM_DHCP_RANGE:-192.168.4.10,192.168.4.250,24h}" INSTALL_DIR="${ESIM_INSTALL_DIR:-/opt/esim-provisioning}" IFACE="${ESIM_IFACE:-wlan0}" FLASK_PORT="${ESIM_FLASK_PORT:-5000}" REPO_DIR="$(cd "$(dirname "$0")/.." && pwd)" echo "=== eSIM Provisioning — WiFi AP Setup ===" echo " SSID: $SSID" echo " Channel: $CHANNEL" echo " AP IP: $AP_IP" echo " Interface: $IFACE" echo " Install dir: $INSTALL_DIR" echo "" # ---- 1. Install packages ---- echo "[1/8] Installing packages..." apt-get update -qq apt-get install -y hostapd dnsmasq nginx python3 python3-pip python3-venv # ---- 2. Static IP on wlan0 ---- echo "[2/8] Configuring static IP on $IFACE..." DHCPCD_CONF=/etc/dhcpcd.conf if ! grep -q "interface $IFACE" "$DHCPCD_CONF" 2>/dev/null; then cat >> "$DHCPCD_CONF" << EOF interface $IFACE static ip_address=$AP_IP/24 nohook wpa_supplicant EOF fi # ---- 3. hostapd ---- echo "[3/8] Configuring hostapd..." cat > /etc/hostapd/hostapd.conf << EOF interface=$IFACE driver=nl80211 ssid=$SSID utf8_ssid=1 hw_mode=g channel=$CHANNEL ieee80211n=1 wmm_enabled=1 auth_algs=1 ignore_broadcast_ssid=0 max_num_sta=50 EOF sed -i 's|#DAEMON_CONF=.*|DAEMON_CONF="/etc/hostapd/hostapd.conf"|' /etc/default/hostapd # ---- 4. dnsmasq ---- echo "[4/8] Configuring dnsmasq..." # Back up original if present [ -f /etc/dnsmasq.conf ] && mv /etc/dnsmasq.conf /etc/dnsmasq.conf.bak cat > /etc/dnsmasq.conf << EOF interface=$IFACE bind-interfaces dhcp-range=$DHCP_RANGE address=/#/$AP_IP no-resolv dhcp-leasefile=/var/lib/misc/dnsmasq.leases log-queries log-dhcp EOF # ---- 5. nginx ---- echo "[5/8] Configuring nginx..." cat > /etc/nginx/sites-available/esim-provisioning << EOF server { listen 80 default_server; server_name _; location = / { return 302 http://$AP_IP/activate; } location /activate { alias $INSTALL_DIR/portal/; index index.html; try_files \$uri \$uri/ /index.html; } location /css/ { alias $INSTALL_DIR/portal/css/; } location /js/ { alias $INSTALL_DIR/portal/js/; } location /api/ { proxy_pass http://127.0.0.1:$FLASK_PORT; proxy_set_header Host \$host; proxy_set_header X-Real-IP \$remote_addr; proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for; } location / { return 302 http://$AP_IP/activate; } } EOF ln -sf /etc/nginx/sites-available/esim-provisioning /etc/nginx/sites-enabled/ rm -f /etc/nginx/sites-enabled/default nginx -t # ---- 6. IP forwarding ---- echo "[6/8] Enabling IP forwarding..." sed -i 's|#net.ipv4.ip_forward=1|net.ipv4.ip_forward=1|' /etc/sysctl.conf sysctl -w net.ipv4.ip_forward=1 # ---- 7. iptables — captive portal redirect ---- echo "[7/8] Configuring iptables..." # Redirect all HTTP traffic from wlan0 clients to nginx (captive portal) iptables -t nat -A PREROUTING -i "$IFACE" -p tcp --dport 80 -j DNAT \ --to-destination "$AP_IP:80" 2>/dev/null || true # Persist iptables rules apt-get install -y iptables-persistent netfilter-persistent save # ---- 8. Deploy server and services ---- echo "[8/8] Deploying server..." mkdir -p "$INSTALL_DIR" /etc/esim-provisioning cp -r "$REPO_DIR/server" "$INSTALL_DIR/" cp -r "$REPO_DIR/portal" "$INSTALL_DIR/" cp -r "$REPO_DIR/scripts" "$INSTALL_DIR/" cp -r "$REPO_DIR/requirements.txt" "$INSTALL_DIR/" [ -f /etc/esim-provisioning/config.yaml ] || \ cp "$REPO_DIR/config.yaml.example" /etc/esim-provisioning/config.yaml # Create venv and install deps python3 -m venv "$INSTALL_DIR/venv" "$INSTALL_DIR/venv/bin/pip" install -q -r "$INSTALL_DIR/requirements.txt" # Create system user id esim &>/dev/null || useradd --system --no-create-home --shell /usr/sbin/nologin esim mkdir -p "$INSTALL_DIR/data" chown -R esim:esim "$INSTALL_DIR/data" # Install systemd services cp "$REPO_DIR/systemd/esim-provisioning.service" /etc/systemd/system/ cp "$REPO_DIR/systemd/captive-portal.service" /etc/systemd/system/ systemctl daemon-reload # Initialise DB CONFIG_PATH=/etc/esim-provisioning/config.yaml \ "$INSTALL_DIR/venv/bin/python" "$INSTALL_DIR/scripts/init_db.py" # Enable everything systemctl unmask hostapd systemctl enable hostapd dnsmasq nginx esim-provisioning captive-portal systemctl restart hostapd dnsmasq nginx esim-provisioning echo "" echo "=== Setup Complete ===" echo "" echo "Edit /etc/esim-provisioning/config.yaml to set your MCC/MNC/OP key." echo "Then: systemctl restart esim-provisioning" echo "" echo "Clients can connect to WiFi '$SSID' and will be redirected to the" echo "eSIM activation portal at http://$AP_IP/activate"