diff --git a/CHANGELOG.md b/CHANGELOG.md
deleted file mode 100644
index 2d563e0..0000000
--- a/CHANGELOG.md
+++ /dev/null
@@ -1,65 +0,0 @@
-# Changelog
-
-All notable changes to this project will be documented in this file.
-
----
-
-## [0.4.0] - 2026-03-18
-
-### Added
-
-* Structured logging system with timestamps
-* Log levels: INFO, OK, ERR
-* Central log file: `/opt/update-manager/log/update-manager.log`
-* Log submenu in UI
-* Log viewing options:
-
- * Full log
- * Live log (tail -f)
- * Last 20 lines
- * Log file location
-
-### Changed
-
-* Refactored UI to group log features into submenu
-* Improved menu structure and usability
-
-### Improved
-
-* Better error visibility for SSH failures
-* Consistent output across hosts
-* README updated with UI screenshots and logging documentation
-
----
-
-## [0.3.0] - 2026-03-18
-
-### Added
-
-* CLI menu (`update-manager-ui.sh`)
-* Interactive host management
-* Dialog-based UI navigation
-
-### Changed
-
-* Project renamed from `lanx-update` to `update-manager`
-* Moved runtime files to `/opt/update-manager`
-
----
-
-## [0.2.0] - 2026-03-18
-
-### Added
-
-* SSH-based update checking across multiple hosts
-* Support for `hosts.conf`
-* Config file support (`/etc/update-manager.conf`)
-
----
-
-## [0.1.0] - 2026-03-17
-
-### Added
-
-* Initial version
-* Basic apt update check functionality
diff --git a/README.md b/README.md
index dc3900b..36fcbfb 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,4 @@
-
-
-
-
+# 🖥️ Update Manager
Simple CLI tool to check and manage updates across multiple Ubuntu systems over SSH.
@@ -29,10 +26,10 @@ Built for Lanx environments – lightweight, fast and no unnecessary dependencie
## Features
* Check updates on multiple hosts
-* Run updates remotely over SSH
-* Interactive CLI menu (dialog-based UI)
-* Centralized logging
+* Run checks remotely over SSH
* Simple config files
+* Built-in logging (file + terminal)
+* Dialog-based UI menu
* No agents required
* Works with existing SSH setup
@@ -40,20 +37,12 @@ Built for Lanx environments – lightweight, fast and no unnecessary dependencie
## Update Manager UI
-### Main menu
-
-
-
-
-### Log menu
-
-
-
+
- Lightweight • No dependencies • Works over SSH
+ Lightweight • Terminal-based • Works over SSH
---
@@ -68,7 +57,7 @@ sudo apt update
sudo apt install dialog openssh-client
sudo mkdir -p /opt/update-manager
-sudo cp update-manager.sh update-manager-ui.sh dialogrc /opt/update-manager/
+sudo cp update-manager.sh update-manager-ui.sh /opt/update-manager/
sudo chmod +x /opt/update-manager/update-manager.sh
sudo chmod +x /opt/update-manager/update-manager-ui.sh
@@ -145,12 +134,6 @@ server3 192.168.1.30 user
## Usage
-### Check updates
-
-```bash
-update-manager check
-```
-
### Start UI
```bash
@@ -159,25 +142,42 @@ update-manager-ui
---
+### Check updates (CLI)
+
+```bash
+update-manager check
+```
+
+---
+
## Logging
-Log file location:
+The tool logs both to terminal and file.
+
+### Primary location
```bash
/opt/update-manager/log/update-manager.log
```
-View log:
+### Fallback location
```bash
-less /opt/update-manager/log/update-manager.log
+~/update-manager/log/update-manager.log
```
-Follow log:
+### Notes
-```bash
-tail -f /opt/update-manager/log/update-manager.log
-```
+* Log directory is created automatically
+* Log file is created automatically
+* Output is written to both terminal and file
+* Log levels:
+
+ * INFO
+ * WARN
+ * ERROR
+
+Logs can be viewed directly from the UI.
---
@@ -189,8 +189,8 @@ tail -f /opt/update-manager/log/update-manager.log
├── update-manager-ui.sh
├── update-manager.conf
├── hosts.conf
-├── log/
-│ └── update-manager.log
+└── log/
+ └── update-manager.log
```
---
@@ -199,7 +199,6 @@ tail -f /opt/update-manager/log/update-manager.log
* Uses SSH to connect to each host
* Runs `apt` commands remotely
-* Logs results locally
* No agents or services needed
* Designed for simple and efficient operations
@@ -210,6 +209,7 @@ tail -f /opt/update-manager/log/update-manager.log
* SSH access to all hosts
* SSH keys recommended (no password prompts)
* Ubuntu/Debian-based systems
+* `dialog` (for UI)
---
@@ -218,6 +218,7 @@ tail -f /opt/update-manager/log/update-manager.log
* 🔔 Notifications (ntfy / push alerts)
* 🌐 Web interface
* 📧 Email reporting
+* 📜 Advanced logging / audit trail
* 📊 Basic monitoring (status, last check, pending updates)
* 🧩 Plugin system (extensible modules)
* 🔐 Security & compliance checks
@@ -225,15 +226,6 @@ tail -f /opt/update-manager/log/update-manager.log
---
-## ❤️ Credits
-
-Built with ❤️ for Lanx by [NodeFox 🦊](https://nodefox.lanx.dk)
-Maintained by [Eddie Nielsen](https://lanx.dk)
-
-> Learn. Adopt. Survive. Share.
-
----
-
## License
This project is licensed under the GNU GPL v3 License.
@@ -241,3 +233,10 @@ This project is licensed under the GNU GPL v3 License.
See the LICENSE file for full details.
---
+
+## Author
+
+Built with ❤️ for [Lanx](https://lanx.dk) by **NodeFox** 🦊
+
+Maintained by Eddie Nielsen
+Feel free to contribute, suggest improvements or fork the project.
diff --git a/dialogrc b/dialogrc
deleted file mode 100644
index 250e64a..0000000
--- a/dialogrc
+++ /dev/null
@@ -1,32 +0,0 @@
-use_shadow = OFF
-use_colors = ON
-
-screen_color = (WHITE,BLUE,OFF)
-dialog_color = (WHITE,BLUE,OFF)
-title_color = (YELLOW,BLUE,ON)
-border_color = (WHITE,BLUE,OFF)
-
-button_active_color = (BLACK,WHITE,ON)
-button_inactive_color = (WHITE,BLUE,OFF)
-
-button_key_active_color = (BLACK,WHITE,ON)
-button_key_inactive_color = (WHITE,BLUE,OFF)
-
-button_label_active_color = (BLACK,WHITE,ON)
-button_label_inactive_color = (WHITE,BLUE,OFF)
-
-menubox_color = (WHITE,BLUE,OFF)
-menubox_border_color = (WHITE,BLUE,OFF)
-
-item_color = (WHITE,BLUE,OFF)
-item_selected_color = (BLACK,WHITE,ON)
-
-tag_color = (WHITE,BLUE,OFF)
-tag_selected_color = (BLACK,WHITE,ON)
-
-tag_key_color = (YELLOW,BLUE,OFF)
-tag_key_selected_color = (BLACK,WHITE,ON)
-
-position_indicator_color = (WHITE,BLUE,OFF)
-uarrow_color = (WHITE,BLUE,OFF)
-darrow_color = (WHITE,BLUE,OFF)
diff --git a/docs/architecture.md b/docs/architecture.md
deleted file mode 100644
index 3c9771c..0000000
--- a/docs/architecture.md
+++ /dev/null
@@ -1,211 +0,0 @@
-
-
-
-
-# 🧠 Update Manager Architecture
-
-This document describes how Update Manager is structured internally and how data flows through the system.
-
----
-
-## Overview
-
-Update Manager is a lightweight, SSH-based system for managing updates across multiple Linux hosts.
-
-It consists of two main layers:
-
-* **UI layer** – interactive menu (`update-manager-ui.sh`)
-* **Core engine** – update logic (`update-manager.sh`)
-
-The system is designed to be simple, transparent, and dependency-light.
-
----
-
-## High-Level Flow
-
-```text
-User
- ↓
-UI (update-manager-ui.sh)
- ↓
-Core (update-manager.sh)
- ↓
-SSH → Remote Hosts
- ↓
-Results
- ↓
-Logging (/opt/update-manager/log)
- ↓
-UI / User
-```
-
----
-
-## Components
-
-### UI Layer (`update-manager-ui.sh`)
-
-Responsible for:
-
-* Displaying menu (via `dialog`)
-* Handling user input
-* Managing hosts (add/remove/edit)
-* Providing access to logs
-* Delegating actions to core engine
-
-The UI does **not perform updates directly**.
-
----
-
-### Core Engine (`update-manager.sh`)
-
-Responsible for:
-
-* Reading configuration
-* Parsing hosts file
-* Executing SSH commands
-* Checking for updates (`apt list --upgradable`)
-* Handling connection errors
-* Writing structured logs
-
-This is the **execution layer** of the system.
-
----
-
-### Hosts Configuration
-
-File:
-
-```bash
-/opt/update-manager/hosts.conf
-```
-
-Format:
-
-```text
-name ip user
-```
-
-Example:
-
-```text
-server1 192.168.1.10 user
-server2 192.168.1.20 user
-server3 192.168.1.30 user
-```
-
-Each line represents a target system accessed via SSH.
-
----
-
-### Logging System
-
-Log file:
-
-```bash
-/opt/update-manager/log/update-manager.log
-```
-
-Log format:
-
-```text
-YYYY-MM-DD HH:MM:SS [LEVEL] host - message
-```
-
-Example:
-
-```text
-2026-03-18 20:45:01 [INFO] lanx-www - Checking updates
-2026-03-18 20:45:03 [OK] lanx-www - 3 updates available
-2026-03-18 20:45:05 [ERR] lanx-db - Connection failed
-```
-
-#### Log Levels
-
-* `INFO` – informational messages
-* `OK` – successful operations
-* `ERR` – errors or failures
-
-Logging is centralized and written locally.
-
----
-
-## Execution Flow
-
-For each host:
-
-1. Read host entry from `hosts.conf`
-2. Establish SSH connection
-3. Execute:
-
-```bash
-apt list --upgradable
-```
-
-4. Parse output
-5. Determine:
-
- * Up-to-date
- * Updates available
- * Connection failure
-6. Write result to:
-
- * terminal output
- * log file
-
----
-
-## Configuration
-
-Primary config:
-
-```bash
-/etc/update-manager.conf
-```
-
-Fallback:
-
-```bash
-./update-manager.conf
-```
-
-Supported options:
-
-* `HOSTS_FILE`
-* `SSH_OPTIONS`
-
----
-
-## Design Principles
-
-* **No agents** – uses standard SSH only
-* **Simple over complex** – minimal dependencies
-* **Transparent behavior** – everything is visible/logged
-* **CLI-first** – designed for terminal environments
-* **Modular growth** – prepared for future extensions
-
----
-
-## Future Architecture Direction
-
-Planned extensions:
-
-* Plugin system (modular features)
-* Web interface (optional UI layer)
-* Notification system (alerts)
-* Metrics / monitoring
-* Integration with Lanx AI
-
----
-
-## Summary
-
-Update Manager follows a clean separation:
-
-* UI = interaction
-* Core = execution
-* Config = data
-* Log = output
-
-This keeps the system predictable, debuggable, and easy to extend.
-
diff --git a/docs/images/architecture-diagram.png b/docs/images/architecture-diagram.png
deleted file mode 100644
index d2b79f2..0000000
Binary files a/docs/images/architecture-diagram.png and /dev/null differ
diff --git a/docs/images/menu-logs.png b/docs/images/menu-logs.png
deleted file mode 100644
index 1bffefe..0000000
Binary files a/docs/images/menu-logs.png and /dev/null differ
diff --git a/docs/images/menu-main.png b/docs/images/menu-main.png
deleted file mode 100644
index 80e1e80..0000000
Binary files a/docs/images/menu-main.png and /dev/null differ
diff --git a/docs/images/update-manager-ui.png b/docs/images/update-manager-ui.png
deleted file mode 100644
index a9dd924..0000000
Binary files a/docs/images/update-manager-ui.png and /dev/null differ
diff --git a/images/updatemanager-logo.png b/images/updatemanager-logo.png
deleted file mode 100644
index bd5a27a..0000000
Binary files a/images/updatemanager-logo.png and /dev/null differ
diff --git a/log/update-manager.sh b/log/update-manager.sh
deleted file mode 100644
index d3e9635..0000000
--- a/log/update-manager.sh
+++ /dev/null
@@ -1,117 +0,0 @@
-#!/usr/bin/env bash
-
-UPDATE_MANAGER_SCRIPT="/opt/update-manager/update-manager.sh"
-
-get_log_file() {
- local primary="/opt/update-manager/log/update-manager.log"
- local fallback="$HOME/update-manager/log/update-manager.log"
-
- if [[ -f "$primary" ]]; then
- echo "$primary"
- else
- echo "$fallback"
- fi
-}
-
-run_check() {
- echo
- bash "$UPDATE_MANAGER_SCRIPT" check
- echo
- read -rp "Press Enter to continue..."
-}
-
-view_log() {
- local log_file
- log_file="$(get_log_file)"
-
- echo
- if [[ -f "$log_file" ]]; then
- less "$log_file"
- else
- echo "Log file not found: $log_file"
- echo
- read -rp "Press Enter to continue..."
- fi
-}
-
-follow_log() {
- local log_file
- log_file="$(get_log_file)"
-
- echo
- if [[ -f "$log_file" ]]; then
- echo "Following log: $log_file"
- echo "Press Ctrl+C to stop."
- echo
- tail -f "$log_file"
- else
- echo "Log file not found: $log_file"
- fi
-
- echo
- read -rp "Press Enter to continue..."
-}
-
-show_log_location() {
- local log_file
- log_file="$(get_log_file)"
-
- echo
- echo "Log file location:"
- echo "$log_file"
- echo
- read -rp "Press Enter to continue..."
-}
-
-show_menu() {
- clear
- echo "=================================="
- echo " Update Manager UI"
- echo "=================================="
- echo
- echo "1) Run update check"
- echo "2) View full log"
- echo "3) Follow log live"
- echo "4) Show log location"
- echo "0) Exit"
- echo
-}
-
-main() {
- if [[ ! -f "$UPDATE_MANAGER_SCRIPT" ]]; then
- echo "Update manager script not found: $UPDATE_MANAGER_SCRIPT"
- exit 1
- fi
-
- while true; do
- show_menu
- read -rp "Choose an option: " choice
-
- case "$choice" in
- 1)
- run_check
- ;;
- 2)
- view_log
- ;;
- 3)
- follow_log
- ;;
- 4)
- show_log_location
- ;;
- 0)
- echo
- echo "Bye."
- exit 0
- ;;
- *)
- echo
- echo "Invalid choice."
- read -rp "Press Enter to continue..."
- ;;
- esac
- done
-}
-
-main
diff --git a/update-manager-ui.png b/update-manager-ui.png
new file mode 100644
index 0000000..33929c8
Binary files /dev/null and b/update-manager-ui.png differ
diff --git a/update-manager-ui.sh b/update-manager-ui.sh
deleted file mode 100755
index af17391..0000000
--- a/update-manager-ui.sh
+++ /dev/null
@@ -1,140 +0,0 @@
-#!/usr/bin/env bash
-
-export DIALOGRC="/opt/update-manager/dialogrc"
-
-UPDATE_MANAGER_SCRIPT="$HOME/update-manager/update-manager.sh"
-HOSTS_FILE="/opt/update-manager/hosts.conf"
-
-get_log_file() {
- local primary="/opt/update-manager/log/update-manager.log"
- local fallback="$HOME/update-manager/log/update-manager.log"
-
- if [[ -f "$primary" ]]; then
- echo "$primary"
- elif [[ -f "$fallback" ]]; then
- echo "$fallback"
- else
- echo ""
- fi
-}
-
-show_log_menu() {
- while true; do
- log_choice=$(dialog --clear \
- --backtitle "Update Manager" \
- --title "Log menu" \
- --menu "Select log action:" 18 60 10 \
- 1 "View full log" \
- 2 "Follow log live" \
- 3 "Show log location" \
- 4 "Show last 20 log lines" \
- 0 "Back" \
- 3>&1 1>&2 2>&3)
-
- clear
-
- case "$log_choice" in
- 1)
- log_file="$(get_log_file)"
- if [[ -n "$log_file" ]]; then
- less "$log_file"
- else
- echo "No log file found yet."
- read -rp "Press Enter to continue..."
- fi
- ;;
- 2)
- log_file="$(get_log_file)"
- if [[ -n "$log_file" ]]; then
- echo "Press Ctrl+C to stop"
- tail -n 20 -f "$log_file"
- else
- echo "No log file found yet."
- fi
- read -rp "Press Enter to continue..."
- ;;
- 3)
- log_file="$(get_log_file)"
- if [[ -n "$log_file" ]]; then
- echo "Log file:"
- echo "$log_file"
- else
- echo "No log file found yet."
- fi
- read -rp "Press Enter to continue..."
- ;;
- 4)
- log_file="$(get_log_file)"
- if [[ -n "$log_file" ]]; then
- tail -n 20 "$log_file"
- else
- echo "No log file found yet."
- fi
- read -rp "Press Enter to continue..."
- ;;
- 0|"")
- break
- ;;
- esac
- done
-}
-
-while true; do
- choice=$(dialog --clear \
- --backtitle "Update Manager" \
- --title "Choose an action" \
- --menu "Select option:" 20 60 10 \
- 1 "Check all hosts" \
- 2 "View hosts file" \
- 3 "Edit hosts file" \
- 4 "Add host" \
- 5 "Remove host" \
- 6 "Log menu" \
- 0 "Exit" \
- 3>&1 1>&2 2>&3)
-
- clear
-
- case "$choice" in
- 1)
- bash "$UPDATE_MANAGER_SCRIPT" check
- read -rp "Press Enter to continue..."
- ;;
- 2)
- less "$HOSTS_FILE"
- ;;
- 3)
- nano "$HOSTS_FILE"
- ;;
- 4)
- read -rp "Name: " name
- read -rp "IP: " ip
- read -rp "User: " user
- if [[ -z "$name" || -z "$ip" || -z "$user" ]]; then
- echo "All fields are required."
- else
- echo "$name $ip $user" >> "$HOSTS_FILE"
- echo "Host added."
- fi
- read -rp "Press Enter to continue..."
- ;;
- 5)
- nl -w2 -s'. ' "$HOSTS_FILE"
- read -rp "Line to remove: " line
- if [[ "$line" =~ ^[0-9]+$ ]]; then
- sed -i "${line}d" "$HOSTS_FILE"
- echo "Host removed."
- else
- echo "Invalid line number."
- fi
- read -rp "Press Enter to continue..."
- ;;
- 6)
- show_log_menu
- ;;
- 0|"")
- clear
- exit 0
- ;;
- esac
-done
diff --git a/update-manager.sh b/update-manager.sh
index 679fea0..89b5ef9 100755
--- a/update-manager.sh
+++ b/update-manager.sh
@@ -1,79 +1,127 @@
#!/usr/bin/env bash
-UPDATE_MANAGER_SCRIPT="$HOME/update-manager/update-manager.sh"
-HOSTS_FILE="/opt/update-manager/hosts.conf"
+CONFIG_FILE="/etc/update-manager.conf"
+[[ -f "$CONFIG_FILE" ]] || CONFIG_FILE="./update-manager.conf"
-get_log_file() {
- local primary="/opt/update-manager/log/update-manager.log"
- local fallback="$HOME/update-manager/log/update-manager.log"
+if [[ -f "$CONFIG_FILE" ]]; then
+ # shellcheck disable=SC1090
+ source "$CONFIG_FILE"
+fi
- if [[ -f "$primary" ]]; then
- echo "$primary"
- else
- echo "$fallback"
+DEFAULT_HOSTS_FILE="${HOSTS_FILE:-/opt/update-manager/hosts.conf}"
+SSH_OPTIONS="${SSH_OPTIONS:--o BatchMode=yes -o ConnectTimeout=5}"
+
+########################################
+# Ensure hosts file exists
+########################################
+
+ensure_hosts_file() {
+ if [[ ! -f "$DEFAULT_HOSTS_FILE" ]]; then
+ echo "Creating example hosts file: $DEFAULT_HOSTS_FILE"
+
+ mkdir -p "$(dirname "$DEFAULT_HOSTS_FILE")"
+
+ cat > "$DEFAULT_HOSTS_FILE" <<'EOF'
+# Example hosts file
+# Format:
+# name ip user
+#
+# server1 192.168.1.10 user
+# server2 192.168.1.20 user
+# server3 10.0.0.5 root
+EOF
fi
}
-while true; do
- choice=$(dialog --clear \
- --backtitle "Update Manager" \
- --title "Choose an action" \
- --menu "Select option:" 15 50 10 \
- 1 "Check all hosts" \
- 2 "View hosts file" \
- 3 "Edit hosts file" \
- 4 "Add host" \
- 5 "Remove host" \
- 6 "View log" \
- 7 "Follow log live" \
- 8 "Show log location" \
- 0 "Exit" \
- 3>&1 1>&2 2>&3)
+########################################
+# Helpers
+########################################
- clear
+get_hosts_file() {
+ if [[ -n "$2" ]]; then
+ echo "$2"
+ else
+ echo "$DEFAULT_HOSTS_FILE"
+ fi
+}
- case $choice in
- 1)
- bash "$UPDATE_MANAGER_SCRIPT" check
- read -rp "Press Enter to continue..."
- ;;
- 2)
- less "$HOSTS_FILE"
- ;;
- 3)
- nano "$HOSTS_FILE"
- ;;
- 4)
- read -rp "Name: " name
- read -rp "IP: " ip
- read -rp "User: " user
- echo "$name $ip $user" >> "$HOSTS_FILE"
- echo "Host added."
- read -rp "Press Enter to continue..."
- ;;
- 5)
- nl -w2 -s'. ' "$HOSTS_FILE"
- read -rp "Line to remove: " line
- sed -i "${line}d" "$HOSTS_FILE"
- echo "Host removed."
- read -rp "Press Enter to continue..."
- ;;
- 6)
- less "$(get_log_file)"
- ;;
- 7)
- echo "Press Ctrl+C to stop"
- tail -f "$(get_log_file)"
- read -rp "Press Enter to continue..."
- ;;
- 8)
- echo "Log file:"
- echo "$(get_log_file)"
- read -rp "Press Enter to continue..."
- ;;
- 0)
- clear
- exit 0
- ;;
- esac
-done
+usage() {
+ cat </dev/null | sed '/^Listing/d'" 2>&1)
+ rc=$?
+
+ printf "===== %s (%s) =====\n" "$name" "$ip"
+
+ if [[ $rc -ne 0 ]]; then
+ echo "❌ connection failed"
+ echo "$result"
+ echo
+ return
+ fi
+
+ if [[ -z "$result" ]]; then
+ echo "Up-to-date"
+ else
+ echo "$result"
+ fi
+
+ echo
+}
+
+########################################
+# Check all hosts
+########################################
+
+check_all() {
+ local hosts_file="$1"
+
+ ensure_hosts_file
+
+ while IFS= read -r line; do
+ [[ -z "$line" || "$line" =~ ^[[:space:]]*# ]] && continue
+
+ local name ip user
+ read -r name ip user <<< "$line"
+
+ [[ -z "$name" || -z "$ip" || -z "$user" ]] && continue
+
+ check_host "$name" "$ip" "$user"
+ done < "$hosts_file"
+}
+
+########################################
+# Main
+########################################
+
+case "${1:-}" in
+ check)
+ HOSTS_FILE_TO_USE="$(get_hosts_file "$@")"
+ check_all "$HOSTS_FILE_TO_USE"
+ ;;
+ *)
+ usage
+ exit 1
+ ;;
+esac