#!/bin/bash # # Options # Device block to write on # Colored output #~ set +x bold=$(tput bold) function red(){ echo -e "${bold}\x1B[31m$1 \x1B[0m" if [ ! -z "${2}" ]; then echo -e "\x1B[31m $($2) \x1B[0m" fi } function green(){ echo -e "${bold}\x1B[32m$1 \x1B[0m" if [ ! -z "${2}" ]; then echo -e "\x1B[32m $($2) \x1B[0m" fi } function yellow(){ echo -e "${bold}\x1B[33m$1 \x1B[0m" if [ ! -z "${2}" ]; then echo -e "\x1B[33m $($2) \x1B[0m" fi } SDCARD=$1 # TODO : accomodate for devices block with name mmcblk0p1|p2 if [ "$SDCARD" == "" ] || [ ! -e "$SDCARD" ] then red "Please specify an existing device block for your sd-card, e.g: '/dev/sda'." exit 0 fi DD_BS="128K" DISK_IMAGE="$HOME/niels/imgs/2022-10-21-pilpil.img.xz" if [ ! -f "$DISK_IMAGE" ] then red "Disk image not found, aborting..." exit 0 fi CONFIG_DIR="$HOME/niels/pilpil-server" if [ ! -d "$CONFIG_DIR" ] then red "Config directory not found, aborting..." exit 0 fi PI_USER="pil" BOOT_MOUNT="/run/media/$USER/boot" ROOTFS_MOUNT="/run/media/$USER/rootfs" #~ LOCAL_MEDIA_DIR="$HOME/Videos" LOCAL_MEDIA_DIR="$HOME/niels/medias" if [ ! -d "$LOCAL_MEDIA_DIR" ] then red "Medias directory not found, aborting..." exit 0 fi REMOTE_MEDIA_DIR="$ROOTFS_MOUNT/home/$PI_USER/Videos" IP_RANGE="10.42.0.1" SSID="omen" PASSWD="EpQmSmXH123" IFW="wlo1" #Band (bg = 2.4Ghz, a= 5Ghz) BAND="bg" # Hidden SSID #~ HIDE="802-11-wireless.hidden false" # Set channel manually #~ CHAN="802-11-wireless.channel 1" # # # 0. Create AP connection # # If connection exists, delete it nmcli con delete $SSID nmcli con add type wifi ifname $IFW con-name $SSID autoconnect yes ssid $SSID nmcli con modify $SSID 802-11-wireless.mode ap 802-11-wireless.band $BAND $CHAN $HIDE 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 # 0.a set IP range on server echo -e "Setting IP range $IP_RANGE/24 in /etc/NetworkManager/system-connections/$SSID.nmconnection ... \n" sudo sed -i "/method=shared/a address1=$IP_RANGE/24, $IP_RANGE" /etc/NetworkManager/system-connections/$SSID.nmconnection sudo systemctl restart NetworkManager nmcli radio wifi on nmcli con up $SSID # 0.b ask for number of clients # This will be used to determine static IP yellow "Nombre de clients à configurer : " read -n 4 CLIENT_NUMBER green "Got $CLIENT_NUMBER...\n" # For some reason networkmanager finds it clever to offer only IPs in range 10-255 even when asked for a /24, /28, etc... # So IPs start at 10 # Get first IP in specified range #~ IP=$(echo $IP_RANGE | awk -F. '{print $4}') FIRST=1 IP=10 echo -e "First IP is $(($RANGE_START)) ...\n" # Remove IP's last byte IP_RANGE_3B=$(echo $IP_RANGE | awk -F. '{print $1"."$2"."$3"."}') # Generate SSL cert with IPs in IP_RANGE IP_CNT=$IP IP_ARRAY=() while [ $IP_CNT -lt $(($CLIENT_NUMBER+$IP)) ] do IP_ARRAY+=("IP:$IP_RANGE_3B$IP_CNT") ((IP_CNT++)) done # Convert array to string HOST_LIST="$(IFS=","; echo "${IP_ARRAY[*]}")" yellow "Got host list : $HOST_LIST \n" # 5. Generate valid ssl cert/key for every IP in range # https://unix.stackexchange.com/questions/104171/create-ssl-certificate-non-interactively yellow "Generating SSL crt/key for $HOST_LIST...\n" openssl req -new -newkey rsa:4096 -days 1825 -nodes -x509 \ -subj "/C=/ST=Denial/L=/O=/CN=$IP_RANGE$FIRST" \ -addext "subjectAltName=$HOST_LIST" \ -keyout "$CONFIG_DIR/selfCA.key" -out "$CONFIG_DIR/selfCA.crt" #sudo openssl req -x509 -nodes -days 3650 -newkey rsa:2048 -keyout "$ROOTFS_MOUNT/etc/ssl/private/nginx-selfsigned.key" -out "$ROOTFS_MOUNT/etc/ssl/certs/nginx-selfsigned.crt" # Proceed with each host for HOST in "${IP_ARRAY[@]}" do HOST=$(echo $HOST | awk -F: '{print $2}') HOST_NAME="pilpil-$(echo $HOST | awk -F. '{print $4}')" # 1. Copy img to sd green "Operation 1/13 : Imaging $SDCARD with the file $DISK_IMAGE ...\n" red "Are you sure you want to ERASE THE CONTENT of $SDCARD ? Type uppercase 'yes' to confirm." read -n 4 GO_DD if [ "$GO_DD" != "YES" ] then red "Answer was different from 'YES'. Aborting..." break fi red "Received answer $GO_DD. Running dd on $SDCARD in 5 seconds." sleep 5 GO_DD=0 # unmount / remount new filesystem green "Unmounting $BOOT_MOUNT and $ROOTFS_MOUNT ...\n" umount $BOOT_MOUNT umount $ROOTFS_MOUNT xzcat "$DISK_IMAGE" | sudo dd of=$SDCARD bs="$DD_BS" oflag=dsync status=progress && sync green "Operation 3/13 : Remounting $BOOT_MOUNT and $ROOTFS_MOUNT ...\n" echo "Remounting..." sleep 1 systemctl --user restart gvfs-udisks2-volume-monitor sleep 3 green "Operation 4/13 : Changing hostname to $HOST_NAME ...\n" # Change hostname echo "$HOST_NAME" | sudo tee "$ROOTFS_MOUNT/etc/hostname" # Reflect that in /etc/hosts sudo sed -i "$ d" "$ROOTFS_MOUNT/etc/hosts" echo -e "127.0.1.1\t$HOST_NAME" | sudo tee -a "$ROOTFS_MOUNT/etc/hosts" ## Enable SSH green "Operation 5/13 : Enabling SSH server on boot ...\n" touch "$BOOT_MOUNT/ssh" sync ## Generate SSH private/public key and install it - Disable passwd login green "Operation 6/13 : Generating private/public SSH key as $HOME/.ssh/$HOST_NAME ...\n" ssh-keygen -t ed25519 -f "$HOME/.ssh/$HOST_NAME" -N "" red "New SSH key pair generated as $HOME/.ssh/$HOST_NAME. Add to ~/.ssh/config ? (y/n)" read -n 2 ADD_SSH_CONF if [ "$ADD_SSH_CONF" == "y" ] then # Add to ~/.ssh/config echo -e "\nHost $HOST_NAME\n\tHostname $HOST\n\tIdentityFile ~/.ssh/$HOST_NAME\n\tUser $PI_USER" | tee -a "$HOME/.ssh/config" fi # Copy public key to rpi green "Operation 7/13 : Installing public SSH key $HOME/.ssh/$HOST.pub in $ROOTFS_MOUNT/home/$PI_USER/.ssh/authorized_keys...\n" sudo cp "$HOME/.ssh/$HOST_NAME.pub" "$ROOTFS_MOUNT/home/$PI_USER/.ssh/authorized_keys" sync # Disable PW login green "Operation 8/13 : Disabling SSH password based login in $ROOTFS_MOUNT/etc/ssh/sshd_config ...\n" echo -e "PasswordAuthentication no\nChallengeResponseAuthentication no\nUsePAM no" | sudo tee -a "$ROOTFS_MOUNT/etc/ssh/sshd_config" sync # 3. Configure wifi with static IP green "Operation 9/13 : Configuring wireless connection to $SSID with pw $PASSWD : ...\n" echo "ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev update_config=1 country=FR network={ ssid=\"$SSID\" # Nom du réseau auquel on se connecte psk=\"$PASSWD\" # Mot de passe wifi # Optional parameters # scan_ssid=1 # hidden ssid # Specify 2.4 or 5G freq # https://w1.fi/cgit/hostap/tree/wpa_supplicant/wpa_supplicant.conf#n910 # https://fr.wikipedia.org/wiki/Liste_des_canaux_Wi-Fi#Bande_2,4_GHz # scan_freq=2412 2437 2462 }" | sudo tee "$ROOTFS_MOUNT/etc/wpa_supplicant/wpa_supplicant.conf" sync # Request specific IP to dhcp server green "Operation 10/13 : Setting static IP $HOST in $ROOTFS_MOUNT/etc/dhcpcd.conf...\n" echo -e "interface wlan0\nrequest $HOST" | sudo tee -a "$ROOTFS_MOUNT/etc/dhcpcd.conf" sync # 5. Install previously generated SSL key/crt #sudo openssl req -x509 -nodes -days 3650 -newkey rsa:2048 -keyout "$ROOTFS_MOUNT/etc/ssl/private/nginx-selfsigned.key" -out "$ROOTFS_MOUNT/etc/ssl/certs/nginx-selfsigned.crt" green "Operation 11/13 : Installing public SSH key $CONFIG_DIR/selfCA.crt in $ROOTFS_MOUNT/etc/ssl/certs/ ...\n" sudo cp "$CONFIG_DIR/selfCA.crt" "$ROOTFS_MOUNT/etc/ssl/certs/nginx-selfsigned.crt" sudo cp "$CONFIG_DIR/selfCA.key" "$ROOTFS_MOUNT/etc/ssl/private/nginx-selfsigned.key" sync #~ # 6. Copy medias green "Operation 12/13 : Syncing media folder $LOCAL_MEDIA_DIR/ with $REMOTE_MEDIA_DIR/ \n" # Remove filler file if [ -f "$REMOTE_MEDIA_DIR/remove_me" ] then sudo rm "$REMOTE_MEDIA_DIR/remove_me" fi # Get available space on rootfs ROOTFS_AVAILABLE_SPACE=$(df -t ext4 -P $ROOTFS_MOUNT | tail -1 | awk '{print $4}') # Get Media folder size MEDIA_SIZE=$(du -c $LOCAL_MEDIA_DIR | tail -1 | awk '{print $1}') # Only copy files if enough space available if [ $MEDIA_SIZE -lt $ROOTFS_AVAILABLE_SPACE ] then USER_ID=$( cat "$ROOTFS_MOUNT/etc/passwd" | grep $PI_USER | awk -F: '{print $3}' ) GROUP_ID=$( cat "$ROOTFS_MOUNT/etc/passwd" | grep $PI_USER | awk -F: '{print $4}' ) sudo cp "$LOCAL_MEDIA_DIR/"* "$REMOTE_MEDIA_DIR/" sudo chown -R $USER_ID:$GROUP_ID "$REMOTE_MEDIA_DIR" sync else red "Not enough space on $ROOTFS_MOUNT, skipping..." fi # Unmount FS green "Operation 13/13 : Unmounting filesystems" umount $BOOT_MOUNT umount $ROOTFS_MOUNT yellow "Client $(($IP-9))/$CLIENT_NUMBER done." if [ $IP -le $IP_CNT ] then red "Please swap sd card in reader and enter uppercase 'yes' to proceed with next client :" read -n 4 GO_ON if [ "$GO_ON" != "YES" ] then red "Answer was different from 'YES'. Aborting...\n" break fi GO_ON=0 ((IP++)) else green "All done !" exit 1 fi done yellow "Nothing more to do." exit 0 #~ rm "$CONFIG_DIR/selfCA.key"