# Préparation de l'image RPI videopi ## Raspi OS et SSH 1. Télécharger l'image disque version "Legacy" lite : https://downloads.raspberrypi.org/raspios_oldstable_lite_armhf/images/raspios_oldstable_lite_armhf-2022-09-26/2022-09-22-raspios-buster-armhf-lite.img.xz 2. Flasher l'image sur une carte SD : `xzcat 2022-09-22-raspios-buster-armhf-lite.img.xz | sudo dd of=/dev/mmcblkp0 bs=128K oflag=dsync status=progress && sync` 3. Monter la carte SD et ajouter un fichier nommé `ssh` sur la partition `/boot` pour activer le serveur SSH; `touch boot/ssh` (https://linuxhint.com/rasperberry_pi_wifi_wpa_supplicant/) 5. Toujours sur la partition `/boot`, créer un fichier nommé `wpa_supplicant.conf` pour configurer la connexion wifi. Le contenu de celui-ci : ``` ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev update_config=1 country=FR network={ ssid="BLAH" # Nom du réseau auquel on se connecte #scan_ssid=1 # Décommenter si le réseau est caché psk="BLAH" # Mot de passe wifi # Pour accélérer la découverte et la connexion du point d'accès wifi, # on peut spécifier les fréquences à balayer en fonction du canal utilisé par ce dernier. # https://w1.fi/cgit/hostap/tree/wpa_supplicant/wpa_supplicant.conf#n910 # Wifi 2.4 Ghz : https://fr.wikipedia.org/wiki/Liste_des_canaux_Wi-Fi#Bande_2,4_GHz # scan_freq=2412 2437 2462 # See nmcli 802-11-wireless.channel # https://developer-old.gnome.org/NetworkManager/stable/settings-802-11-wireless.html # Wifi 5ghz : https://fr.wikipedia.org/wiki/Liste_des_canaux_Wi-Fi#Liste_des_canaux_dans_la_bande_des_5_GHz # scan_freq= 5805 } ``` 4. Insérer la carte dans le RPI et démarrer le système. 5. Se connecter via SSH. 6. Adduser pil ## Modification de config.txt Ajouter les lignes suivantes au fichier `/boot/config.txt` : ``` # Forcer HDMI Full HD hdmi_group=1 hdmi_mode=16 # fullHD@60 [all] # Désactivation du bluetooth dtoverlay=pi3-disable-bt max_framebuffers=2 # Mémoire vidéo gpu_mem=320 # Désactiver le logo éclair et l'arc en ciel au démarrage boot_delay=1 avoid_warnings=1 disable_splash=1 ``` ## Configuration du Wifi ``` echo -e " ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev\n update_config=1\n country=FR\n \n network={\n ssid="BLAH" # Nom du réseau auquel on se connecte\n #scan_ssid=1 # hidden ssid \n psk="BLAH" # Mot de passe wifi\n # Specify 2.4 or 5G freq\n # https://w1.fi/cgit/hostap/tree/wpa_supplicant/wpa_supplicant.conf#n910\n # https://fr.wikipedia.org/wiki/Liste_des_canaux_Wi-Fi#Bande_2,4_GHz # scan_freq=2412 2437 2462\n # See nmcli 802-11-wireless.channel\n # https://developer-old.gnome.org/NetworkManager/stable/settings-802-11-wireless.html\n # scan_freq= 5805\n }\n" | sudo tee -a /etc/wpa_supplicant/wpa_supplicant.conf ``` ## Limiter le nombre de paquets installés par APT ``` echo -e "APT::Get::Install-Recommends "false";\nAPT::Get::Install-Suggests "false";" | sudo tee -a /etc/apt/apt.conf ``` ## Rendre le démarrage du RPI complètement silencieux (écran noir) ### cmdline.txt Editer le fichier `/boot/cmdline.txt` et ajouter les options suivantes à la fin de la première ligne: ``` console=tty3 loglevel=3 vt.global_cursor_default=0 logo.nologo consoleblank=1 ``` ### Login silencieux Lancer les commandes suivantes : * `echo "" | sudo tee /etc/issue` * `echo "" | sudo tee /etc/motd` * `touch ~/.hushlogin` Editer le fichier `/etc/systemd/system/getty@tty1.service.d/autologin.conf` et remplacer le contenu par : ``` [Service] ExecStart= ExecStart=-/sbin/agetty --skip-login --noclear --noissue --login-options "-f pil" %I $TERM ``` Editer le fichier `/etc/rc.local` et ajouter la ligne suivante juste avant "exit 0" : `setterm -term linux -blank 1 >/dev/tty1` ## Connexion automatique au démarrage Lancer la commande `raspi-config`, puis aller dans "1 System Options", "S5 Boot / Auto login", "B2 Console Auto Login". ## Installation des logiciels nécessaires ``` sudo apt-get update # min sudo apt-get install vlc vlc-plugin-base python3-minimal python3-pip nginx file lua5.2 python pip install flask flask-httpauth waitress toml werkzeug # build # sudo apt-get install vlc git dkms firmware-realtek firmware-iwlwifi firmware-ipw2x00 firmware-atheros raspberrypi-kernel-headers build-essential va-driver-all va-driver vdpau-driver-all ``` ### SSH : identification par clés Sur le serveur régie, générer les clés publiques/privées avec : ``` # générer une clé sans mot de passe, adapter le nom du fichier ssh-keygen -t ed25519 -f ~/.ssh/videopiX -N "" # copier sur le client rpi en adaptant l'IP SSH_AUTH_SOCK="" ssh-copy-id -i .ssh/videopiX.pub pi@$IP ``` Désactiver la connexion par login/mdp : ``` echo "PasswordAuthentication no ChallengeResponseAuthentication no UsePAM no" | sudo tee -a /etc/ssh/sshd_config ``` Sur le serveur régie, éditer le fichier `~/.ssh/config` et ajouter à la fin : ``` # VideoPi Host 10.42.0.142 IdentityFile ~/.ssh/ User pi Host 10.42.0.135 IdentityFile ~/.ssh/rpi3 User pi ``` ## Systemd Unit : démarrage automatique des services ## VLC Créer le fichier `.config/systemd/user/vlc.service` contenant: ``` [Unit] Description=VLC http service [Service] WorkingDirectory=/home/pil/ ExecStart=/usr/bin/cvlc --quiet -I http --no-osd --http-password=secret Restart=always [Install] WantedBy=multi-user.target ``` Puis lancer les commandes : ``` systemctl --user daemon-reload systemctl --user enable vlc systemctl --user start vlc ``` ## pilpil Créer le fichier `.config/systemd/user/pilpil.service` contenant: ``` [Unit] Description=Pilpil Command Server After=network.target [Service] WorkingDirectory=/home/pil/pilpil-client ExecStart=/home/pil/pilpil-client/app.py Restart=always [Install] WantedBy=multi-user.target ``` Puis lancer les commandes : ``` systemctl --user daemon-reload systemctl --user enable pilpil systemctl --user start pilpil ``` ## Configuration du serveur régie ### Linux : network-manager cli ``` hotspot() { SSID="omen" PASSWD="EpQmSmXH123" #Intel IFW="wlo1" #Brostrend #IFW="wlp0s20f0u1" #Band (bg = 2.4Ghz, a= 5Ghz) BAND="bg" #HIDE="802-11-wireless.hidden false" CHAN="802-11-wireless.channel 1" if [ "$1" == "off" ];then nmcli radio wifi off nmcli con delete $SSID else if [ "$1" == "wlp0s20f0u1" ];then IFW="wlp0s20f0u1" # IFW="wlp0s20f0u2u4" # BAND="a" # CHAN="802-11-wireless.channel 161" fi nmcli con delete $SSID nmcli con add type wifi ifname $IFW con-name $SSID autoconnect no ssid $SSID nmcli con modify $SSID 802-11-wireless.mode ap 802-11-wireless.band $BAND $CHAN ipv4.method shared nmcli con modify $SSID wifi-sec.key-mgmt wpa-psk nmcli con modify $SSID 802-11-wireless-security.proto rsn nmcli con modify $SSID 802-11-wireless-security.pairwise ccmp nmcli con modify $SSID wifi-sec.psk $PASSWD nmcli radio wifi on nmcli con up $SSID fi } ``` #### Changer la plage d'IP du hotspot Une fois la connexion créée, éditer `/etc/NetworkManager/system-connections/$SSID.nmconnection` et ajouter une directive `address1` à la section "[ipv4]": ``` [ipv4] method=shared address1=192.168.125.1/24,192.168.125.1 ``` puis redémarrer networkmanager : ``` sudo systemctl restart NetworkManager ``` ### IP fixes des clients #### Bail dhcp permanent `sudo nano /etc/NetworkManager/dnsmasq-shared.d/wlo1.conf` ``` log-queries log-facility=/var/log/dnsmasq.log #rpi1 dhcp-host=00:e0:4c:18:0a:fa,rpi1,10.42.0.142 #rpi3 dhcp-host=b8:27:eb:12:55:31,rpi3,10.42.0.135 ``` #### WPA supplicant ### Windows setup #### Hotspot : netsh ``` netsh wlan set hostednetwork mode=allow ssid=Hotspot key=ZiZiPass netsh wlan start hostednetwork ``` #### Dependencies 1. Install wsl/msys2 ; [https://learn.microsoft.com/fr-fr/windows/wsl/install]/[https://www.msys2.org/] 2. Install openssh, rsync, python-pip : ``` pacman -S openssh rsync python-pip ``` 3. Install python deps : ``` pip install flask waitress toml ``` 4. Start app with `flask run` ### Win/Linux install With Docker-compose / Docker desktop: ``` docker-compose -f docker-compose.yml up ``` ### Firewall : port 67 Ouvrir port 67 pour le DHCP ## Imaging the OS ### From Sd to image `dd bs=256K if=/dev/sda of=BLAH.img status=progress oflag=dsync` ### Shrink image `sudo pishrink.sh -sZpa BLAH.img` ### From image to sd `xzcat 2022-07-19-videopi.img.xz | sudo dd of=/dev/sda bs=128K oflag=dsync status=progress && sync` ### Regenerate SSH hostkeys on first start `sudo ln -s /lib/systemd/system/regenerate_ssh_host_keys.service /mount_point/etc/systemd/system/multi-user.target.wants/regenerate_ssh_host_keys.service` ### (Optional) Resize FS to fill SD card Use `raspi-config` to resize the file system; "Advanced options" > "Expand Filesystem" ## Installation * Install python 3.10 * Use pip to install flask, waitress : ``` pip install flask waitress toml ``` ## Other : ### VLC http LUA : ajouter des méthodes On modifie le fichier [`httprequests.lua`](https://code.videolan.org/videolan/vlc/-/blob/master/share/lua/intf/modules/httprequests.lua) : `/usr/lib/arm-linux-gnueabihf/vlc/lua/intf/modules/httprequests.lua` Pour être sur d'avoir la bonne version, `apt-get source vlc-plugin-base` après avoir décommenter la ligne pour les sources dans `/etc/apt/sources.list`. Puis `tar -xvf vlc_3.0.17.4.orig.tar.xz vlc-3.0.17.4/share/lua/intf/modules/httprequests.lua`. On compile avec luac en faisant attention à bien utiliser la bonne version de luac ( 5.2 avec VLC-3.0.17.4 au 09-2022 ) : ``` file httprequests.luac luac.out: Lua bytecode, version 5.2 ``` Ajout ligne 131 : ```lua elseif command == "pl_move" then vlc.playlist.move( id, tonumber(val) ) ``` [https://salsa.debian.org/multimedia-team/vlc](https://salsa.debian.org/multimedia-team/vlc) #### pl_move : Usage Sample playlist : ``` ``` ``` # Move id 3 after id 5 10.42.0.135:8080/requests/status.xml?command=pl_move&id=3&val=5 ``` ``` # Make id 4 first item in list 10.42.0.135:8080/requests/status.xml?command=pl_move&id=4&val=1 Make an array from new playlist, then loop other that from the end ``` ### Certbot, Nginx, Waitress https://dev.to/thetrebelcc/how-to-run-a-flask-app-over-https-using-waitress-and-nginx-2020-235c ``` sudo apt-get install nginx ``` /etc/nginx/sites-available/default : ``` # Cmd server server { listen 8888 ssl; ssl_certificate /etc/ssl/certs/nginx-selfsigned.crt; ssl_certificate_key /etc/ssl/private/nginx-selfsigned.key; location / { client_max_body_size 100M; # Max http_upload size proxy_pass http://127.0.0.1:5000; proxy_set_header X-Real-IP $remote_addr; } } # VLC server server { listen 8887 ssl; ssl_certificate /etc/ssl/certs/nginx-selfsigned.crt; ssl_certificate_key /etc/ssl/private/nginx-selfsigned.key; location / { proxy_pass http://127.0.0.1:5001; proxy_set_header X-Real-IP $remote_addr; } } ``` openssl : ``` openssl req -new -newkey rsa:4096 -days 1825 -nodes -x509 -subj "/C=/ST=Denial/L=/O=/CN=10.42.0.135" -addext "subjectAltName=10.42.0.135" -keyout "/etc/ssl/private/nginx-selfsigned.key" -out "/etc/ssl/certs/nginx-selfsigned.crt" ``` #### Fix nginx startup fail if /var/log/nginx doesn't exists In '/etc/nginx/mklogdir.sh' : ```bash #!/bin/bash if [[ ! -d /var/log/nginx ]] then mkdir /var/log/nginx systemctl restart nginx fi ``` then `sudo chmod +x /etc/nginx/mklogdir.sh`. After that, edit the nginx service unit to add a `ExecStartPre` directive to run the script : ``` sudo systemctl edit --full nginx.service [Service] Type=forking PIDFile=/run/nginx.pid ExecStartPre=/etc/nginx/mklogdir.sh # Add this line ``` ### Bash script ```bash #!/bin/bash PASSWD="secret" ADDRESSES=("10.42.0.1" "10.42.0.135" "10.42.0.142") #ADDRESSES1=("10.42.0.1" "10.42.0.135") #ADDRESSES2=("10.42.0.142") for ADDR in ${ADDRESSES[@]} do echo "Sending command $1 and $2 to $ADDR..." echo -e "$PASSWD\n$1\n$2" | nc "$ADDR" 9999 -w 5 & # echo -e "$PASSWD\n$1\n$2" | nc "$ADDR" 9999 -w 5 | sed '/Welcome/d;/VLC/d;/Password/d;' & # echo -e "$PASSWD\n$1\n$2" | nc "$ADDR" 9999 > /dev/null & done sleep 0.5 for ADDR in ${ADDRESSES[@]} do echo "Sending command $3 and $4 to $ADDR..." echo -e "$PASSWD\n$3\n$4" | nc "$ADDR" 9999 > /dev/null & done ``` #### DKMS install All modules on all kernels : ``` ls /lib/modules | \ sudo xargs -n1 /usr/lib/dkms/dkms_autoinstaller start ``` Specific module on specific kernel : ``` sudo dkms build -m rtl8821cu -v 5.12.0 -k $kernel_version # rtl8192eu/1.0 sudo dkms install -m rtl8821cu -v 5.12.0 -k $kernel_version # rtl8192eu/1.0 # The module should loaded automatically but just if needed... sudo modprobe 8821cu # 8192eu ```