Compare commits
2
Commits
f09bd6bb95
...
84e8f074e8
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
84e8f074e8 | ||
|
|
551df48687 |
@@ -91,7 +91,7 @@ Useful options (`iso/build-iso.sh --help` for all):
|
||||
|
||||
| Option | Effect |
|
||||
|---|---|
|
||||
| `--unattended` | First-boot install takes every default with no prompts (skips the Core Settings menu) and reboots into the kiosk. Set sites afterwards in the Web UI (`http://<ip>:8090`) or `./install.sh`. |
|
||||
| `--unattended` | First-boot install takes every default with no prompts (skips the Core Settings menu) and reboots into the kiosk. Set sites afterwards in the Web UI (`http://<ip>:8888`) or `./install.sh`. |
|
||||
| `--username NAME [--password PASS]` | Pre-set the admin account (password is prompted for if omitted; only a hash goes on the ISO). Not `kiosk`. |
|
||||
| `--hostname`, `--ssh-key FILE`, `--locale`, `--keyboard` | Pre-set those. |
|
||||
| `--auto-network` / `--auto-storage` | Skip the network screen (DHCP on ethernet) / wipe the largest disk without asking. |
|
||||
@@ -1585,7 +1585,7 @@ full migration pass.
|
||||
- **Fix:** the CUPS menu could report an installed CUPS as "not installed" (`dpkg -l | grep -q` failing under `set -o pipefail`).
|
||||
|
||||
**Previous (v2.17.0):**
|
||||
- **Web UI now installs by default** during first-time provisioning (fixed port 8090, no prompt) instead of being opt-in — the Addons menu entry still works standalone for reconfiguring the port or reinstalling it on a kiosk provisioned before this change.
|
||||
- **Web UI now installs by default** during first-time provisioning (port 8888 for new installs, 8090 on older ones; no prompt) instead of being opt-in — the Addons menu entry still works standalone for reconfiguring the port or reinstalling it on a kiosk provisioned before this change.
|
||||
- **The web UI can now install/reconfigure CUPS Printing, LMS Server, Squeezelite Player, and Asterisk Intercom, and check for updates** — the same four addons plus Update named directly. Every one of these is the exact same interactive `action_*` function the terminal menu already uses (no prompt/mutation refactor of any addon file), driven by piping the right answers on stdin — the same technique this project's own bash tests already use to drive these functions.
|
||||
- **Privilege model:** the web service itself still runs as `$KIOSK_USER` with zero ambient `sudo`. A new narrow, allow-listed root helper is the only way it ever gains privilege — reachable only via a single-path passwordless sudo rule (generated and validated with `visudo -c -f` before being installed), and it re-checks its own fixed action allow-list before dispatching anything. Chosen over running the whole service as root after asking directly: since this repo has no login of its own by design, a request that reaches the web UI with no reverse proxy in front is effectively unauthenticated, so the allow-list bounds what that can actually do to five vetted actions, never a root shell.
|
||||
- Long-running installs stream live output to the browser via Server-Sent Events, one action at a time — a second request while one is in flight gets a clear `409`, never silently queued or dropped.
|
||||
|
||||
+1
-1
@@ -18,7 +18,7 @@
|
||||
# ~/ubuntu-based-kiosk - interactively by default (same prompts as a
|
||||
# manual install), or with --unattended taking every default and
|
||||
# rebooting straight into the kiosk. Configure sites afterwards via
|
||||
# the Web UI (http://<ip>:8090) or ./install.sh.
|
||||
# the Web UI (http://<ip>:8888) or ./install.sh.
|
||||
#
|
||||
# Nothing in the original ISO is changed except /boot/grub/grub.cfg
|
||||
# (menu title, plus the `autoinstall` kernel argument with --no-confirm);
|
||||
|
||||
+15
-1
@@ -1226,6 +1226,19 @@ function historyHome(){
|
||||
markActivity();
|
||||
}
|
||||
|
||||
// Power menu -> Lock now: put up the lock screen right away (the same one
|
||||
// the inactivity timeout shows). Only when password protection is on and a
|
||||
// code is set - showLockoutScreen refuses otherwise, so a kiosk with no
|
||||
// code can't be locked with nothing to unlock it.
|
||||
function lockNow(){
|
||||
if(!enablePasswordProtection||!lockoutPassword){
|
||||
console.log('[LOCKOUT] Lock now ignored - password protection is off');
|
||||
return;
|
||||
}
|
||||
console.log('[LOCKOUT] Lock now requested from the power menu');
|
||||
showLockoutScreen('unlock');
|
||||
}
|
||||
|
||||
function showPinEntry(){
|
||||
if(pinWindow&&!pinWindow.isDestroyed()){
|
||||
pinWindow.focus();
|
||||
@@ -1545,7 +1558,7 @@ function showPowerMenu(){
|
||||
|
||||
// For normal mode, use custom overlay with 30-second timeout
|
||||
console.log('[POWER] Showing custom power menu overlay');
|
||||
const powerInfo={version:VERSION,localIP:localIP,vpnIP:vpnIP.trim()};
|
||||
const powerInfo={version:VERSION,localIP:localIP,vpnIP:vpnIP.trim(),canLock:!!(enablePasswordProtection&&lockoutPassword)};
|
||||
// Send to all views (preload.js runs in views, not mainWindow)
|
||||
for(const view of views){
|
||||
if(view&&view.webContents&&!view.webContents.isDestroyed()){
|
||||
@@ -1730,6 +1743,7 @@ async function createWindow(){
|
||||
if(action==='shutdown')exec('systemctl poweroff');
|
||||
else if(action==='restart')exec('systemctl reboot');
|
||||
else if(action==='reload'){app.relaunch();app.quit();}
|
||||
else if(action==='lock')lockNow();
|
||||
});
|
||||
ipcMain.on('toggle-hidden',toggleHidden);
|
||||
ipcMain.on('history-nav',(event,direction)=>{
|
||||
|
||||
@@ -666,6 +666,16 @@ window.addEventListener('DOMContentLoaded',()=>{
|
||||
ipcRenderer.send('power-action','reload');
|
||||
});
|
||||
|
||||
// Only offered when password protection is on (set in showPowerMenu).
|
||||
const lockBtn=document.createElement('button');
|
||||
lockBtn.id='power-menu-lock';
|
||||
lockBtn.textContent='🔒 Lock now';
|
||||
lockBtn.style.cssText=btnStyle+'background:#8e44ad;color:white;display:none;';
|
||||
lockBtn.addEventListener('click',()=>{
|
||||
hidePowerMenu();
|
||||
ipcRenderer.send('power-action','lock');
|
||||
});
|
||||
|
||||
const cancelBtn=document.createElement('button');
|
||||
cancelBtn.textContent='Cancel';
|
||||
cancelBtn.style.cssText=btnStyle+'background:#7f8c8d;color:white;';
|
||||
@@ -673,6 +683,7 @@ window.addEventListener('DOMContentLoaded',()=>{
|
||||
hidePowerMenu();
|
||||
});
|
||||
|
||||
buttonsDiv.appendChild(lockBtn);
|
||||
buttonsDiv.appendChild(shutdownBtn);
|
||||
buttonsDiv.appendChild(restartBtn);
|
||||
buttonsDiv.appendChild(reloadBtn);
|
||||
@@ -708,6 +719,8 @@ window.addEventListener('DOMContentLoaded',()=>{
|
||||
}
|
||||
infoDiv.innerHTML=infoText;
|
||||
}
|
||||
const lockBtn=document.getElementById('power-menu-lock');
|
||||
if(lockBtn)lockBtn.style.display=(info&&info.canLock)?'':'none';
|
||||
|
||||
powerMenu.style.display='flex';
|
||||
powerMenuVisible=true;
|
||||
|
||||
+1
-1
@@ -328,7 +328,7 @@ provision_configure_webui() {
|
||||
return 0
|
||||
fi
|
||||
|
||||
local port="8090"
|
||||
local port="8888"
|
||||
webui_write_env_file "$port"
|
||||
webui_write_unit_file
|
||||
webui_write_helper_script
|
||||
|
||||
@@ -59,9 +59,9 @@ webui_is_active() {
|
||||
|
||||
webui_port() {
|
||||
if sudo test -f "$WEBUI_ENV_DIR/webui.env" 2>/dev/null; then
|
||||
sudo grep -oP '^PORT=\K.*' "$WEBUI_ENV_DIR/webui.env" 2>/dev/null || echo "8090"
|
||||
sudo grep -oP '^PORT=\K.*' "$WEBUI_ENV_DIR/webui.env" 2>/dev/null || echo "8888"
|
||||
else
|
||||
echo "8090"
|
||||
echo "8888"
|
||||
fi
|
||||
}
|
||||
|
||||
@@ -281,7 +281,7 @@ action_webui_install() {
|
||||
ask_yes_no "Install the Web UI?" "n" || { echo "Cancelled"; return; }
|
||||
|
||||
local port
|
||||
port=$(ask_integer "Port to listen on" "8090" 1024 65535)
|
||||
port=$(ask_integer "Port to listen on" "8888" 1024 65535)
|
||||
|
||||
echo "Installing app files and npm dependencies..."
|
||||
if ! webui_install_app_files; then
|
||||
@@ -321,6 +321,8 @@ action_webui_reconfigure() {
|
||||
webui_write_env_file "$port"
|
||||
sudo systemctl restart kiosk-webui
|
||||
sudo ufw allow "${port}/tcp" comment 'Kiosk Web UI' 2>/dev/null || true
|
||||
# The old port is no longer used - close it.
|
||||
sudo ufw delete allow "${current_port}/tcp" 2>/dev/null || true
|
||||
log_success "Web UI now listening on port ${port}"
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -294,7 +294,7 @@ app.put('/api/region', (req, res) => {
|
||||
runRegionHelper('region-set', input, res);
|
||||
});
|
||||
|
||||
const PORT = process.env.PORT || 8090;
|
||||
const PORT = process.env.PORT || 8888;
|
||||
const BIND_ADDR = process.env.BIND_ADDR || '0.0.0.0';
|
||||
|
||||
if (require.main === module) {
|
||||
|
||||
Reference in New Issue
Block a user