423 lines
11 KiB
Bash
423 lines
11 KiB
Bash
#!/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}"
|