#!/bin/bash # OpenWall Dashboard Installer for Debian # Installs and configures the dashboard app for touch displays with 9:16 ratio # Supports Wayland session with auto-start set -e # Colors for output RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' NC='\033[0m' # No Color # Configuration APP_USER="openwall" APP_DIR="/opt/openwall" DISPLAY_WIDTH="1080" DISPLAY_HEIGHT="1920" SERVICE_NAME="openwall-dashboard" echo -e "${BLUE}OpenWall Dashboard Installer${NC}" echo -e "${BLUE}==============================${NC}" # Check if running as root if [[ $EUID -ne 0 ]]; then echo -e "${RED}This script must be run as root${NC}" exit 1 fi # Update system echo -e "${YELLOW}Updating system packages...${NC}" apt update && apt upgrade -y # Install required packages echo -e "${YELLOW}Installing required packages...${NC}" apt install -y \ curl \ wget \ git \ build-essential \ python3 \ python3-pip \ nodejs \ npm \ wayland-protocols \ wayland-utils \ weston \ sway \ swaylock \ swayidle \ xwayland \ libdrm2 \ libinput-tools \ udev \ systemd \ xinput \ x11-xserver-utils \ mesa-utils \ vulkan-tools \ libgl1-mesa-dri \ libgles2-mesa \ libegl1-mesa \ firefox-esr \ chromium \ fonts-liberation \ fonts-dejavu-core \ unclutter \ xdotool # Install Node.js LTS echo -e "${YELLOW}Installing Node.js LTS...${NC}" curl -fsSL https://deb.nodesource.com/setup_lts.x | bash - apt install -y nodejs # Install pnpm echo -e "${YELLOW}Installing pnpm...${NC}" npm install -g pnpm # Create application user echo -e "${YELLOW}Creating application user...${NC}" if ! id "$APP_USER" &>/dev/null; then useradd -m -s /bin/bash "$APP_USER" usermod -aG video,input,audio "$APP_USER" fi # Create application directory echo -e "${YELLOW}Setting up application directory...${NC}" mkdir -p "$APP_DIR" chown "$APP_USER:$APP_USER" "$APP_DIR" # Copy application files echo -e "${YELLOW}Installing application files...${NC}" if [ -d "$(dirname "$0")/../dashboard" ]; then cp -r "$(dirname "$0")/../dashboard/"* "$APP_DIR/" cp -r "$(dirname "$0")/../server" "$APP_DIR/" chown -R "$APP_USER:$APP_USER" "$APP_DIR" else echo -e "${RED}Dashboard directory not found. Please run this script from the OpenWall project root.${NC}" exit 1 fi # Install application dependencies echo -e "${YELLOW}Installing application dependencies...${NC}" cd "$APP_DIR" sudo -u "$APP_USER" pnpm install # Install server dependencies cd "$APP_DIR/server" sudo -u "$APP_USER" npm install # Create Wayland session configuration echo -e "${YELLOW}Configuring Wayland session...${NC}" cat > /usr/share/wayland-sessions/openwall.desktop << EOF [Desktop Entry] Name=OpenWall Dashboard Comment=OpenWall Touch Dashboard Session Exec=/opt/openwall/start-session.sh Type=Application DesktopNames=openwall EOF # Create session start script cat > "$APP_DIR/start-session.sh" << 'EOF' #!/bin/bash # OpenWall Dashboard Session Starter export XDG_RUNTIME_DIR="/run/user/$(id -u)" export XDG_SESSION_TYPE=wayland export XDG_CURRENT_DESKTOP=openwall export QT_QPA_PLATFORM=wayland export GDK_BACKEND=wayland export MOZ_ENABLE_WAYLAND=1 # Start Wayland compositor (Sway) exec sway --config /opt/openwall/sway-config EOF chmod +x "$APP_DIR/start-session.sh" # Create Sway configuration for dashboard cat > "$APP_DIR/sway-config" << EOF # OpenWall Dashboard Sway Configuration # Optimized for touch displays with 9:16 ratio # Set display configuration output * { mode ${DISPLAY_WIDTH}x${DISPLAY_HEIGHT}@60Hz scale 1 transform normal bg #000000 solid_color } # Input configuration for touch input type:touch { events enabled tap enabled natural_scroll enabled dwt disabled } # Input configuration for touchpad input type:touchpad { events enabled tap enabled natural_scroll enabled dwt enabled accel_profile adaptive pointer_accel 0.3 } # Disable window decorations and gaps default_border none default_floating_border none gaps inner 0 gaps outer 0 # Hide cursor after 3 seconds seat * hide_cursor 3000 # Disable screen timeout exec swayidle timeout 0 '' before-sleep 'true' # Start the dashboard application exec /opt/openwall/start-dashboard.sh EOF # Create dashboard start script cat > "$APP_DIR/start-dashboard.sh" << 'EOF' #!/bin/bash # Start the backend server cd /opt/openwall/server node index.js & # Wait for server to start sleep 3 # Start the dashboard in fullscreen cd /opt/openwall pnpm run electron -- --kiosk --touch-events --disable-pinch --overscroll-history-navigation=0 --disable-features=TranslateUI EOF chmod +x "$APP_DIR/start-dashboard.sh" # Update Electron main process for kiosk mode cat > "$APP_DIR/src/main/index.js" << 'EOF' import { app, shell, BrowserWindow, screen } from 'electron' import { join } from 'path' import { electronApp, optimizer, is } from '@electron-toolkit/utils' import icon from '../../resources/icon.png?asset' function createWindow() { // Get the primary display const primaryDisplay = screen.getPrimaryDisplay() const { width, height } = primaryDisplay.workAreaSize // Create the browser window in kiosk mode for touch displays const mainWindow = new BrowserWindow({ width: width, height: height, show: false, fullscreen: true, kiosk: true, frame: false, autoHideMenuBar: true, webPreferences: { preload: join(__dirname, '../preload/index.js'), sandbox: false, nodeIntegration: false, contextIsolation: true, webSecurity: false } }) // Disable zoom and context menu for touch interface mainWindow.webContents.on('before-input-event', (event, input) => { if (input.control && (input.key === '+' || input.key === '-' || input.key === '=')) { event.preventDefault() } }) mainWindow.webContents.on('context-menu', (event) => { event.preventDefault() }) mainWindow.on('ready-to-show', () => { mainWindow.show() mainWindow.setFullScreen(true) }) mainWindow.webContents.setWindowOpenHandler((details) => { shell.openExternal(details.url) return { action: 'deny' } }) // Load the app if (is.dev && process.env['ELECTRON_RENDERER_URL']) { mainWindow.loadURL(process.env['ELECTRON_RENDERER_URL']) } else { mainWindow.loadFile(join(__dirname, '../renderer/index.html')) } } app.whenReady().then(() => { electronApp.setAppUserModelId('com.openwall.dashboard') app.on('browser-window-created', (_, window) => { optimizer.watchWindowShortcuts(window) }) createWindow() app.on('activate', function () { if (BrowserWindow.getAllWindows().length === 0) createWindow() }) }) app.on('window-all-closed', () => { if (process.platform !== 'darwin') app.quit() }) EOF # Create systemd service for auto-start echo -e "${YELLOW}Creating systemd service...${NC}" cat > "/etc/systemd/system/${SERVICE_NAME}.service" << EOF [Unit] Description=OpenWall Dashboard Service After=graphical-session.target Wants=graphical-session.target [Service] Type=simple User=${APP_USER} Group=${APP_USER} WorkingDirectory=${APP_DIR} Environment=HOME=/home/${APP_USER} Environment=XDG_RUNTIME_DIR=/run/user/1001 ExecStart=${APP_DIR}/start-dashboard.sh Restart=always RestartSec=10 [Install] WantedBy=graphical-session.target EOF # Create udev rules for touch input echo -e "${YELLOW}Configuring touch input...${NC}" cat > /etc/udev/rules.d/99-openwall-touch.rules << 'EOF' # OpenWall touch input configuration SUBSYSTEM=="input", ATTRS{name}=="*touch*", ENV{LIBINPUT_CALIBRATION_MATRIX}="1 0 0 0 1 0" SUBSYSTEM=="input", ATTRS{name}=="*Touch*", ENV{LIBINPUT_CALIBRATION_MATRIX}="1 0 0 0 1 0" EOF # Configure X11 display settings (fallback) echo -e "${YELLOW}Configuring display settings...${NC}" cat > /etc/X11/xorg.conf.d/99-openwall-display.conf << EOF Section "Monitor" Identifier "HDMI-1" Option "PreferredMode" "${DISPLAY_WIDTH}x${DISPLAY_HEIGHT}" Option "Position" "0 0" Option "Rotate" "normal" EndSection Section "Screen" Identifier "Default Screen" Monitor "HDMI-1" DefaultDepth 24 SubSection "Display" Depth 24 Modes "${DISPLAY_WIDTH}x${DISPLAY_HEIGHT}" EndSubSection EndSection EOF # Create auto-login configuration echo -e "${YELLOW}Configuring auto-login...${NC}" mkdir -p /etc/systemd/system/getty@tty1.service.d cat > /etc/systemd/system/getty@tty1.service.d/override.conf << EOF [Service] ExecStart= ExecStart=-/sbin/agetty --autologin ${APP_USER} --noclear %I \$TERM EOF # Configure user session to start Wayland echo -e "${YELLOW}Configuring user session...${NC}" mkdir -p "/home/${APP_USER}/.config/systemd/user" cat > "/home/${APP_USER}/.config/systemd/user/openwall-session.service" << EOF [Unit] Description=OpenWall Dashboard Session After=graphical-session.target [Service] Type=exec ExecStart=/opt/openwall/start-session.sh Restart=always RestartSec=5 [Install] WantedBy=default.target EOF # Set up user environment cat > "/home/${APP_USER}/.profile" << 'EOF' # OpenWall Dashboard Environment export XDG_SESSION_TYPE=wayland export XDG_CURRENT_DESKTOP=openwall export QT_QPA_PLATFORM=wayland export GDK_BACKEND=wayland export MOZ_ENABLE_WAYLAND=1 # Auto-start Wayland session on login if [ -z "$DISPLAY" ] && [ "$XDG_VTNR" = "1" ]; then exec /opt/openwall/start-session.sh fi EOF chown -R "${APP_USER}:${APP_USER}" "/home/${APP_USER}" # Enable services echo -e "${YELLOW}Enabling services...${NC}" systemctl daemon-reload systemctl enable "${SERVICE_NAME}.service" # Enable user service sudo -u "$APP_USER" systemctl --user enable openwall-session.service # Build the application echo -e "${YELLOW}Building application...${NC}" cd "$APP_DIR" sudo -u "$APP_USER" pnpm run build # Set file permissions chown -R "$APP_USER:$APP_USER" "$APP_DIR" chmod +x "$APP_DIR"/*.sh # Reload udev rules udevadm control --reload-rules udevadm trigger echo -e "${GREEN}Installation completed successfully!${NC}" echo -e "${GREEN}==============================${NC}" echo "" echo -e "${BLUE}Installation Summary:${NC}" echo -e "• Application installed to: ${APP_DIR}" echo -e "• User created: ${APP_USER}" echo -e "• Display configured for: ${DISPLAY_WIDTH}x${DISPLAY_HEIGHT} (9:16 ratio)" echo -e "• Wayland session: openwall" echo -e "• Service: ${SERVICE_NAME}" echo "" echo -e "${YELLOW}Next steps:${NC}" echo -e "1. Reboot the system: ${BLUE}reboot${NC}" echo -e "2. The dashboard will start automatically on boot" echo -e "3. Access the dashboard at the configured display" echo "" echo -e "${YELLOW}Manual control:${NC}" echo -e "• Start service: ${BLUE}systemctl start ${SERVICE_NAME}${NC}" echo -e "• Stop service: ${BLUE}systemctl stop ${SERVICE_NAME}${NC}" echo -e "• View logs: ${BLUE}journalctl -u ${SERVICE_NAME} -f${NC}" echo "" echo -e "${GREEN}Reboot now to start the OpenWall Dashboard!${NC}"