diff --git a/TODO.md b/TODO.md index a5e7c96..d15d3bb 100644 --- a/TODO.md +++ b/TODO.md @@ -3,12 +3,6 @@ ## First time/Octo-Config - Add network configuration (replace nmtui) - Add hostname configuration (replace nmtui) -- Better service configuration (deeper menu) -- System check -- Touch screen calibration - -## Frontend -- Separate frontend from pi account ## Nginx - Add HTTP basic auth (especially to MJPG) diff --git a/stage1/01-sys-tweaks/00-run.sh b/stage1/01-sys-tweaks/00-run.sh index 51331c7..4225fe8 100755 --- a/stage1/01-sys-tweaks/00-run.sh +++ b/stage1/01-sys-tweaks/00-run.sh @@ -9,6 +9,7 @@ install -m 644 files/.dialogrc "${ROOTFS_DIR}/etc/skel/.dialogrc" install -m 644 files/.dialogrc "${ROOTFS_DIR}/root/.dialogrc" mkdir -p "${ROOTFS_DIR}/etc/skel/.config/openbox" install -m 644 files/autostart "${ROOTFS_DIR}/etc/skel/.config/openbox/autostart" +install -m 644 files/menu.xml "${ROOTFS_DIR}/etc/skel/.config/openbox/menu.xml" on_chroot << EOF if ! id -u ${FIRST_USER_NAME} >/dev/null 2>&1; then @@ -17,7 +18,10 @@ fi if ! id -u octoprint >/dev/null 2>&1; then adduser --system --shell /usr/sbin/nologin --group --disabled-password --gecos "" octoprint fi +if ! id -u kiosk >/dev/null 2>&1; then + adduser --disabled-password --shell /usr/sbin/nologin --gecos "" kiosk +fi echo "${FIRST_USER_NAME}:${FIRST_USER_PASS}" | chpasswd -echo "octoprint:$(cat /dev/urandom | tr -dc _A-Z-a-z-0-9 | head -c40)" | chpasswd +echo "kiosk:$(cat /dev/urandom | tr -dc _A-Z-a-z-0-9 | head -c40)" | chpasswd echo "root:$(cat /dev/urandom | tr -dc _A-Z-a-z-0-9 | head -c40)" | chpasswd EOF diff --git a/stage1/01-sys-tweaks/files/.browser.sh b/stage1/01-sys-tweaks/files/.browser.sh index 01dd8fe..c1ebadb 100644 --- a/stage1/01-sys-tweaks/files/.browser.sh +++ b/stage1/01-sys-tweaks/files/.browser.sh @@ -1,25 +1,25 @@ #!/bin/bash # Grabs the port (and IP) out of the nginx config -LISTEN=$(grep -i listen /etc/nginx/listen.conf | awk '{gsub(";",""); print $2}') +LISTEN=$(awk '/listen/{gsub(";",""); print $2}' /etc/nginx/listen.conf) # If the value we just grabbed doesn't contain an IP, prepend localhost if ! echo $LISTEN | grep ":" 2>&1; then - ADDRESS="localhost:$LISTEN" + ADDRESS="https://localhost:$LISTEN" else - ADDRESS=$LISTEN + ADDRESS="https://$LISTEN" fi # Override the automatically detected address if the user wants to if [[ -f ~/.overrideurl.sh ]]; then source ~/.overrideurl.sh; fi # Wait until Nginx/override comes up -while ! curl "$ADDRESS" 2>&1 >/dev/null; do +while ! curl -f -k -s -I "$ADDRESS" 2>&1 >/dev/null; do sleep 1 done # Wait until OctoPrint comes up if it is enabled -while [[ -f /etc/systemd/system/multi-user.target.wants/octoprint.service ]] && ! curl "localhost:5000"; do +while [[ -f /etc/systemd/system/multi-user.target.wants/octoprint.service ]] && ! curl -f -s -I "localhost:5000"; do sleep 1 done @@ -31,4 +31,4 @@ done # -K | Enable kiosk mode (doesn't seem to do anything?) # -n | Disable web inspector # -p | Disable plugins -surf -t -F -g -K -n -p "https://$ADDRESS" +surf -t -F -g -K -n -p "$ADDRESS" diff --git a/stage1/01-sys-tweaks/files/menu.xml b/stage1/01-sys-tweaks/files/menu.xml new file mode 100644 index 0000000..60e591c --- /dev/null +++ b/stage1/01-sys-tweaks/files/menu.xml @@ -0,0 +1,18 @@ + + + + + + + bash ~/.browser.sh + + + + + + + + diff --git a/stage2/01-sys-tweaks/01-run.sh b/stage2/01-sys-tweaks/01-run.sh index 5cb650a..c5f1ff6 100755 --- a/stage2/01-sys-tweaks/01-run.sh +++ b/stage2/01-sys-tweaks/01-run.sh @@ -46,6 +46,9 @@ done for GRP in dialout plugdev video users; do adduser octoprint \$GRP done +for GRP in users; do + adduser kiosk \$GRP +done EOF on_chroot << EOF diff --git a/stage2/06-utils/files/first-time.sh b/stage2/06-utils/files/first-time.sh index 7efe87e..11aea05 100755 --- a/stage2/06-utils/files/first-time.sh +++ b/stage2/06-utils/files/first-time.sh @@ -67,7 +67,10 @@ suggested_menu () { dialog --title "NOTICE" --nocancel --colors --msgbox "This collection of software is currently in beta. It is lacking several critical features. \Zb\Z1DO NOT\Zn use this in a production environment." 10 50 # Force the user to change the pi user's password before the RPi gets botnetted -change_password +change_password +# Randomize the root and frontend password +echo "kiosk:$(cat /dev/urandom | tr -dc _A-Z-a-z-0-9 | head -c40)" | chpasswd +echo "root:$(cat /dev/urandom | tr -dc _A-Z-a-z-0-9 | head -c40)" | chpasswd dialog --title "Network Configuration" --nocancel --msgbox "Setup will now open nmtui, a program to help configure your ethernet/wireless interfaces. Hit Quit when you are done." 10 50 nmtui @@ -76,10 +79,14 @@ nmtui dpkg-reconfigure tzdata # Enable/disable OctoPrint, GUI, MJPG and SSH -service_select +service_toggle screen_timeout +if ( udevadm info --export-db | grep ID_INPUT_TOUCHSCREEN=1 >/dev/null ) && dialog --title "Touchscreen Calibration" --defaultno --yesno "Do you wish to calibrate your touchscreen?\nMost touchscreens are calibrated out of the factory, so this is usually not needed." 10 60; then + startx $(which xinput_calibrator) --no-timeout --output-filename /etc/X11/xorg.conf.d/99-calibration.conf +fi + # Makes a certificate and key for Nginx HTTPS openssl req -x509 -nodes -days 36500 -newkey rsa:4096 -subj "/C=/ST=/L=/O=/OU=/CN=*/emailAddress=" -out /etc/ssl/certs/nginx-octoprint.crt -keyout /etc/ssl/private/nginx-octoprint.key @@ -90,6 +97,7 @@ fi # If MJPG service is enabled, ask user which video device to use if [[ -f /etc/systemd/system/multi-user.target.wants/mjpg-streamer.service ]]; then + video_select video_config fi diff --git a/stage2/06-utils/files/octo-config b/stage2/06-utils/files/octo-config index 43f1dbb..8525c74 100755 --- a/stage2/06-utils/files/octo-config +++ b/stage2/06-utils/files/octo-config @@ -9,26 +9,77 @@ fi source /usr/local/lib/octo-lib.sh main_menu () { - local MAINMENU=$(dialog --nocancel --title "Pi Setup" --menu "" 10 50 0 \ + local MAINMENU=$(dialog --nocancel --title "TouchPrint Setup" --menu "" 10 50 0 \ "1" "Configure networking" \ "2" "Change password for pi" \ "3" "Configure services" \ "4" "Configure screen timeout" \ - "5" "Configure Nginx" \ - "6" "Configure MJPG" \ - "7" "Exit" 3>&1 1>&2 2>&3) + "5" "Calibrate touchscreen" \ + "6" "Exit" 3>&1 1>&2 2>&3) case $MAINMENU in "1") nmtui; main_menu; return 0;; "2") change_password; main_menu; return 0;; - "3") service_select; main_menu; return 0;; + "3") services_menu; main_menu; return 0;; "4") screen_timeout; main_menu; return 0;; - "5") nginx_config; main_menu; return 0;; - "6") video_config; main_menu; return 0;; - "7") return 0;; + "5") dialog --title "Touchscreen Calibration" --infobox "Waiting for touchscreen calibrator to close..." 3 50; DISPLAY=:0 xinput_calibrator --no-timeout --output-filename /etc/X11/xorg.conf.d/99-calibration.conf; main_menu; return 0;; + "6") return 0;; esac } +services_menu () { + local SERVICESMENU=$(dialog --nocancel --title "Services Select" --menu "" 10 50 0 \ + "1" "Enable/disable services" \ + "2" "Service health check" \ + "3" "Configure Nginx" \ + "4" "Configure MJPG" \ + "5" "Go Back" 3>&1 1>&2 2>&3) + + case $SERVICESMENU in + "1") service_toggle; services_menu; return 0;; + "2") service_health; services_menu; return 0;; + "3") nginx_config; services_menu; return 0;; + "4") video_menu; services_menu; return 0;; + "5") return 0;; + esac +} + +service_health () { + # Grab listening address/port from Nginx config + if [[ -f /etc/nginx/listen.conf ]]; then + LISTEN=$(awk '/listen/{gsub(";",""); print $2}' /etc/nginx/listen.conf) + else + LISTEN="443" + fi + + # If Nginx config didn't contain a port, assume localhost + if ! echo $LISTEN | grep ":" 2>&1; then + ADDRESS="localhost:$LISTEN" + else + ADDRESS=$LISTEN + fi + + # I hate bash, and soon you will too + dialog --colors --title "Service Health" --msgbox "\ +\ZnOctoPrint: \Zb$(if curl -s -I 127.0.0.1:5000 >/dev/null; then echo '\Z2Online'; elif [[ ! -f /etc/systemd/system/multi-user.target.wants/octoprint.service ]]; then echo "Disabled"; else echo '\Z1Offline'; fi) +\ZnMJPG: \Zb$(if curl -s -I 127.0.0.1:9000 >/dev/null; then echo '\Z2Online'; elif [[ ! -f /etc/systemd/system/multi-user.target.wants/mjpg-streamer.service ]]; then echo "Disabled"; else echo '\Z1Offline'; fi) +\ZnNginx: \Zb$(if curl -k -s -I https://$ADDRESS >/dev/null; then echo '\Z2Online'; elif [[ ! -f /etc/systemd/system/multi-user.target.wants/nginx.service ]]; then echo "Disabled"; else echo '\Z1Offline'; fi) +\ZnSSH: \Zb$(if pgrep sshd >/dev/null; then echo '\Z2Online'; elif [[ ! -f /etc/systemd/system/multi-user.target.wants/sshd.service ]]; then echo "Disabled"; else echo '\Z1Offline'; fi)" 0 0 +} + +video_menu () { + local VIDEOMENU=$(dialog --title "MJPG Config" --menu "" 10 50 0 \ + "1" "Camera Selection" \ + "2" "Video Settings" \ + "3" "Go Back" 3>&1 1>&2 2>&3) + + case $VIDEOMENU in + "1") video_select; video_menu; return 0;; + "2") video_config; video_menu; return 0;; + "3") return 0;; + esac +} + main_menu if dialog --title "Reboot Confirmation" --yesno "Some changes require a reboot to take effect.\nDo you want to reboot now?" 10 50; then reboot diff --git a/stage2/06-utils/files/octo-lib.sh b/stage2/06-utils/files/octo-lib.sh index 77305d0..a17c087 100644 --- a/stage2/06-utils/files/octo-lib.sh +++ b/stage2/06-utils/files/octo-lib.sh @@ -19,7 +19,7 @@ change_password () { unset PASSWORD } -service_select () { +service_toggle () { # Toggle the checkboxes if the service is active or not local SERVICE_MENU=$(dialog --separate-output --nocancel --title "Select services" --checklist "Enable/disable services" 0 0 0 \ "1" "OctoPrint" $(if [[ -f /etc/systemd/system/multi-user.target.wants/octoprint.service ]]; then echo "ON"; else echo "OFF"; fi) \ @@ -69,7 +69,6 @@ service_select () { systemctl disable ssh fi - << 'EOF' for ((i = 0; i <= 3; i++)); do for n in "${SERVICE_MENU[@]}"; do @@ -91,9 +90,12 @@ service_select () { EOF } -screen_timeout() { +screen_timeout () { local TIMEOUT=$(dialog --nocancel --title "Screen Timeout" --inputbox "Input your desired screen timeout in seconds.\nEnter \"off\" to disable the screen timeout.\n\nAdding a screen timeout can reduce screen burn in.\n\nDefault: off" 12 60 "off" 3>&1 1>&2 2>&3) - cat > /home/pi/.xtimeout << EOF + + [[ "$TIMEOUT" == "" ]] && return 0 + + cat > /home/kiosk/.xtimeout << EOF xset s ${TIMEOUT} xset -dpms EOF @@ -104,24 +106,29 @@ nginx_config () { # Grab the variable from the nginx conf if it exists, otherwise use default if [[ -f /etc/nginx/listen.conf ]]; then - LISTEN=$(grep -i listen /etc/nginx/listen.conf | awk '{gsub(";",""); print $2}') + LISTEN=$(awk '/listen/{gsub(";",""); print $2}' /etc/nginx/listen.conf) else LISTEN="443" fi LISTEN=$(dialog --title "Nginx Config" --nocancel --inputbox "Configure what port and IP Nginx should listen on.\nTo listen on all IPs, just enter the port.\nDefault: 443" 11 50 "$LISTEN" 3>&1 1>&2 2>&3) + [[ "$LISTEN" == "" ]] && return 0 + # Write new value to nginx echo "listen $LISTEN;" > /etc/nginx/listen.conf } -video_config () { +video_select () { # In the unlikely event that there are no video devices, don't continue if ! ls /dev/video* 2>&1 >/dev/null; then dialog --title "Error" --msgbox "No video devices detected!" 10 50 return 1 fi + # Grab config values + source /usr/local/etc/mjpg-server/config.sh + # Grab all video devices local DEVICES=($(ls /dev/video*)) @@ -129,13 +136,41 @@ video_config () { # Generate a menu from said video devices for ((i = 0; i < ${#DEVICES[@]}; i++)); do - DEVICELIST+="${DEVICES[$i]} $i OFF " + if [[ "$VIDEO_DEVICE" == ${DEVICES[$i]} ]]; then + DEVICELIST+="${DEVICES[$i]} $i ON " + else + DEVICELIST+="${DEVICES[$i]} $i OFF " + fi done - local DEVICE_MENU=$(dialog --title "Video Config" --nocancel --radiolist "Choose which video device you wish to use for MJPG-Streamer" 10 50 0 $DEVICELIST 3>&1 1>&2 2>&3) + local DEVICE_MENU=$(dialog --title "MJPG Config" --nocancel --radiolist "Choose which video device you wish to use for MJPG-Streamer" 10 50 0 $DEVICELIST 3>&1 1>&2 2>&3) [[ "$DEVICE_MENU" == "" ]] && return 0 - # Write selected value to startup script - echo -e '#!/bin/bash'"\n/usr/local/bin/mjpeg-server -a 127.0.0.1:9000 -- ffmpeg -i $DEVICE_MENU -f v4l2 -f mpjpeg -" > /usr/local/bin/start-mjpg + # Write selected value to config file + echo -e "VIDEO_DEVICE=$DEVICE_MENU\nVIDEO_SIZE=$VIDEO_SIZE\nFRAMERATE=$FRAMERATE" > /usr/local/etc/mjpg-server/config.sh +} + +video_config () { + # Include config values + source /usr/local/etc/mjpg-server/config.sh + + # Set video device to a resonable default if it isn't set for some reason + if [[ "$VIDEO_DEVICE" == "" ]]; then + VIDEO_DEVICE="/dev/video0" + fi + + local VIDEOCONFIG_MENU=$(dialog --nocancel --title "MJPG Config" --form "Choose desired camera resolution and framerate." 10 50 0\ + "Resolution: " 1 1 "$VIDEO_SIZE" 1 13 10 0 \ + "Framerate: " 2 1 "$FRAMERATE" 2 12 3 0 3>&1 1>&2 2>&3) + VIDEOCONFIG_MENU=($VIDEOCONFIG_MENU) + + if [[ "$VIDEOCONFIG_MENU[0]" == "" ]] || [[ "$VIDEOCONFIG_MENU[1]" == "" ]]; then + dialog --title "Error" --msgbox "Invalid input!" 10 50 + video_config + return 0 + fi + + # Write values to config file + echo -e "VIDEO_DEVICE=$VIDEO_DEVICE\nVIDEO_SIZE=${VIDEOCONFIG_MENU[0]}\nFRAMERATE=${VIDEOCONFIG_MENU[1]}" > /usr/local/etc/mjpg-server/config.sh } diff --git a/stage3/00-install-packages/01-run.sh b/stage3/00-install-packages/01-run.sh index 4adb563..6654d2d 100755 --- a/stage3/00-install-packages/01-run.sh +++ b/stage3/00-install-packages/01-run.sh @@ -1,41 +1,7 @@ #!/bin/bash -e -#echo -n -e "NODM_USER=${FIRST_USER_NAME}\nNODM_XSESSION=/home/${FIRST_USER_NAME}/.xprofile" > ${ROOTFS_DIR}/etc/nodm.conf - -cat > ${ROOTFS_DIR}/etc/default/nodm << EOF -# nodm configuration - -# Set NODM_ENABLED to something different than 'false' to enable nodm -NODM_ENABLED=true - -# User to autologin for -NODM_USER=${FIRST_USER_NAME} - -# First vt to try when looking for free VTs -NODM_FIRST_VT=7 - -# X session -NODM_XSESSION=/home/${FIRST_USER_NAME}/.xprofile - -# Options for nodm itself -NODM_OPTIONS= - -# Options for the X server. -# -# Format: [/usr/bin/] [:] -# -# The Xserver executable and the display name can be omitted, but should -# be placed in front, if nodm's defaults shall be overridden. -NODM_X_OPTIONS='-nolisten tcp' - -# If an X session will run for less than this time in seconds, nodm will wait an -# increasing bit of time before restarting the session. -NODM_MIN_SESSION_TIME=60 - -# Timeout (in seconds) to wait for X to be ready to accept connections. If X is -# not ready before this timeout, it is killed and restarted. -NODM_X_TIMEOUT=300 -EOF +mkdir -p ${ROOTFS_DIR}/etc/default +install -m 644 files/nodm ${ROOTFS_DIR}/etc/default/nodm # Probably not needed on_chroot << EOF diff --git a/stage3/00-install-packages/files/nodm b/stage3/00-install-packages/files/nodm new file mode 100644 index 0000000..b254e2b --- /dev/null +++ b/stage3/00-install-packages/files/nodm @@ -0,0 +1,33 @@ +# nodm configuration + +# Set NODM_ENABLED to something different than 'false' to enable nodm +NODM_ENABLED=true + +# User to autologin for +NODM_USER=kiosk + +# First vt to try when looking for free VTs +NODM_FIRST_VT=7 + +# X session +NODM_XSESSION=/home/kiosk/.xprofile + +# Options for nodm itself +NODM_OPTIONS= + +# Options for the X server. +# +# Format: [/usr/bin/] [:] +# +# The Xserver executable and the display name can be omitted, but should +# be placed in front, if nodm's defaults shall be overridden. +NODM_X_OPTIONS='-nolisten tcp' + +# If an X session will run for less than this time in seconds, nodm will wait an +# increasing bit of time before restarting the session. +NODM_MIN_SESSION_TIME=60 + +# Timeout (in seconds) to wait for X to be ready to accept connections. If X is +# not ready before this timeout, it is killed and restarted. +NODM_X_TIMEOUT=300 +