diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2b8e897 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/getoptions \ No newline at end of file diff --git a/add_nginx_camera.sh b/add_nginx_camera.sh new file mode 100644 index 0000000..9424dec --- /dev/null +++ b/add_nginx_camera.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +# TODO: add nginx configs for an additional camera streamer \ No newline at end of file diff --git a/config/apt-packages b/config/apt-packages index cbc51ba..356f566 100644 --- a/config/apt-packages +++ b/config/apt-packages @@ -16,3 +16,5 @@ mariadb-server python3-dev stm32flash virtualenv +nginx +lolcat \ No newline at end of file diff --git a/config/nginx/common_vars.conf b/config/nginx/common_vars.conf new file mode 100644 index 0000000..9c3f85e --- /dev/null +++ b/config/nginx/common_vars.conf @@ -0,0 +1,6 @@ +# /etc/nginx/conf.d/common_vars.conf + +map $http_upgrade $connection_upgrade { + default upgrade; + '' close; +} \ No newline at end of file diff --git a/config/nginx/mainsail-proxy.conf b/config/nginx/mainsail-proxy.conf new file mode 100644 index 0000000..9383ecb --- /dev/null +++ b/config/nginx/mainsail-proxy.conf @@ -0,0 +1,14 @@ +# location ~ ^/PRINTERNAMELC/(.*) { +# proxy_pass http://127.0.0.1:PORT/$1; +# proxy_http_version 1.1; +# proxy_set_header Upgrade $http_upgrade; +# proxy_set_header Connection $connection_upgrade; +# proxy_set_header Host $host; +# proxy_buffering off; +# proxy_read_timeout 10800s; +# proxy_send_timeout 10800s; +# proxy_connect_timeout 30s; +# } +location ~ ^/PRINTERNAMELC/(.*) { + return 301 $scheme://$host:PORT/$1; +} \ No newline at end of file diff --git a/config/nginx/mainsail-site.conf b/config/nginx/mainsail-site.conf new file mode 100644 index 0000000..9f1c1d6 --- /dev/null +++ b/config/nginx/mainsail-site.conf @@ -0,0 +1,55 @@ +# config file for a specific printer subdir +server { + listen PORT default_server; + rewrite_log on; + access_log /var/log/nginx/PRINTERNAME-mainsail-access.log; + error_log /var/log/nginx/PRINTERNAME-mainsail-error.log info; + + # disable this section on smaller hardware like a pi zero + gzip on; + gzip_vary on; + gzip_proxied any; + gzip_proxied expired no-cache no-store private auth; + gzip_comp_level 4; + gzip_buffers 16 8k; + gzip_http_version 1.1; + gzip_types text/plain text/css text/xml text/javascript application/javascript application/x-javascript application/json application/xml; + + index index.html; + + # disable max upload size checks + client_max_body_size 0; + + # disable proxy request buffering + proxy_request_buffering off; + root /home/pi/PRINTERNAME/mainsail; + + location / { + try_files $uri $uri/ /index.html; + } + + location = /index.html { + add_header Cache-Control "no-store, no-cache, must-revalidate"; + } + + location /websocket { + proxy_pass http://PRINTERNAMELCapiserver/websocket; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection $connection_upgrade; + proxy_set_header Host $http_host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_read_timeout 86400; + } + + location ~ ^/(printer|api|access|machine|server)/ { + proxy_pass http://PRINTERNAMELCapiserver$request_uri; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Host $http_host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Scheme $scheme; + } +} \ No newline at end of file diff --git a/config/nginx/mainsail-upstream.conf b/config/nginx/mainsail-upstream.conf new file mode 100644 index 0000000..15f1492 --- /dev/null +++ b/config/nginx/mainsail-upstream.conf @@ -0,0 +1,6 @@ +# config file for a specific printer upstream + +upstream PRINTERNAMELCapiserver { + ip_hash; + server 127.0.0.1:PORT; +} \ No newline at end of file diff --git a/config/nginx/site.conf b/config/nginx/site.conf new file mode 100644 index 0000000..a2186b4 --- /dev/null +++ b/config/nginx/site.conf @@ -0,0 +1,92 @@ +# /etc/nginx/sites-available/site.conf + +server { + listen 80 default_server; + rewrite_log on; + access_log /var/log/nginx/mainsail-access.log; + error_log /var/log/nginx/mainsail-error.log debug; + + # disable this section on smaller hardware like a pi zero + gzip on; + gzip_vary on; + gzip_proxied any; + gzip_proxied expired no-cache no-store private auth; + gzip_comp_level 4; + gzip_buffers 16 8k; + gzip_http_version 1.1; + gzip_types text/plain text/css text/xml text/javascript application/javascript application/x-javascript application/json application/xml; + + index index.html; + server_name _; + + # disable max upload size checks + client_max_body_size 0; + + # disable proxy request buffering + proxy_request_buffering off; + + include /etc/nginx/mainsail/proxy/*.conf; + + location /webcam/ { + postpone_output 0; + proxy_buffering off; + proxy_ignore_headers X-Accel-Buffering; + access_log off; + error_log off; + proxy_pass http://mjpgstreamer1/; + } + + location /webcam2/ { + postpone_output 0; + proxy_buffering off; + proxy_ignore_headers X-Accel-Buffering; + access_log off; + error_log off; + proxy_pass http://mjpgstreamer2/; + } + + location /webcam3/ { + postpone_output 0; + proxy_buffering off; + proxy_ignore_headers X-Accel-Buffering; + access_log off; + error_log off; + proxy_pass http://mjpgstreamer3/; + } + + location /webcam4/ { + postpone_output 0; + proxy_buffering off; + proxy_ignore_headers X-Accel-Buffering; + access_log off; + error_log off; + proxy_pass http://mjpgstreamer4/; + } + + location /webcam5/ { + postpone_output 0; + proxy_buffering off; + proxy_ignore_headers X-Accel-Buffering; + access_log off; + error_log off; + proxy_pass http://mjpgstreamer5/; + } + + location /webcam6/ { + postpone_output 0; + proxy_buffering off; + proxy_ignore_headers X-Accel-Buffering; + access_log off; + error_log off; + proxy_pass http://mjpgstreamer6/; + } + + location /webcam7/ { + postpone_output 0; + proxy_buffering off; + proxy_ignore_headers X-Accel-Buffering; + access_log off; + error_log off; + proxy_pass http://mjpgstreamer7/; + } +} \ No newline at end of file diff --git a/config/nginx/upstreams.conf b/config/nginx/upstreams.conf new file mode 100644 index 0000000..a23bd6a --- /dev/null +++ b/config/nginx/upstreams.conf @@ -0,0 +1,38 @@ +# /etc/nginx/conf.d/upstreams.conf + +include /etc/nginx/mainsail/upstream/*.conf; + +upstream mjpgstreamer1 { + ip_hash; + server 127.0.0.1:8080; +} + +upstream mjpgstreamer2 { + ip_hash; + server 127.0.0.1:8081; +} + +upstream mjpgstreamer3 { + ip_hash; + server 127.0.0.1:8082; +} + +upstream mjpgstreamer4 { + ip_hash; + server 127.0.0.1:8083; +} + +upstream mjpgstreamer5 { + ip_hash; + server 127.0.0.1:8084; +} + +upstream mjpgstreamer6 { + ip_hash; + server 127.0.0.1:8085; +} + +upstream mjpgstreamer7 { + ip_hash; + server 127.0.0.1:8086; +} \ No newline at end of file diff --git a/setup.sh b/setup.sh index f550b47..76327f4 100755 --- a/setup.sh +++ b/setup.sh @@ -1,11 +1,30 @@ #!/bin/bash -# TODO: CHANGE KLIPPER PORTS -# TODO: Setup Mainsail # TODO: Add Crowsnest Support -# TODO: Add Override cmd arguments # TODO: Avoid duplicate printer names +# TODO: Dry run +# TODO: Printer Directory Page in NGINX +# TODO: Fix PolicyKit issues "klippy_uds_address" +# Handle arguments +ARG_HELP=0 +ARG_SKIP_APT=0 +ARG_NAME=0 +ARG_CONFIG=0 +ARG_PORT=0 +while [[ "$#" -gt 0 ]]; do + case $1 in + -h|--help) ARG_HELP=1 ;; + -a|--skip-apt) ARG_SKIP_APT=1 ;; + -n|--name) ARG_NAME="$2" ; shift ;; + -c|--config) ARG_CONFIG="$2" ; shift ;; + -p|--port) ARG_PORT="$2" ; shift ;; + *) echo "Unknown Parameter"; exit 3 ;; + esac + shift +done + +# Prepare global variables SOURCE=${BASH_SOURCE[0]} while [ -L "$SOURCE" ]; do TARGET=$(readlink "$SOURCE") @@ -22,76 +41,116 @@ cd $ROOT_DIR source ./ColorEchoForShell/dist/ColorEcho.bash +if [[ "$ARG_HELP" == 1 ]]; then + echo.Cyan "HacDC Printewr Setup Script Usage" + echo.Yellow "./setup.sh [options]" + echo "" + echo.BoldPurple "Option Description" + echo.Rainbow "-h/--help Display this help msg" + echo.Rainbow "-a/--skip-apt Skip installing apt packages" + echo.Rainbow "-n/--name Specify printer name (skips popup)" + echo.Rainbow "-c/--config Specify printer config (skips popup)" + echo.Rainbow "-p/--port Specify printer port (skips popup)" + exit 0 +fi # Pull Klipper git submodule update --init --recursive # Install packages -echo.Cyan "Installing required packageas" -for PACKAGE in `cat $ROOT_DIR/config/apt-packages`; do - sudo apt install -y $PACKAGE -done +if [[ "$ARG_SKIP_APT" == 1 ]]; then + echo.ICyan "Apt packagees skipped" +else + echo.Cyan "Installing required packageas" + for PACKAGE in `cat $ROOT_DIR/config/apt-packages`; do + sudo apt install -y $PACKAGE + done +fi # Name Printer -NAME_NOT_VALID=true -while $NAME_NOT_VALID ; do - PRINTER_NAME=$(dialog --backtitle 'drwho@hackers.town' --inputbox 'Name This Printer' 8 40 "${PRINTER_NAME}" 3>&1 1>&2 2>&3) - if [[ $PRINTER_NAME =~ ^[a-zA-Z0-9_-]+$ ]]; then - NAME_NOT_VALID=false - fi -done +PRINTER_NAME="" +if [[ "$ARG_NAME" == 0 ]]; then + NAME_NOT_VALID=true + while $NAME_NOT_VALID ; do + PRINTER_NAME=$(dialog --backtitle 'drwho@hackers.town' --inputbox 'Name This Printer' 8 40 "${PRINTER_NAME}" 3>&1 1>&2 2>&3) + if [[ $PRINTER_NAME =~ ^[a-zA-Z0-9_-]+$ ]]; then + NAME_NOT_VALID=false + fi + done +else + echo.ICyan "Using passed printer name: $ARG_NAME" + PRINTER_NAME="$ARG_NAME" +fi cp -r $ROOT_DIR/dirs $ROOT_DIR/$PRINTER_NAME # Select Klipper Config cd $ROOT_DIR/$PRINTER_NAME/klipper make menuconfig -CONFIG_FILES=(`ls config`) -CONFIG_FILES+=("Enter_Manually") -let i=0 -C=() -for f in ${CONFIG_FILES[@]}; do - C+=($i $f) - let i+=1 -done -CONFIG_INDEX=$(dialog --backtitle "drwho@hackers.town" --title "Printer Selection" --menu "Select Printer Config" --output-fd 1 40 0 1 ${C[@]}) -CONFIG_FILE=${CONFIG_FILES[$CONFIG_INDEX]} -if [[ $CONFIG_FILE == "Enter_Manually" ]]; then - MANUAL_FILE="" - while [ ! -f "${MANUAL_FILE}" ]; do - MANUAL_FILE=$(dialog --backtitle "drwho@hackers.town" --title "Manual Config Selection" --inputbox "Enter Full Config File Path" 8 40 "${MANUAL_FILE}" 3>&1 1>&2 2>&3) +CONFIG_FILE="" +if [[ "$ARG_CONFIG" == 0 ]]; then + CONFIG_FILES=(`ls config`) + CONFIG_FILES+=("Enter_Manually") + let i=0 + C=() + for f in ${CONFIG_FILES[@]}; do + C+=($i $f) + let i+=1 done - CONFIG_FILE=$MANUAL_FILE + CONFIG_INDEX=$(dialog --backtitle "drwho@hackers.town" --title "Printer Selection" --menu "Select Printer Config" --output-fd 1 40 0 1 ${C[@]}) + CONFIG_FILE=${CONFIG_FILES[$CONFIG_INDEX]} + if [[ $CONFIG_FILE == "Enter_Manually" ]]; then + MANUAL_FILE="" + while [ ! -f "${MANUAL_FILE}" ]; do + MANUAL_FILE=$(dialog --backtitle "drwho@hackers.town" --title "Manual Config Selection" --inputbox "Enter Full Config File Path" 8 40 "${MANUAL_FILE}" 3>&1 1>&2 2>&3) + done + CONFIG_FILE=$MANUAL_FILE + else + # TODO: maybe replace this with the full path? + CONFIG_FILE="./config/$CONFIG_FILE" + fi else - CONFIG_FILE="./config/$CONFIG_FILE" + echo.ICyan "Using passed config file" + CONFIG_FILE="$ARG_CONFIG" fi # Select Serial Device -DEVICES=(`ls /dev/serial/by-id/`) -DEVICES+=("Enter_Manually") -let i=0 -C=() -for f in ${DEVICES[@]}; do - C+=($i $f) - let i+=1 -done -DEVICE_INDEX=$(dialog --backtitle "drwho@hackers.town" --title "USB Device Selection" --menu "Select USB Device" --output-fd 1 40 0 1 ${C[@]}) -DEVICE=${DEVICES[$DEVICE_INDEX]} - -if [[ $DEVICE == "Enter_Manually" ]]; then - MANUAL_FILE="" - while [ ! -f "${MANUAL_FILE}" ]; do - MANUAL_FILE=$(dialog --backtitle "drwho@hackers.town" --title "Manual Device Selection" --inputbox "Enter Full Device File Path" 8 40 "${MANUAL_FILE}" 3>&1 1>&2 2>&3) +DEVICE="" +if [[ "$ARG_PORT" == 0 ]]; then + DEVICES=(`ls /dev/serial/by-id/`) + DEVICES+=("Enter_Manually") + let i=0 + C=() + for f in ${DEVICES[@]}; do + C+=($i $f) + let i+=1 done - DEVICE=$MANUAL_FILE + DEVICE_INDEX=$(dialog --backtitle "drwho@hackers.town" --title "USB Device Selection" --menu "Select USB Device" --output-fd 1 40 0 1 ${C[@]}) + DEVICE=${DEVICES[$DEVICE_INDEX]} + + if [[ $DEVICE == "Enter_Manually" ]]; then + MANUAL_FILE="" + while [ ! -f "${MANUAL_FILE}" ]; do + MANUAL_FILE=$(dialog --backtitle "drwho@hackers.town" --title "Manual Device Selection" --inputbox "Enter Full Device File Path" 8 40 "${MANUAL_FILE}" 3>&1 1>&2 2>&3) + done + DEVICE="/dev/serial/by-id/$MANUAL_FILE" + fi +else + echo.ICyan "Using passed serial port" + DEVICE="$ARG_PORT" fi # Build Klipper +echo.Cyan "Compile Klipper Firmware" cp $CONFIG_FILE $ROOT_DIR/$PRINTER_NAME/klipper/printer.cfg -sed -i -e "s/^serial: .\+$/serial: \/dev\/serial\/by-id\/${DEVICE}/g" "${ROOT_DIR}/$PRINTER_NAME/klipper/printer.cfg" +sed -i -e "s/^serial: .\+$/LINEHERE/g" "$ROOT_DIR/$PRINTER_NAME/klipper/printer.cfg" +cat $ROOT_DIR/$PRINTER_NAME/klipper/printer.cfg | replace "LINEHERE" "serial: $DEVICE" > $ROOT_DIR/$PRINTER_NAME/klipper/tmp.cfg +rm $ROOT_DIR/$PRINTER_NAME/klipper/printer.cfg +mv $ROOT_DIR/$PRINTER_NAME/klipper/tmp.cfg $ROOT_DIR/$PRINTER_NAME/klipper/printer.cfg make -j$(nproc) # Flash Firmware -make flash FLASH_DEVICE=/dev/serial/by-id/$DEVICE +echo.Cyan "Flash Device" +make flash FLASH_DEVICE=$DEVICE # Copy over printer config file echo.Cyan "Setup printer.cfg" @@ -126,11 +185,55 @@ echo.Cyan "Downloading Mainsail" wget -q -O mainsail.zip https://github.com/mainsail-crew/mainsail/releases/latest/download/mainsail.zip unzip -o mainsail.zip -d $PRINTER_NAME/mainsail rm mainsail.zip -# -# -# SETUP MAINSAIL HERE BAKA -# -# + +echo.ICyan "Installing base nginx configs" +if [ ! -f /etc/nginx/conf.d/upstreams.conf ]; then + sudo cp $ROOT_DIR/config/nginx/upstreams.conf /etc/nginx/conf.d/upstreams.conf + sudo chown root:root /etc/nginx/conf.d/upstreams.conf +else + echo.ICyan "upstreams.conf already exists" +fi + +if [ ! -f /etc/nginx/sites-available/site.conf ]; then + sudo cp $ROOT_DIR/config/nginx/site.conf /etc/nginx/sites-available/site.conf + sudo chown root:root /etc/nginx/sites-available/site.conf +else + echo.ICyan "site.conf already exists" +fi + +if [ ! -f /etc/nginx/conf.d/common_vars.conf ]; then + sudo cp $ROOT_DIR/config/nginx/common_vars.conf /etc/nginx/conf.d/common_vars.conf + sudo chown root:root /etc/nginx/conf.d/common_vars.conf +else + echo.ICyan "common_vars.conf already exists" +fi + +if [ ! -d /etc/nginx/mainsail/sites ]; then + sudo mkdir -p /etc/nginx/mainsail/sites +fi +if [ ! -d /etc/nginx/mainsail/upstream ]; then + sudo mkdir -p /etc/nginx/mainsail/upstream +fi +if [ ! -d /etc/nginx/mainsail/proxy ]; then + sudo mkdir -p /etc/nginx/mainsail/proxy +fi + +echo.Cyan "Generate and Install $PRINTER_NAME nginx configs" +cat $ROOT_DIR/config/nginx/mainsail-upstream.conf | replace "PRINTERNAMELC" "${PRINTER_NAME,,}" | replace "PORT" "$NEW_PORT" > $ROOT_DIR/$PRINTER_NAME/upstream.conf +PROXY_PORT=$((NEW_PORT - 7000 + 8000)) +cat $ROOT_DIR/config/nginx/mainsail-site.conf | replace "PRINTERNAMELC" "${PRINTER_NAME,,}" | replace "/home/pi" "$HOME" | replace "PRINTERNAME" "$PRINTER_NAME" | replace "PORT" "$PROXY_PORT" > $ROOT_DIR/$PRINTER_NAME/site.conf +cat $ROOT_DIR/config/nginx/mainsail-proxy.conf | replace "PRINTERNAMELC" "${PRINTER_NAME,,}" | replace "PORT" "$PROXY_PORT" > $ROOT_DIR/$PRINTER_NAME/proxy.conf +# add proxy +sudo cp $ROOT_DIR/$PRINTER_NAME/upstream.conf /etc/nginx/mainsail/upstream/$PRINTER_NAME.conf +sudo cp $ROOT_DIR/$PRINTER_NAME/site.conf /etc/nginx/sites-available/$PRINTER_NAME.conf +sudo cp $ROOT_DIR/$PRINTER_NAME/proxy.conf /etc/nginx/mainsail/proxy/$PRINTER_NAME.conf +sudo ln -s /etc/nginx/sites-available/$PRINTER_NAME.conf /etc/nginx/sites-enabled/$PRINTER_NAME.conf + +sudo chown -R root:root /etc/nginx/mainsail +if [ -f /etc/nginx/sites-enabled/site.conf ]; then + echo.ICyan "Restart nginx if the site is already enabled" + sudo systemctl stop nginx +fi # Setup klipper python env echo.Cyan "Setup Klipper Python Virtual Environment" @@ -189,3 +292,11 @@ for svc in ${SERVICES[@]}; do done # Cleanup +$HOME/$PRINTER_NAME/moonraker/scripts/set-policykit-rules.sh +echo.BoldCyan "${PRINTER_NAME} is setup with moonraker on port ${NEW_PORT}" +sudo nginx -t +if [ ! -f /etc/nginx/sites-enabled/site.conf ]; then + echo.Red "NGINX config not enabled, don't forget to symlink the site.conf file from sites-available to sites-enabled" +else + sudo systemctl start nginx +fi \ No newline at end of file