#!/bin/sh # Exit immediately if a command exits with a non-zero status. # We disable this ('+e') temporarily during the nomodeset check. set -u # --- Color Definitions --- RED='\e[1;31m' BLU='\e[1;34m' GRN='\e[1;32m' YLW='\e[1;33m' DEF='\e[0m' # --- End Color Definitions --- # --- Configuration --- # Set the URL you want the signage to display KIOSK_URL="https://example.com" # Set the user account to run the signage under SIGNAGE_USER="signage" # WayVNC Configuration # SET THIS PASSWORD! If left blank, a default 'changeme' will be used, which is INSECURE. WAYVNC_PASSWORD_TO_SET="burek123" # Example: "your_secure_password" WAYVNC_USERNAME="signage_vnc" # Username for VNC authentication WAYVNC_LISTEN_ADDRESS="0.0.0.0" # Listen on all interfaces WAYVNC_PORT="5900" # Default VNC port # --- End Configuration --- # --- Step Counter --- TOTAL_STEPS=14 # Adjusted for new WayVNC config step CURRENT_STEP=0 log_step_message() { CURRENT_STEP=$((CURRENT_STEP + 1)) echo -e "${BLU}[Step $CURRENT_STEP/$TOTAL_STEPS] $1...${DEF}" } # --- End Step Counter --- echo -e "${BLU}Starting Alpine Linux Signage Setup (Using Sway, greetd, WayVNC)...${DEF}" echo -e "${BLU}Target URL: ${GRN}$KIOSK_URL${DEF}" echo -e "${BLU}Signage User: ${GRN}$SIGNAGE_USER${DEF}" echo -e "${BLU}WayVNC will listen on: ${GRN}$WAYVNC_LISTEN_ADDRESS:$WAYVNC_PORT${DEF}" if [ -z "$WAYVNC_PASSWORD_TO_SET" ]; then echo -e "${RED}WARNING: WAYVNC_PASSWORD_TO_SET is empty. A default insecure password 'changeme' will be used.${DEF}" WAYVNC_PASSWORD_TO_SET="changeme" fi echo "-------------------------------------" # 1. Check if running as root if [ "$(id -u)" -ne 0 ]; then echo -e "${RED}ERROR: This script must be run as root${DEF}" 1>&2 exit 1 fi # 2. Check for 'nomodeset' kernel parameter set +e KERNEL_CMDLINE=$(cat /proc/cmdline) log_step_message "Checking kernel command line for 'nomodeset'" echo "Command line: $KERNEL_CMDLINE" if echo "$KERNEL_CMDLINE" | grep -q -w 'nomodeset'; then echo -e "${RED}!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!${DEF}" echo -e "${RED}!! ${YLW}WARNING: 'nomodeset' detected! Wayland (Sway) will likely NOT work. ${RED}!!${DEF}" echo -e "${RED}!! ${YLW}Remove 'nomodeset' from your bootloader config and reboot. ${RED}!!${DEF}" echo -e "${RED}!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!${DEF}" else echo -e "${GRN}'nomodeset' not found. Proceeding...${DEF}" fi set -e echo "-------------------------------------" # 3. Update repositories log_step_message "Updating package repositories" apk update echo "-------------------------------------" # 4. Setup base Wayland environment log_step_message "Setting up base Wayland environment (elogind, eudev)" apk add --no-cache alpine-conf setup-wayland-base echo -e "${GRN}Base Wayland environment setup complete.${DEF}" echo "-------------------------------------" # 5. Install necessary packages (openssl added) log_step_message "Installing core packages (Sway, Chromium, Greetd, WayVNC, openssl etc.)" apk add \ sway \ swayidle \ swaybg \ wl-clipboard \ xwayland \ chromium \ mesa-dri-gallium \ mesa-va-gallium \ mesa-egl \ dbus \ font-dejavu \ ttf-freefont \ util-linux \ linux-firmware \ greetd \ greetd-agreety \ wayvnc \ openssl # Added for key generation echo -e "${GRN}Required packages installed.${DEF}" echo "-------------------------------------" # 6. D-Bus service log_step_message "Enabling and starting D-Bus service" if ! rc-service dbus status > /dev/null 2>&1; then rc-update add dbus default rc-service dbus start echo -e "${GRN}D-Bus service enabled and started.${DEF}" else echo -e "${GRN}D-Bus service already running or enabled.${DEF}" fi echo "-------------------------------------" # 7. open-vm-tools service log_step_message "Enabling and starting open-vm-tools service" if apk info --installed open-vm-tools > /dev/null 2>&1; then if ! rc-service open-vm-tools status > /dev/null 2>&1; then rc-update add open-vm-tools default rc-service open-vm-tools start echo -e "${GRN}open-vm-tools service enabled and started.${DEF}" else echo -e "${GRN}open-vm-tools service already running or enabled.${DEF}" fi else echo -e "${YLW}open-vm-tools not installed, skipping service setup.${DEF}" fi echo "-------------------------------------" # 8. Create signage user and groups log_step_message "Creating signage user '$SIGNAGE_USER' and configuring groups" if ! id -u "$SIGNAGE_USER" >/dev/null 2>&1; then addgroup "$SIGNAGE_USER" adduser -D -G "$SIGNAGE_USER" -s /bin/sh -h "/home/$SIGNAGE_USER" "$SIGNAGE_USER" addgroup "$SIGNAGE_USER" video addgroup "$SIGNAGE_USER" input echo -e "${GRN}User '$SIGNAGE_USER' created and added to video/input groups.${DEF}" else echo -e "${YLW}User '$SIGNAGE_USER' already exists. Ensuring shell and groups...${DEF}" usermod -s /bin/sh "$SIGNAGE_USER" if ! getent group "$SIGNAGE_USER" >/dev/null 2>&1; then addgroup "$SIGNAGE_USER"; if ! groups "$SIGNAGE_USER" | grep -q -w "$SIGNAGE_USER"; then addgroup "$SIGNAGE_USER" "$SIGNAGE_USER"; fi; fi if ! groups "$SIGNAGE_USER" | grep -q -w video; then addgroup "$SIGNAGE_USER" video; echo -e "${GRN}Added $SIGNAGE_USER to video.${DEF}"; else echo -e "${GRN}$SIGNAGE_USER already in video.${DEF}"; fi if ! groups "$SIGNAGE_USER" | grep -q -w input; then addgroup "$SIGNAGE_USER" input; echo -e "${GRN}Added $SIGNAGE_USER to input.${DEF}"; else echo -e "${GRN}$SIGNAGE_USER already in input.${DEF}"; fi fi SIGNAGE_HOME="/home/$SIGNAGE_USER" mkdir -p "$SIGNAGE_HOME/.local/share/sway" chown -R "$SIGNAGE_USER:$SIGNAGE_USER" "$SIGNAGE_HOME" chmod 750 "$SIGNAGE_HOME" chmod -R 700 "$SIGNAGE_HOME/.local" echo -e "${GRN}User home directory configured.${DEF}" echo "-------------------------------------" # 9. Configure user's .profile (WayVNC password not needed here anymore) log_step_message "Configuring $SIGNAGE_HOME/.profile for $SIGNAGE_USER" SIGNAGE_PROFILE="$SIGNAGE_HOME/.profile" cat > "$SIGNAGE_PROFILE" << EOF # Profile for $SIGNAGE_USER executed by /bin/sh on login # --- Other Environment Variables (optional) --- # export XDG_CURRENT_DESKTOP=sway # export MOZ_ENABLE_WAYLAND=1 # export QT_QPA_PLATFORM=wayland EOF chown "$SIGNAGE_USER:$SIGNAGE_USER" "$SIGNAGE_PROFILE" chmod 600 "$SIGNAGE_PROFILE" echo -e "${GRN}$SIGNAGE_PROFILE configured.${DEF}" echo "-------------------------------------" # 10. Configure WayVNC with authentication log_step_message "Configuring WayVNC with authentication" SIGNAGE_CONFIG_DIR="$SIGNAGE_HOME/.config" WAYVNC_CONFIG_DIR="$SIGNAGE_CONFIG_DIR/wayvnc" WAYVNC_KEYS_DIR="$WAYVNC_CONFIG_DIR/keys" WAYVNC_CONFIG_FILE="$WAYVNC_CONFIG_DIR/config" mkdir -p "$WAYVNC_KEYS_DIR" chown -R "$SIGNAGE_USER:$SIGNAGE_USER" "$SIGNAGE_CONFIG_DIR" || true # In case .config already existed chmod 700 "$SIGNAGE_CONFIG_DIR" chmod 700 "$WAYVNC_CONFIG_DIR" chmod 700 "$WAYVNC_KEYS_DIR" # Generate self-signed cert and keys if they don't exist TLS_KEY_FILE="$WAYVNC_KEYS_DIR/tls_key.pem" TLS_CERT_FILE="$WAYVNC_KEYS_DIR/tls_cert.pem" # WayVNC also supports rsa_private_key_file for RSA-AES, we'll use TLS for simplicity here. # If you need RSA-AES, you'd generate an RSA key: openssl genrsa -out "$WAYVNC_KEYS_DIR/rsa_key.pem" 2048 if [ ! -f "$TLS_KEY_FILE" ] || [ ! -f "$TLS_CERT_FILE" ]; then echo -e "${BLU}Generating self-signed TLS certificate and key for WayVNC...${DEF}" # Run as signage user to ensure correct ownership from the start su - "$SIGNAGE_USER" -c "openssl genpkey -algorithm RSA -out \"$TLS_KEY_FILE\" -pkeyopt rsa_keygen_bits:2048" su - "$SIGNAGE_USER" -c "openssl req -new -key \"$TLS_KEY_FILE\" -out \"$WAYVNC_KEYS_DIR/tls_csr.pem\" -subj \"/CN=localhost/O=Kiosk/OU=Signage\"" su - "$SIGNAGE_USER" -c "openssl x509 -req -days 3650 -in \"$WAYVNC_KEYS_DIR/tls_csr.pem\" -signkey \"$TLS_KEY_FILE\" -out \"$TLS_CERT_FILE\"" rm -f "$WAYVNC_KEYS_DIR/tls_csr.pem" # Clean up CSR echo -e "${GRN}TLS certificate and key generated.${DEF}" else echo -e "${GRN}WayVNC TLS certificate and key already exist.${DEF}" fi # Create WayVNC config file cat > "$WAYVNC_CONFIG_FILE" << EOF # WayVNC configuration for signage kiosk address=$WAYVNC_LISTEN_ADDRESS port=$WAYVNC_PORT enable_auth=true username=$WAYVNC_USERNAME password=$WAYVNC_PASSWORD_TO_SET # For TLS encryption (recommended) private_key_file=$TLS_KEY_FILE certificate_file=$TLS_CERT_FILE # Optional: If you generated an RSA key for RSA-AES (some clients might prefer) # rsa_private_key_file=$WAYVNC_KEYS_DIR/rsa_key.pem # Optional: Relax encryption requirements (can be less secure, for compatibility) # relax_encryption=true # Optional: Keyboard layout settings # xkb_layout=us EOF chown "$SIGNAGE_USER:$SIGNAGE_USER" "$WAYVNC_CONFIG_FILE" chmod 600 "$WAYVNC_CONFIG_FILE" chmod 400 "$TLS_KEY_FILE" # Restrict private key readability chmod 644 "$TLS_CERT_FILE" echo -e "${GRN}WayVNC configuration file created at $WAYVNC_CONFIG_FILE with authentication enabled.${DEF}" if [ "$WAYVNC_PASSWORD_TO_SET" = "changeme" ]; then echo -e "${RED}CRITICAL: WayVNC password is set to 'changeme'. This is INSECURE. Change WAYVNC_PASSWORD_TO_SET in the script and re-run, or manually edit $WAYVNC_CONFIG_FILE.${DEF}" fi echo "-------------------------------------" # 11. Configure Sway log_step_message "Configuring Sway" SIGNAGE_SWAY_CONFIG_DIR="$SIGNAGE_CONFIG_DIR/sway" # .config already handled SIGNAGE_SWAY_CONFIG_FILE="$SIGNAGE_SWAY_CONFIG_DIR/config" mkdir -p "$SIGNAGE_SWAY_CONFIG_DIR" # Ensure sway dir exists under .config chown -R "$SIGNAGE_USER:$SIGNAGE_USER" "$SIGNAGE_SWAY_CONFIG_DIR" chmod 700 "$SIGNAGE_SWAY_CONFIG_DIR" cat > "$SIGNAGE_SWAY_CONFIG_FILE" << EOF # Sway configuration for Alpine Signage Kiosk set \$mod Mod4 font pango:DejaVu Sans Mono 10 output * enable output * power on seat * hide_cursor 1000 exec /usr/bin/chromium \\ --enable-features=UseOzonePlatform \\ --ozone-platform=wayland \\ --kiosk \\ --no-first-run \\ --disable-infobars \\ --disable-session-crashed-bubble \\ --disable-component-update \\ --disable-pinch \\ --app=$KIOSK_URL \\ --no-sandbox \\ --password-store=basic \\ --enable-zero-copy \\ --ignore-gpu-blocklist \\ --disable-gpu # WayVNC will now use its own config file for auth exec wayvnc --render-cursor # Address/port are now in its config file bindsym \$mod+Shift+q kill bindsym \$mod+Shift+c reload bindsym \$mod+Shift+e exec swaynag -t warning -m 'You pressed the exit shortcut. Do you really want to exit sway? This will end the kiosk session.' -B 'Yes, exit sway' 'swaymsg exit' focus_follows_mouse no mouse_warping output EOF chown "$SIGNAGE_USER:$SIGNAGE_USER" "$SIGNAGE_SWAY_CONFIG_FILE" chmod 600 "$SIGNAGE_SWAY_CONFIG_FILE" echo -e "${GRN}Sway configuration file written to $SIGNAGE_SWAY_CONFIG_FILE.${DEF}" echo "-------------------------------------" # 12. Configure greetd log_step_message "Configuring greetd" GREETD_CONFIG_DIR="/etc/greetd" GREETD_CONFIG_FILE="$GREETD_CONFIG_DIR/config.toml" mkdir -p "$GREETD_CONFIG_DIR" SWAY_LOG_PATH_IN_GREETD="$SIGNAGE_HOME/.local/share/sway/sway-greetd.log" cat > "$GREETD_CONFIG_FILE" << EOF [terminal] vt = 1 [default_session] user = "$SIGNAGE_USER" command = "/usr/bin/dbus-run-session /usr/bin/sway -V -d 2> $SWAY_LOG_PATH_IN_GREETD" EOF chmod 644 "$GREETD_CONFIG_FILE" echo -e "${GRN}greetd config written to $GREETD_CONFIG_FILE.${DEF}" echo "-------------------------------------" # 13. Configure inittab log_step_message "Configuring autologin via greetd in /etc/inittab" if [ -f "/etc/inittab" ]; then if [ ! -f "/etc/inittab.bak.signage" ]; then cp /etc/inittab /etc/inittab.bak.signage; echo -e "${GRN}Backed up /etc/inittab.${DEF}"; fi sed -i -e '/^tty[2-6]:/s/^/#/' /etc/inittab GREETD_INITTAB_LINE="tty1::respawn:/usr/sbin/greetd" if grep -q "^tty1::respawn:" /etc/inittab && ! grep -Fxq "$GREETD_INITTAB_LINE" /etc/inittab; then sed -i "s|^tty1::respawn:.*|$GREETD_INITTAB_LINE|" /etc/inittab echo -e "${GRN}tty1 entry modified for greetd.${DEF}" elif ! grep -Fxq "$GREETD_INITTAB_LINE" /etc/inittab; then echo "$GREETD_INITTAB_LINE" >> /etc/inittab; echo -e "${GRN}Added greetd line to /etc/inittab.${DEF}" else echo -e "${GRN}greetd line already in /etc/inittab.${DEF}"; fi else echo -e "${RED}Warning: /etc/inittab not found.${DEF}"; fi echo "-------------------------------------" # 14. Configure PAM log_step_message "Attempting to configure PAM for elogind session" PAM_TARGET_FILE="" if [ -f "/etc/pam.d/greetd" ]; then PAM_TARGET_FILE="/etc/pam.d/greetd"; \ elif [ -f "/etc/pam.d/system-login" ]; then PAM_TARGET_FILE="/etc/pam.d/system-login"; \ elif [ -f "/etc/pam.d/system-auth" ]; then PAM_TARGET_FILE="/etc/pam.d/system-auth"; fi if [ -n "$PAM_TARGET_FILE" ]; then echo -e "${BLU}Using $PAM_TARGET_FILE for PAM.${DEF}" if ! grep -q "pam_elogind.so" "$PAM_TARGET_FILE"; then if [ ! -f "$PAM_TARGET_FILE.bak.signage" ]; then cp "$PAM_TARGET_FILE" "$PAM_TARGET_FILE.bak.signage"; echo -e "${GRN}Backed up $PAM_TARGET_FILE.${DEF}"; fi if grep -q "^session" "$PAM_TARGET_FILE"; then awk '/^session/{if(!p++) print; print "session optional pam_elogind.so"; next} 1' "$PAM_TARGET_FILE" > "$PAM_TARGET_FILE.tmp" && mv "$PAM_TARGET_FILE.tmp" "$PAM_TARGET_FILE" else echo "session optional pam_elogind.so" >> "$PAM_TARGET_FILE"; fi echo -e "${GRN}pam_elogind.so added to PAM config.${DEF}" else echo -e "${GRN}pam_elogind.so already in PAM config.${DEF}"; fi else echo -e "${RED}Warning: Could not find suitable PAM file to modify.${DEF}"; fi echo "-------------------------------------" # --- Final Summary --- echo -e "${BLU}[Step $((CURRENT_STEP +1))/$TOTAL_STEPS] Final checks and information (this is not an actual step increment).${DEF}" CURRENT_STEP=$TOTAL_STEPS # Ensure counter matches total for summary echo -e "${GRN}-----------------------------------------------------${DEF}" echo -e "${GRN} Alpine Linux Signage Setup Script Finished! ${DEF}" echo -e "${GRN}-----------------------------------------------------${DEF}" echo -e "${BLU} SUMMARY:${DEF}" echo -e " ${GRN}* User '$SIGNAGE_USER' created, added to 'video'/'input' groups.${DEF}" echo -e " ${GRN}* WayVNC configured with authentication (user: ${YLW}$WAYVNC_USERNAME${GRN}, pass: ${YLW}${WAYVNC_PASSWORD_TO_SET}${GRN}). Config: ${YLW}$WAYVNC_CONFIG_FILE${DEF}" echo -e " ${YLW} Self-signed TLS certs generated in ${WAYVNC_KEYS_DIR}. You may need to accept these in your VNC client.${DEF}" if [ "$WAYVNC_PASSWORD_TO_SET" = "changeme" ]; then echo -e " ${RED}CRITICAL: WayVNC password is 'changeme'. THIS IS INSECURE!${DEF}" fi echo -e " ${GRN}* Sway configured to launch Chromium Kiosk and WayVNC.${DEF}" echo -e " ${GRN}* Autologin via greetd and inittab configured.${DEF}" echo "" echo -e "${RED} !!! IMPORTANT !!!${DEF}" echo -e " ${RED}* If 'nomodeset' warning appeared, graphical kiosk WILL NOT WORK until fixed.${DEF}" echo -e " ${YLW}* Connect to VNC using user: ${GRN}$WAYVNC_USERNAME${YLW} and password: ${GRN}YOUR_SET_PASSWORD${DEF}" echo -e " ${YLW}The VNC server is listening on ${GRN}$WAYVNC_LISTEN_ADDRESS:$WAYVNC_PORT${DEF}" echo -e "${RED}!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!${DEF}" echo "" echo -e "${GRN} Please REBOOT the system for changes to take effect.${DEF}" echo -e "${GRN} Command: ${YLW}reboot${DEF}" echo "" echo -e "${BLU} TROUBLESHOOTING AFTER REBOOT:${DEF}" echo -e " ${BLU}1. Check user groups: ${GRN}groups $SIGNAGE_USER${YLW} (should include 'video', 'input')${DEF}" echo -e " ${BLU}2. Check Sway log: ${GRN}cat $SWAY_LOG_PATH_IN_GREETD${DEF}" echo -e " ${BLU}3. Check WayVNC config: ${GRN}cat $WAYVNC_CONFIG_FILE${DEF}" echo -e " ${BLU}4. Check WayVNC running: ${GRN}ps aux | grep wayvnc ; netstat -tulnp | grep :$WAYVNC_PORT${DEF}" echo -e " ${BLU}5. Manually test WayVNC (as $SIGNAGE_USER on TTY2, after stopping greetd & starting sway):${DEF}" echo -e " ${GRN}wayvnc${DEF}" echo -e "${GRN}-----------------------------------------------------${DEF}" exit 0