From 104debb6e17b2b05c31f4e4a801793bad2e08c4e Mon Sep 17 00:00:00 2001 From: thehack904 <35552907+thehack904@users.noreply.github.com> Date: Tue, 7 Oct 2025 13:52:57 -0500 Subject: [PATCH 01/41] Update README.md --- README.md | 194 +++++++++++++++++++++++++++++++++++------------------- 1 file changed, 127 insertions(+), 67 deletions(-) diff --git a/README.md b/README.md index 739ad57..1cbdb8c 100644 --- a/README.md +++ b/README.md @@ -3,100 +3,160 @@ ![Version](https://img.shields.io/badge/version-v3.0.1-blue) RetroIPTVGuide is an IPTV Web Interface inspired by 90s/2000s cable TV guides. -It is designed to work with [ErsatzTV](https://ersatztv.org/) [(GitRepo)](https://github.com/ErsatzTV/ErsatzTV/tree/main) but should support any `.m3u` and `.xml` IPTV source. +It is designed to work with [ErsatzTV](https://ersatztv.org/) [(GitRepo)](https://github.com/ErsatzTV/ErsatzTV/tree/main) but supports any `.m3u`, `.m3u8`, and `.xml` IPTV source. -โ��๏ธ� **Note:** This is still a BETA release. It is not recommended for direct Internet/public-facing deployments. +⚠️ **Note:** This is still a BETA release. It is not recommended for direct Internet/public-facing deployments. - [Installation / Uninstall Guide](INSTALL.md) - [Changelog](CHANGELOG.md) - [Roadmap](ROADMAP.md) - [License](LICENSE) -## โ�จ Features (v3.0.0) -- ๐�”‘ **User Authentication** - - Login/logout system with hashed passwords. - - Admin and regular user accounts. - - Password change functionality. - - Admin-only user management (add/delete users). -- ๐�“ก **Tuner Management** - - Multiple tuner support stored in `tuners.db`. - - Switch between active tuners via the web UI. - - Update `.m3u` and `.xml` tuner URLs (persisted in DB). -- ๐�“บ **Guide & Playback** - - Program guide rendered from XMLTV with automatic fallback for missing data. - - Channels without guide entries display “No Guide Data Available”. - - Video playback using HTML5 + HLS.js. - - Playback events logged with user + channel + timestamp. -- ๐�“‘ **Logging** - - Activity log (`activity.log`) records authentication events, tuner changes, playback, and admin actions. - - Admin-only **Logs page** with real-time log viewing. - - Log file size display with color coding. - - Admin-only โ€�Clear Logsโ€� button to truncate logs. -- ๐��จ **UI Enhancements** - - Unified header across all pages (Guide, Logs, Add User, Delete User, Change Password, Change Tuner, Login). - - Active tuner display + live clock in header. - - **Themes submenu** with multiple options: - - Light - - Dark - - AOL/CompuServe - - TV Guide Magazine - - Theme persistence stored in browser localStorage, applied instantly across all pages. - - **About Page under Settings menu** โ€” shows version, Python, OS, uptime, paths. -- โ��๏ธ� **System** - - Automatic initialization of `users.db` and `tuners.db` on first run. - - SQLite databases use WAL mode for better concurrency. - - Preloads tuner/channel/guide data from DB on startup. - - **Cross-platform installers (Linux/Windows) (v3.0.0)**. - - **Uninstaller scripts (Linux/Windows) (v3.0.0)**. - - **Automated version bump tool (`bump_version.py`) (v3.0.0)**. +--- + +## ✨ Features (v3.0.1) + +### 🔑 User Authentication +- Login/logout system with hashed passwords. +- Admin and regular user accounts. +- Password change functionality. +- Admin-only user management (add/delete users). + +### 📡 Tuner Management +- Multiple tuner support stored in `tuners.db`. +- Switch between active tuners via the web UI. +- Update `.m3u`, `.m3u8`, and `.xml` tuner URLs (persisted in DB). +- Active tuner refreshes instantly when changed — **no logout required**. +- Detection for invalid XML inputs (e.g., `.m3u` pasted into `.xml` field). + +### 📺 Guide & Playback +- Program guide rendered from XMLTV data. +- **Automatic fallback:** Channels missing XMLTV data display *“No Guide Data Available”*. +- Channel list parsed from M3U playlist. +- Video playback using HTML5 + HLS.js. +- Playback events logged with user + channel + timestamp. +- Scalable time grid and responsive EPG layout. + +### 📑 Logging +- `activity.log` records authentication events, tuner changes, playback, and admin actions. +- Admin-only **Logs page** with real-time log viewing. +- Log file size display with color coding. +- Admin-only “Clear Logs” button to truncate logs. + +### 🎨 UI Enhancements +- Unified header across all pages: Guide, Logs, Add User, Delete User, Change Password, Change Tuner, and Login. +- Active tuner display + live clock in header. +- “No Guide Data Available” placeholders styled in gray/italic with dashed border. +- **Themes submenu** with multiple options: + - Light + - Dark + - AOL/CompuServe + - TV Guide Magazine +- Theme persistence stored in browser localStorage, applied instantly across all pages. +- **About Page under Settings** — shows version, Python, OS, uptime, and paths. +- **Login Page Redesign (v3.0.1)**: + - Floating centered login box with 3D shadow. + - RetroIPTVGuide logo positioned upper-right. + +### ⚙️ System +- Automatic initialization of `users.db` and `tuners.db` on first run. +- SQLite databases use WAL mode for better concurrency. +- Preloads tuner/channel/guide data from DB on startup. +- **Cross-platform installers (Linux/Windows)**. +- **Uninstaller scripts (Linux/Windows)**. +- **Automated version bump tool (`bump_version.py`)**. --- -## ๐��� Browser Compatibility -This project is designed to work with **all major browsers**. -It has been tested on: +## 🧩 Version History + +| Version | Date | Key Features | +|----------|------|---------------| +| **v3.0.1** | 2025-10-07 | EPG fallback system, tuner refresh fix, login redesign | +| **v3.0.0** | 2025-10-03 | Windows installer/uninstaller, cross-platform setup, unified UI | +| **v2.3.x** | 2025-09 | Unified theming, About page, installer logging, tuner rename/delete | +| **v2.0.0** | 2025-09 | Persistent tuners.db, user logs, unified headers | +| **v1.x.x** | 2025-08 | Initial IPTV Flask prototype | + +--- + +## 🌐 Browser Compatibility +RetroIPTVGuide is compatible with all modern browsers: + - Firefox - Chrome - Safari - Edge -## ๐�’ป Tested Devices & OS -The web interface has been tested on: -- **Ubuntu (desktop/server)** +--- + +## 💻 Tested Devices & Operating Systems +- **Ubuntu 24.04 (desktop/server)** +- **TrueNAS SCALE (Docker/Podman)** +- **Windows 10 / 11** +- **macOS Monterey / Ventura** - **iOS (mobile/tablet)** -- **Android (Samsung Mobile Phone)** -- **macOS** -- **Windows 10/11** -- **MacOS** -- **Windows** +- **Android (Samsung / Pixel)** + +--- + +## 🛠️ Installation Platforms +- Debian-based Linux (Ubuntu, Pop!\_OS, Mint) +- Windows 10/11 (via PowerShell + NSSM) +- MacOS (manual install or future installer support) -## ๐���๏ธ� Installation Platform -- **Debian Based Linux (desktop/server)** -- **Windows 10/11** +--- -## ๐�“บ Screenshots +## 📸 Screenshots -## ๐�“บ Guide Page +### 📺 Guide Page ![Guide Screenshot](docs/screenshots/guide.png) -## ๐�“บ Video Pop Out -![Video Pop Out](docs/screenshots/guide_with_video_breakout.png) +### 📺 Video Pop Out +![Guide Pop Out](docs/screenshots/guide_with_video_breakout.png) -## ๐�“บ Video Pop Out on Desktop +### 💻 Desktop Pop Out ![Desktop Pop Out](docs/screenshots/video_breakout_desktop.png) -## ๐�“บ TV Guide Magazine Theme +### 📰 TV Guide Magazine Theme ![TV Guide Theme](docs/screenshots/TV_Guide_Theme.png) -## ๐�“บ AOL / CompuServe Theme -![AOL / CompuServe Theme](docs/screenshots/AOL_Compuserve_Theme.png) +### 💾 AOL / CompuServe Theme +![AOL Theme](docs/screenshots/AOL_Compuserve_Theme.png) --- -## ๐�ค� Contributing -Contributions are welcome! Hereโ€�s how you can help: -1. **Report Issues**: Found a bug or want to suggest a feature? Open an [issue](../../issues). -2. **Submit Pull Requests**: Fork the repo, make changes, and submit a PR. Please ensure code is tested before submitting. -3. **Improve Documentation**: Help refine the installation guide, add screenshots, or improve explanations in the README. +## 🤝 Contributing + +Contributions are welcome! Here’s how you can help: + +1. **Report Issues** – Found a bug or want to suggest a feature? Open an [issue](../../issues). +2. **Submit Pull Requests** – Fork, modify, test, and submit PRs for new features or fixes. +3. **Improve Documentation** – Add screenshots, examples, or clearer explanations. + +All contributions will be reviewed before merging into the main branch. + +--- + +## 🧭 Roadmap (Next Planned Features) +- [ ] `.m3u8` single-channel tuner support +- [ ] Log filtering and pagination +- [ ] Guide search/filter +- [ ] Favorites and notifications +- [ ] Responsive mobile layout +- [ ] Auto-refresh EPG schedule + +See [ROADMAP.md](ROADMAP.md) for full details. + +--- + +## 🧰 Maintainer Notes +- **Repo:** [RetroIPTVGuide](https://github.com/thehack904/RetroIPTVGuide) +- **Maintainer:** J.H. +- **License:** [Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International (CC BY-NC-SA 4.0)](https://creativecommons.org/licenses/by-nc-sa/4.0/) +- **Version:** v3.0.1 +- **Release Date:** 2025-10-07 + +--- -All contributions will be reviewed by the project maintainer before merging. +© 2025 RetroIPTVGuide Project — *Licensed under CC BY-NC-SA 4.0. Inspired by the golden era of cable TV.* From a9e739d4e51b3bd14e992500312a8c63aeaa675c Mon Sep 17 00:00:00 2001 From: thehack904 <35552907+thehack904@users.noreply.github.com> Date: Wed, 8 Oct 2025 08:43:18 -0500 Subject: [PATCH 02/41] Update INSTALL.md --- INSTALL.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/INSTALL.md b/INSTALL.md index f044906..827c03e 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -81,7 +81,7 @@ Default login: **admin / strongpassword123** #### Quick update (one-liner) ```bash -sudo -u iptv bash -H -c "cd /home/iptv/iptv-server && git fetch --all && git reset --hard origin/main" && sudo systemctl restart iptv-server.service +sudo -u iptv bash -H -c "cd /home/iptv/iptv-server && git fetch --all && git reset --hard origin/main" && sudo systemctl daemon-reload && sudo systemctl restart iptv-server.service ``` or From bd92e53b7d99d23b27d2dfe41e444a225c693e55 Mon Sep 17 00:00:00 2001 From: thehack904 <35552907+thehack904@users.noreply.github.com> Date: Thu, 9 Oct 2025 06:55:45 -0500 Subject: [PATCH 03/41] Create retroiptv_rpi.sh Install / Uninstall for Raspberry Pi --- retroiptv_rpi.sh | 269 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 269 insertions(+) create mode 100644 retroiptv_rpi.sh diff --git a/retroiptv_rpi.sh b/retroiptv_rpi.sh new file mode 100644 index 0000000..1a4f4dd --- /dev/null +++ b/retroiptv_rpi.sh @@ -0,0 +1,269 @@ +#!/bin/bash +# RetroIPTVGuide Raspberry Pi Manager +# Combined Installer / Uninstaller for Pi 3 & 4 +# License: Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International + +# --- Banner --- +cat <<'EOF' +░█████████ ░██ ░██████░█████████ ░██████████░██ ░██ ░██████ ░██ ░██ +░██ ░██ ░██ ░██ ░██ ░██ ░██ ░██ ░██ ░██ ░██ ░██ +░██ ░██ ░███████ ░████████ ░██░████ ░███████ ░██ ░██ ░██ ░██ ░██ ░██ ░██ ░██ ░██ ░██ ░████████ ░███████ +░█████████ ░██ ░██ ░██ ░███ ░██ ░██ ░██ ░█████████ ░██ ░██ ░██ ░██ █████ ░██ ░██ ░██░██ ░██ ░██ ░██ +░██ ░██ ░█████████ ░██ ░██ ░██ ░██ ░██ ░██ ░██ ░██ ░██ ░██ ██ ░██ ░██ ░██░██ ░██ ░█████████ +░██ ░██ ░██ ░██ ░██ ░██ ░██ ░██ ░██ ░██ ░██░██ ░██ ░███ ░██ ░███ ░██░██ ░███ ░██ +░██ ░██ ░███████ ░████ ░██ ░███████ ░██████░██ ░██ ░███ ░█████░█ ░█████░██ ░██ ░█████░██ ░███████ + + + +EOF +echo "===========================================================================" +echo " RetroIPTVGuide | Raspberry Pi Edition" +echo "===========================================================================" +echo "" + +set -e + +APP_DIR="/opt/RetroIPTVGuide" +SERVICE_FILE="/etc/systemd/system/retroiptvguide.service" +CONFIG_FILE="/boot/config.txt" +USER_NAME="${SUDO_USER:-$(whoami)}" + +ACTION="$1" +AUTO_YES=false +if [[ "$2" == "--yes" || "$2" == "-y" ]]; then + AUTO_YES=true +fi + +#====================== FUNCTIONS ======================# + +show_usage() { + echo "" + echo "Usage:" + echo " sudo ./retroiptv_rpi.sh install" + echo " sudo ./retroiptv_rpi.sh uninstall [--yes|-y]" + echo "" + echo "Examples:" + echo " sudo ./retroiptv_rpi.sh install" + echo " sudo ./retroiptv_rpi.sh uninstall --yes" + echo "" + exit 1 +} + +#---------------------------------------------------------- +install_app() { + echo "" + echo "============================================================" + echo " RetroIPTVGuide Raspberry Pi Installer Agreement " + echo "============================================================" + echo "" + echo "This installer will perform the following actions:" + echo " - Detect Raspberry Pi model (3 or 4)" + echo " - Install dependencies (Python3, ffmpeg, etc.)" + echo " - Clone or update RetroIPTVGuide into /opt/RetroIPTVGuide" + echo " - Configure Python virtual environment and systemd service" + echo " - Auto-configure GPU acceleration (KMS/Fake KMS)" + echo " - Optionally reboot when done" + echo "" + echo "By continuing, you agree that:" + echo " - This software should ONLY be run on internal networks." + echo " - It must NOT be exposed to the public Internet." + echo " - You accept all risks; no warranty is provided." + echo "" + + read -p "Do you agree to these terms? (yes/no): " agreement + if [ "$agreement" != "yes" ]; then + echo "Installation aborted by user." + exit 1 + fi + echo "Agreement accepted. Continuing..." + echo "" + + # Detect model + PI_MODEL=$(tr -d '\0' < /proc/device-tree/model) + if echo "$PI_MODEL" | grep -q "Raspberry Pi 4"; then + PI_TYPE="pi4" + elif echo "$PI_MODEL" | grep -q "Raspberry Pi 3"; then + PI_TYPE="pi3" + else + PI_TYPE="unknown" + fi + echo "Detected board: $PI_MODEL ($PI_TYPE)" + echo "" + + # Update + deps + sudo apt update -y && sudo apt full-upgrade -y + sudo apt install -y git python3 python3-venv python3-pip ffmpeg mesa-utils v4l-utils raspi-config + + # Clone repo + if [ ! -d "$APP_DIR" ]; then + echo "Cloning RetroIPTVGuide..." + sudo git clone https://github.com/thehack904/RetroIPTVGuide.git "$APP_DIR" + else + echo "Existing repo found, updating..." + cd "$APP_DIR" && sudo git pull + fi + + # Python venv + cd "$APP_DIR" + sudo python3 -m venv venv + source venv/bin/activate + pip install --upgrade pip + if [ -f requirements.txt ]; then + pip install -r requirements.txt + else + pip install Flask + fi + deactivate + + # Systemd service + sudo tee "$SERVICE_FILE" > /dev/null </dev/null || true + sudo systemctl disable retroiptvguide 2>/dev/null || true + echo "Service stopped and disabled." + fi + + # Remove service + [ -f "$SERVICE_FILE" ] && sudo rm -f "$SERVICE_FILE" && sudo systemctl daemon-reload + + # Remove app directory + if [ -d "$APP_DIR" ]; then + if [ "$AUTO_YES" = true ]; then + sudo rm -rf "$APP_DIR" + echo "Application directory deleted automatically." + else + read -p "Delete all files under $APP_DIR? (yes/no): " del + [[ "$del" == "yes" ]] && sudo rm -rf "$APP_DIR" && echo "Deleted." || echo "Retained." + fi + fi + + # Optional logs + LOG_DIRS=("/var/log/retroiptvguide" "/tmp/retroiptvguide" "$HOME/.cache/retroiptvguide") + for dir in "${LOG_DIRS[@]}"; do + if [ -d "$dir" ]; then + if [ "$AUTO_YES" = true ]; then + sudo rm -rf "$dir" + echo "Removed logs: $dir" + else + read -p "Delete logs in $dir? (yes/no): " ans + [[ "$ans" == "yes" ]] && sudo rm -rf "$dir" && echo "Deleted $dir." + fi + fi + done + + echo "" + echo "============================================================" + echo " Uninstallation Complete " + echo "============================================================" + echo "All RetroIPTVGuide components removed." + echo "System packages remain installed." + echo "End time: $(date)" + echo "" +} + +#====================== MAIN ======================# + +if [[ -z "$ACTION" ]]; then + show_usage +fi + +case "$ACTION" in + install) + install_app + ;; + uninstall) + uninstall_app + ;; + *) + show_usage + ;; +esac From f77791ab01bc7c22799346a69b051cdaf04e0801 Mon Sep 17 00:00:00 2001 From: thehack904 <35552907+thehack904@users.noreply.github.com> Date: Thu, 9 Oct 2025 07:01:07 -0500 Subject: [PATCH 04/41] Update retroiptv_rpi.sh --- retroiptv_rpi.sh | 352 +++++++++++++++++++---------------------------- 1 file changed, 141 insertions(+), 211 deletions(-) diff --git a/retroiptv_rpi.sh b/retroiptv_rpi.sh index 1a4f4dd..2920098 100644 --- a/retroiptv_rpi.sh +++ b/retroiptv_rpi.sh @@ -1,7 +1,7 @@ #!/bin/bash -# RetroIPTVGuide Raspberry Pi Manager -# Combined Installer / Uninstaller for Pi 3 & 4 -# License: Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International +# RetroIPTVGuide Raspberry Pi Manager (Installer + Uninstaller) +# Logs all output to /var/log/retroiptvguide/YYYYMMDD-HHMMSS.log +# License: CC BY-NC-SA 4.0 # --- Banner --- cat <<'EOF' @@ -23,6 +23,21 @@ echo "" set -e +# --- Logging Setup --- +LOG_DIR="/var/log/retroiptvguide" +TIMESTAMP=$(date +"%Y%m%d-%H%M%S") +LOG_FILE="$LOG_DIR/install-$TIMESTAMP.log" + +# Make sure log directory exists and is writable +sudo mkdir -p "$LOG_DIR" +sudo chmod 755 "$LOG_DIR" + +# Redirect all stdout/stderr to tee so user sees it and it’s saved +exec > >(tee -a "$LOG_FILE") 2>&1 + +echo "Log file: $LOG_FILE" +echo "" + APP_DIR="/opt/RetroIPTVGuide" SERVICE_FILE="/etc/systemd/system/retroiptvguide.service" CONFIG_FILE="/boot/config.txt" @@ -30,97 +45,63 @@ USER_NAME="${SUDO_USER:-$(whoami)}" ACTION="$1" AUTO_YES=false -if [[ "$2" == "--yes" || "$2" == "-y" ]]; then - AUTO_YES=true -fi +if [[ "$2" == "--yes" || "$2" == "-y" ]]; then AUTO_YES=true; fi #====================== FUNCTIONS ======================# - show_usage() { - echo "" - echo "Usage:" - echo " sudo ./retroiptv_rpi.sh install" - echo " sudo ./retroiptv_rpi.sh uninstall [--yes|-y]" - echo "" - echo "Examples:" - echo " sudo ./retroiptv_rpi.sh install" - echo " sudo ./retroiptv_rpi.sh uninstall --yes" - echo "" - exit 1 + echo "" + echo "Usage:" + echo " sudo ./retroiptv_rpi.sh install" + echo " sudo ./retroiptv_rpi.sh uninstall [--yes|-y]" + echo "" + exit 1 } #---------------------------------------------------------- install_app() { - echo "" - echo "============================================================" - echo " RetroIPTVGuide Raspberry Pi Installer Agreement " - echo "============================================================" - echo "" - echo "This installer will perform the following actions:" - echo " - Detect Raspberry Pi model (3 or 4)" - echo " - Install dependencies (Python3, ffmpeg, etc.)" - echo " - Clone or update RetroIPTVGuide into /opt/RetroIPTVGuide" - echo " - Configure Python virtual environment and systemd service" - echo " - Auto-configure GPU acceleration (KMS/Fake KMS)" - echo " - Optionally reboot when done" - echo "" - echo "By continuing, you agree that:" - echo " - This software should ONLY be run on internal networks." - echo " - It must NOT be exposed to the public Internet." - echo " - You accept all risks; no warranty is provided." - echo "" - - read -p "Do you agree to these terms? (yes/no): " agreement - if [ "$agreement" != "yes" ]; then - echo "Installation aborted by user." - exit 1 - fi - echo "Agreement accepted. Continuing..." - echo "" - - # Detect model - PI_MODEL=$(tr -d '\0' < /proc/device-tree/model) - if echo "$PI_MODEL" | grep -q "Raspberry Pi 4"; then - PI_TYPE="pi4" - elif echo "$PI_MODEL" | grep -q "Raspberry Pi 3"; then - PI_TYPE="pi3" - else - PI_TYPE="unknown" - fi - echo "Detected board: $PI_MODEL ($PI_TYPE)" - echo "" - - # Update + deps - sudo apt update -y && sudo apt full-upgrade -y - sudo apt install -y git python3 python3-venv python3-pip ffmpeg mesa-utils v4l-utils raspi-config - - # Clone repo - if [ ! -d "$APP_DIR" ]; then - echo "Cloning RetroIPTVGuide..." - sudo git clone https://github.com/thehack904/RetroIPTVGuide.git "$APP_DIR" - else - echo "Existing repo found, updating..." - cd "$APP_DIR" && sudo git pull - fi - - # Python venv - cd "$APP_DIR" - sudo python3 -m venv venv - source venv/bin/activate - pip install --upgrade pip - if [ -f requirements.txt ]; then - pip install -r requirements.txt - else - pip install Flask - fi - deactivate - - # Systemd service - sudo tee "$SERVICE_FILE" > /dev/null < /dev/null </dev/null || true - sudo systemctl disable retroiptvguide 2>/dev/null || true - echo "Service stopped and disabled." - fi - - # Remove service - [ -f "$SERVICE_FILE" ] && sudo rm -f "$SERVICE_FILE" && sudo systemctl daemon-reload - - # Remove app directory - if [ -d "$APP_DIR" ]; then - if [ "$AUTO_YES" = true ]; then - sudo rm -rf "$APP_DIR" - echo "Application directory deleted automatically." - else - read -p "Delete all files under $APP_DIR? (yes/no): " del - [[ "$del" == "yes" ]] && sudo rm -rf "$APP_DIR" && echo "Deleted." || echo "Retained." - fi - fi - - # Optional logs - LOG_DIRS=("/var/log/retroiptvguide" "/tmp/retroiptvguide" "$HOME/.cache/retroiptvguide") - for dir in "${LOG_DIRS[@]}"; do - if [ -d "$dir" ]; then - if [ "$AUTO_YES" = true ]; then - sudo rm -rf "$dir" - echo "Removed logs: $dir" - else - read -p "Delete logs in $dir? (yes/no): " ans - [[ "$ans" == "yes" ]] && sudo rm -rf "$dir" && echo "Deleted $dir." - fi - fi - done - - echo "" - echo "============================================================" - echo " Uninstallation Complete " - echo "============================================================" - echo "All RetroIPTVGuide components removed." - echo "System packages remain installed." - echo "End time: $(date)" - echo "" + echo "" + echo "============================================================" + echo " RetroIPTVGuide Uninstaller for Raspberry Pi " + echo "============================================================" + echo "" + + if [ "$AUTO_YES" = false ]; then + read -p "Proceed with uninstallation? (yes/no): " c + [[ "$c" != "yes" ]] && echo "Aborted." && exit 1 + fi + + systemctl stop retroiptvguide 2>/dev/null || true + systemctl disable retroiptvguide 2>/dev/null || true + [ -f "$SERVICE_FILE" ] && sudo rm -f "$SERVICE_FILE" && sudo systemctl daemon-reload + + if [ -d "$APP_DIR" ]; then + if [ "$AUTO_YES" = true ]; then sudo rm -rf "$APP_DIR" + else read -p "Delete $APP_DIR? (yes/no): " d && [[ "$d" == "yes" ]] && sudo rm -rf "$APP_DIR"; fi + fi + + LOG_DIRS=("/var/log/retroiptvguide" "/tmp/retroiptvguide" "$HOME/.cache/retroiptvguide") + for dir in "${LOG_DIRS[@]}"; do + [ -d "$dir" ] || continue + if [ "$AUTO_YES" = true ]; then sudo rm -rf "$dir" + else read -p "Delete logs in $dir? (yes/no): " a && [[ "$a" == "yes" ]] && sudo rm -rf "$dir"; fi + done + + echo "" + echo "============================================================" + echo " Uninstallation Complete " + echo "============================================================" + echo "All RetroIPTVGuide components removed." + echo "End time: $(date)" + echo "Log file: $LOG_FILE" + echo "" } #====================== MAIN ======================# - -if [[ -z "$ACTION" ]]; then - show_usage -fi - +if [[ -z "$ACTION" ]]; then show_usage; fi case "$ACTION" in - install) - install_app - ;; - uninstall) - uninstall_app - ;; - *) - show_usage - ;; + install) install_app ;; + uninstall) uninstall_app ;; + *) show_usage ;; esac From 76be2a428db32be9d4ed123c6dba108f78fca699 Mon Sep 17 00:00:00 2001 From: thehack904 <35552907+thehack904@users.noreply.github.com> Date: Thu, 9 Oct 2025 07:18:35 -0500 Subject: [PATCH 05/41] Update retroiptv_rpi.sh --- retroiptv_rpi.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/retroiptv_rpi.sh b/retroiptv_rpi.sh index 2920098..dafce25 100644 --- a/retroiptv_rpi.sh +++ b/retroiptv_rpi.sh @@ -122,15 +122,15 @@ EOF case "$PI_TYPE" in pi3) sudo raspi-config nonint do_gldriver G1 - sudo raspi-config nonint do_memory_split 128 + sudo raspi-config nonint set_config_var gpu_mem 128 /boot/config.txt grep -q "dtoverlay=vc4-fkms-v3d" "$CONFIG_FILE" || echo "dtoverlay=vc4-fkms-v3d" | sudo tee -a "$CONFIG_FILE" ;; pi4) sudo raspi-config nonint do_gldriver G2 - sudo raspi-config nonint do_memory_split 256 + sudo raspi-config nonint set_config_var gpu_mem 256 /boot/config.txt grep -q "dtoverlay=vc4-kms-v3d" "$CONFIG_FILE" || echo "dtoverlay=vc4-kms-v3d" | sudo tee -a "$CONFIG_FILE" ;; - *) sudo raspi-config nonint do_memory_split 128 ;; + *) sudo raspi-config nonint set_config_var gpu_mem 128 /boot/config.txt ;; esac echo "" From 4e6f600cd095530c19566e0fdf5be91ad3f88ff8 Mon Sep 17 00:00:00 2001 From: thehack904 <35552907+thehack904@users.noreply.github.com> Date: Thu, 9 Oct 2025 08:36:58 -0500 Subject: [PATCH 06/41] Update ROADMAP.md --- ROADMAP.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/ROADMAP.md b/ROADMAP.md index 7704779..59f07f7 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -100,3 +100,15 @@ These are **not yet implemented**, but provide a development path for future rel ## ✅ Completed (v3.0.0) - [x] Full Windows installer/uninstaller support with NSSM service, firewall rule, and Chocolatey integration (v3.0.0). - [x] Documentation updates (README.md, INSTALL.md) to reflect Windows support (v3.0.0). + +### Installer Enhancement: Kiosk vs Headless Mode (Planned) +**Target Version:** v3.2.0 +**Status:** Planned +**Effort:** Medium + +- Add an interactive mode selector to the Raspberry Pi installer. +- Headless mode → install to `/home/iptv/iptv-server` with service user `iptv`. +- Kiosk mode → install to `/opt/RetroIPTVGuide` and auto-launch Chromium in fullscreen displaying RetroIPTVGuide. +- Support command-line flags: `--mode kiosk` or `--mode headless` for non-interactive installs. +- Ensure logs and services are properly separated between modes. + From 8ff431a2988f26dffb55e00646db219334715a0f Mon Sep 17 00:00:00 2001 From: thehack904 <35552907+thehack904@users.noreply.github.com> Date: Thu, 9 Oct 2025 08:38:34 -0500 Subject: [PATCH 07/41] Update ROADMAP.md --- ROADMAP.md | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/ROADMAP.md b/ROADMAP.md index 59f07f7..a659ab9 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -80,6 +80,17 @@ These are **not yet implemented**, but provide a development path for future rel - Medium term: Test and harden installer/uninstaller on mixed Windows environments (v3.0.0 complete, further refinements planned). - Long term: .m3u8 support, DB logs, recording functionality. +## 💻🥧 Installer Enhancement: Kiosk vs Headless Mode (Planned) +**Target Version:** v3.2.0 +**Status:** Planned +**Effort:** Medium + +- Add an interactive mode selector to the Raspberry Pi installer. +- Headless mode → install to `/home/iptv/iptv-server` with service user `iptv`. +- Kiosk mode → install to `/opt/RetroIPTVGuide` and auto-launch Chromium in fullscreen displaying RetroIPTVGuide. +- Support command-line flags: `--mode kiosk` or `--mode headless` for non-interactive installs. +- Ensure logs and services are properly separated between modes. + --- ## ✅ Completed @@ -96,19 +107,6 @@ These are **not yet implemented**, but provide a development path for future rel - [x] Basic Windows installer support (Git Bash + PowerShell bootstrap) (v2.3.0). - ## ✅ Completed (v3.0.0) - [x] Full Windows installer/uninstaller support with NSSM service, firewall rule, and Chocolatey integration (v3.0.0). - [x] Documentation updates (README.md, INSTALL.md) to reflect Windows support (v3.0.0). - -### Installer Enhancement: Kiosk vs Headless Mode (Planned) -**Target Version:** v3.2.0 -**Status:** Planned -**Effort:** Medium - -- Add an interactive mode selector to the Raspberry Pi installer. -- Headless mode → install to `/home/iptv/iptv-server` with service user `iptv`. -- Kiosk mode → install to `/opt/RetroIPTVGuide` and auto-launch Chromium in fullscreen displaying RetroIPTVGuide. -- Support command-line flags: `--mode kiosk` or `--mode headless` for non-interactive installs. -- Ensure logs and services are properly separated between modes. - From e9e040002770839e2b5b8685d39a0349f047eefb Mon Sep 17 00:00:00 2001 From: thehack904 <35552907+thehack904@users.noreply.github.com> Date: Thu, 9 Oct 2025 11:06:49 -0500 Subject: [PATCH 08/41] Update retroiptv_rpi.sh --- retroiptv_rpi.sh | 238 ++++++++++++++++++++++++++++++----------------- 1 file changed, 152 insertions(+), 86 deletions(-) diff --git a/retroiptv_rpi.sh b/retroiptv_rpi.sh index dafce25..ccbe44f 100644 --- a/retroiptv_rpi.sh +++ b/retroiptv_rpi.sh @@ -1,6 +1,7 @@ #!/bin/bash -# RetroIPTVGuide Raspberry Pi Manager (Installer + Uninstaller) -# Logs all output to /var/log/retroiptvguide/YYYYMMDD-HHMMSS.log +# RetroIPTVGuide Raspberry Pi Installer (Headless, Pi3/4/5) +# Installs to /home/iptv/iptv-server for consistency with Debian/Windows +# Logs to /var/log/retroiptvguide/install-YYYYMMDD-HHMMSS.log # License: CC BY-NC-SA 4.0 # --- Banner --- @@ -13,102 +14,173 @@ cat <<'EOF' ░██ ░██ ░██ ░██ ░██ ░██ ░██ ░██ ░██ ░██ ░██░██ ░██ ░███ ░██ ░███ ░██░██ ░███ ░██ ░██ ░██ ░███████ ░████ ░██ ░███████ ░██████░██ ░██ ░███ ░█████░█ ░█████░██ ░██ ░█████░██ ░███████ - - EOF echo "===========================================================================" -echo " RetroIPTVGuide | Raspberry Pi Edition" +echo " RetroIPTVGuide | Raspberry Pi Edition (Headless)" echo "===========================================================================" echo "" set -e -# --- Logging Setup --- +# --- Logging --- LOG_DIR="/var/log/retroiptvguide" TIMESTAMP=$(date +"%Y%m%d-%H%M%S") LOG_FILE="$LOG_DIR/install-$TIMESTAMP.log" - -# Make sure log directory exists and is writable sudo mkdir -p "$LOG_DIR" sudo chmod 755 "$LOG_DIR" - -# Redirect all stdout/stderr to tee so user sees it and it’s saved exec > >(tee -a "$LOG_FILE") 2>&1 - echo "Log file: $LOG_FILE" echo "" -APP_DIR="/opt/RetroIPTVGuide" +# --- Vars --- +APP_USER="iptv" +APP_DIR="/home/$APP_USER/iptv-server" SERVICE_FILE="/etc/systemd/system/retroiptvguide.service" CONFIG_FILE="/boot/config.txt" -USER_NAME="${SUDO_USER:-$(whoami)}" ACTION="$1" AUTO_YES=false -if [[ "$2" == "--yes" || "$2" == "-y" ]]; then AUTO_YES=true; fi +AUTO_AGREE=false +for arg in "$@"; do + case "$arg" in + --yes|-y) AUTO_YES=true ;; + --agree|-a) AUTO_AGREE=true ;; + esac +done -#====================== FUNCTIONS ======================# -show_usage() { - echo "" - echo "Usage:" - echo " sudo ./retroiptv_rpi.sh install" - echo " sudo ./retroiptv_rpi.sh uninstall [--yes|-y]" - echo "" - exit 1 +# --- Helpers --- +set_gpu_mem() { + local val="$1" + if command -v raspi-config >/dev/null 2>&1; then + sudo raspi-config nonint set_config_var gpu_mem "$val" "$CONFIG_FILE" + else + # Fallback: edit/append gpu_mem in /boot/config.txt + sudo sed -i -E 's/^\s*gpu_mem\s*=.*/gpu_mem='"$val"'/g' "$CONFIG_FILE" 2>/dev/null || true + if ! grep -qE '^\s*gpu_mem\s*=' "$CONFIG_FILE" 2>/dev/null; then + echo "gpu_mem=$val" | sudo tee -a "$CONFIG_FILE" >/dev/null + fi + fi +} + +ensure_owned_by_iptv() { + sudo chown -R "$APP_USER:$APP_USER" "$APP_DIR" } -#---------------------------------------------------------- +pip_install_as_iptv() { + local cmd="$1" + sudo -u "$APP_USER" bash -lc "$cmd" +} + +#====================== INSTALL ======================# install_app() { echo "" echo "============================================================" - echo " RetroIPTVGuide Raspberry Pi Installer Agreement " + echo " RetroIPTVGuide Raspberry Pi Headless Installer " echo "============================================================" echo "" echo "This installer will perform the following actions:" - echo " - Detect Raspberry Pi model (3 or 4)" + echo " - Detect Raspberry Pi model (3, 4, or newer)" echo " - Install dependencies (Python3, ffmpeg, etc.)" - echo " - Clone or update RetroIPTVGuide into /opt/RetroIPTVGuide" + echo " - Create system user 'iptv' (if not present)" + echo " - Clone RetroIPTVGuide into /home/iptv/iptv-server" echo " - Configure Python virtual environment and systemd service" - echo " - Auto-configure GPU acceleration (KMS/Fake KMS)" + echo " - Auto-configure GPU memory for headless operation" + echo " - Enable the retroiptvguide service on boot" echo " - Optionally reboot when done" echo "" - read -p "Do you agree to these terms? (yes/no): " agreement - [[ "$agreement" != "yes" ]] && echo "Installation aborted." && exit 1 - - # Detect model - PI_MODEL=$(tr -d '\0' < /proc/device-tree/model) - if echo "$PI_MODEL" | grep -q "Raspberry Pi 4"; then PI_TYPE="pi4" - elif echo "$PI_MODEL" | grep -q "Raspberry Pi 3"; then PI_TYPE="pi3" - else PI_TYPE="unknown"; fi + echo "By continuing, you agree that:" + echo " - This software should only be run on internal networks." + echo " - It must not be exposed to the public Internet." + echo " - You accept all risks; no warranty is provided." + echo "" + + if [ "$AUTO_AGREE" = true ]; then + echo "[Auto-agree] Terms accepted via --agree flag." + else + read -p "Do you agree to these terms? (yes/no): " agreement + if [ "$agreement" != "yes" ]; then + echo "Installation aborted by user." + exit 1 + fi + echo "Agreement accepted. Continuing..." + fi + echo "" + + # Detect Pi model + PI_MODEL=$(tr -d '\0' < /proc/device-tree/model 2>/dev/null || echo "Unknown Model") + if echo "$PI_MODEL" | grep -q "Raspberry Pi 5"; then + PI_TYPE="pi5" + elif echo "$PI_MODEL" | grep -q "Raspberry Pi 4"; then + PI_TYPE="pi4" + elif echo "$PI_MODEL" | grep -q "Raspberry Pi 3"; then + PI_TYPE="pi3" + else + PI_TYPE="unknown" + fi echo "Detected board: $PI_MODEL ($PI_TYPE)" + echo "" - sudo apt update -y && sudo apt full-upgrade -y - sudo apt install -y git python3 python3-venv python3-pip ffmpeg mesa-utils v4l-utils raspi-config + # Create system user + if ! id "$APP_USER" &>/dev/null; then + echo "Creating user '$APP_USER'..." + sudo useradd -m -r -s /usr/sbin/nologin "$APP_USER" + fi + + # Prepare app dir + sudo mkdir -p "$APP_DIR" + ensure_owned_by_iptv + + # Update & deps (apt-get, script-safe) + echo "Installing dependencies..." + sudo apt-get update -y + sudo apt-get dist-upgrade -y + sudo apt-get install -y git python3 python3-venv python3-pip ffmpeg mesa-utils v4l-utils + # raspi-config is standard on Raspberry Pi OS; on Ubuntu it may be missing (we handle fallback in set_gpu_mem) + sudo apt-get install -y raspi-config || true - if [ ! -d "$APP_DIR" ]; then - sudo git clone https://github.com/thehack904/RetroIPTVGuide.git "$APP_DIR" + # Clone / update repo + if [ ! -d "$APP_DIR/.git" ]; then + sudo -u "$APP_USER" git clone https://github.com/thehack904/RetroIPTVGuide.git "$APP_DIR" else - cd "$APP_DIR" && sudo git pull + ( cd "$APP_DIR" && sudo -u "$APP_USER" git pull ) fi - cd "$APP_DIR" - sudo python3 -m venv venv - source venv/bin/activate - pip install --upgrade pip - [ -f requirements.txt ] && pip install -r requirements.txt || pip install Flask - deactivate + # Python venv & deps (as iptv user) + if [ ! -d "$APP_DIR/venv" ]; then + sudo -u "$APP_USER" python3 -m venv "$APP_DIR/venv" + fi + pip_install_as_iptv "source '$APP_DIR/venv/bin/activate' && pip install --upgrade pip" + if [ -f "$APP_DIR/requirements.txt" ]; then + pip_install_as_iptv "source '$APP_DIR/venv/bin/activate' && pip install -r '$APP_DIR/requirements.txt'" + else + pip_install_as_iptv "source '$APP_DIR/venv/bin/activate' && pip install Flask" + fi - sudo tee "$SERVICE_FILE" > /dev/null </dev/null < Date: Thu, 9 Oct 2025 11:09:28 -0500 Subject: [PATCH 09/41] Update retroiptv_rpi.sh --- retroiptv_rpi.sh | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/retroiptv_rpi.sh b/retroiptv_rpi.sh index ccbe44f..0fdff3d 100644 --- a/retroiptv_rpi.sh +++ b/retroiptv_rpi.sh @@ -205,6 +205,21 @@ EOF echo "Full log saved to: $LOG_FILE" echo "" + # --- Post-install verification --- + echo "Verifying service status..." + sleep 3 + if systemctl is-active --quiet retroiptvguide; then + echo "✅ Service is active." + if curl -fs http://localhost:5000 >/dev/null 2>&1; then + echo "✅ Web interface responding on port 5000." + else + echo "⚠️ Service active, but no HTTP response. Check logs in $LOG_FILE." + fi + else + echo "❌ Service not active. Run: sudo systemctl status retroiptvguide" + fi + echo "" + # Optional reboot prompt if [ "$AUTO_YES" = true ]; then # For unattended runs, perform a quick service check and skip reboot by default From 26d4dac371464dba8c4811d74c4a602b0c54d6b5 Mon Sep 17 00:00:00 2001 From: thehack904 <35552907+thehack904@users.noreply.github.com> Date: Thu, 9 Oct 2025 11:29:36 -0500 Subject: [PATCH 10/41] Update retroiptv_rpi.sh --- retroiptv_rpi.sh | 85 +++++++++++++++++++++++------------------------- 1 file changed, 40 insertions(+), 45 deletions(-) diff --git a/retroiptv_rpi.sh b/retroiptv_rpi.sh index 0fdff3d..7fda9bb 100644 --- a/retroiptv_rpi.sh +++ b/retroiptv_rpi.sh @@ -48,28 +48,20 @@ for arg in "$@"; do esac done -# --- Helpers --- +# --- Helper functions --- set_gpu_mem() { local val="$1" if command -v raspi-config >/dev/null 2>&1; then sudo raspi-config nonint set_config_var gpu_mem "$val" "$CONFIG_FILE" else - # Fallback: edit/append gpu_mem in /boot/config.txt sudo sed -i -E 's/^\s*gpu_mem\s*=.*/gpu_mem='"$val"'/g' "$CONFIG_FILE" 2>/dev/null || true if ! grep -qE '^\s*gpu_mem\s*=' "$CONFIG_FILE" 2>/dev/null; then echo "gpu_mem=$val" | sudo tee -a "$CONFIG_FILE" >/dev/null fi fi } - -ensure_owned_by_iptv() { - sudo chown -R "$APP_USER:$APP_USER" "$APP_DIR" -} - -pip_install_as_iptv() { - local cmd="$1" - sudo -u "$APP_USER" bash -lc "$cmd" -} +ensure_owned_by_iptv() { sudo chown -R "$APP_USER:$APP_USER" "$APP_DIR"; } +pip_install_as_iptv() { sudo -u "$APP_USER" bash -lc "$1"; } #====================== INSTALL ======================# install_app() { @@ -80,6 +72,7 @@ install_app() { echo "" echo "This installer will perform the following actions:" echo " - Detect Raspberry Pi model (3, 4, or newer)" + echo " - Check storage, RAM, and swap configuration" echo " - Install dependencies (Python3, ffmpeg, etc.)" echo " - Create system user 'iptv' (if not present)" echo " - Clone RetroIPTVGuide into /home/iptv/iptv-server" @@ -98,54 +91,62 @@ install_app() { echo "[Auto-agree] Terms accepted via --agree flag." else read -p "Do you agree to these terms? (yes/no): " agreement - if [ "$agreement" != "yes" ]; then - echo "Installation aborted by user." - exit 1 - fi + [[ "$agreement" != "yes" ]] && echo "Installation aborted." && exit 1 echo "Agreement accepted. Continuing..." fi echo "" # Detect Pi model PI_MODEL=$(tr -d '\0' < /proc/device-tree/model 2>/dev/null || echo "Unknown Model") - if echo "$PI_MODEL" | grep -q "Raspberry Pi 5"; then - PI_TYPE="pi5" - elif echo "$PI_MODEL" | grep -q "Raspberry Pi 4"; then - PI_TYPE="pi4" - elif echo "$PI_MODEL" | grep -q "Raspberry Pi 3"; then - PI_TYPE="pi3" - else - PI_TYPE="unknown" - fi + case "$PI_MODEL" in + *"Raspberry Pi 5"*) PI_TYPE="pi5" ;; + *"Raspberry Pi 4"*) PI_TYPE="pi4" ;; + *"Raspberry Pi 3"*) PI_TYPE="pi3" ;; + *) PI_TYPE="unknown" ;; + esac echo "Detected board: $PI_MODEL ($PI_TYPE)" echo "" - # Create system user + # Check SD card and swap + echo "Checking storage and memory..." + ROOT_DEV=$(df / | tail -1 | awk '{print $1}') + SD_SIZE=$(df -h / | awk 'NR==2 {print $2}') + MEM_TOTAL=$(awk '/MemTotal/ {print int($2/1024)}' /proc/meminfo) + SWAP_TOTAL=$(awk '/SwapTotal/ {print int($2/1024)}' /proc/meminfo) + echo "Root device: $ROOT_DEV" + echo "Storage size: $SD_SIZE" + echo "RAM: ${MEM_TOTAL}MB | Swap: ${SWAP_TOTAL}MB" + if [ "$MEM_TOTAL" -lt 1000 ] && [ "$SWAP_TOTAL" -lt 400 ]; then + echo "⚠️ Warning: <1GB RAM and <400MB swap — increase swap to 1GB for stability:" + echo " sudo dphys-swapfile swapoff && sudo sed -i 's/^CONF_SWAPSIZE=.*/CONF_SWAPSIZE=1024/' /etc/dphys-swapfile && sudo dphys-swapfile setup && sudo dphys-swapfile swapon" + fi + if df -BG / | awk 'NR==2 {exit ($2<8)}'; then + echo "⚠️ Warning: Root filesystem smaller than 8GB — limited space for logs/updates." + fi + echo "" + + # Create user if needed if ! id "$APP_USER" &>/dev/null; then echo "Creating user '$APP_USER'..." sudo useradd -m -r -s /usr/sbin/nologin "$APP_USER" fi - - # Prepare app dir sudo mkdir -p "$APP_DIR" ensure_owned_by_iptv - # Update & deps (apt-get, script-safe) + # Update & deps echo "Installing dependencies..." sudo apt-get update -y sudo apt-get dist-upgrade -y - sudo apt-get install -y git python3 python3-venv python3-pip ffmpeg mesa-utils v4l-utils - # raspi-config is standard on Raspberry Pi OS; on Ubuntu it may be missing (we handle fallback in set_gpu_mem) - sudo apt-get install -y raspi-config || true + sudo apt-get install -y git python3 python3-venv python3-pip ffmpeg mesa-utils v4l-utils raspi-config || true - # Clone / update repo + # Clone or update repo if [ ! -d "$APP_DIR/.git" ]; then sudo -u "$APP_USER" git clone https://github.com/thehack904/RetroIPTVGuide.git "$APP_DIR" else ( cd "$APP_DIR" && sudo -u "$APP_USER" git pull ) fi - # Python venv & deps (as iptv user) + # Python venv setup if [ ! -d "$APP_DIR/venv" ]; then sudo -u "$APP_USER" python3 -m venv "$APP_DIR/venv" fi @@ -155,15 +156,13 @@ install_app() { else pip_install_as_iptv "source '$APP_DIR/venv/bin/activate' && pip install Flask" fi - - # Ensure DB/data dirs if app expects them sudo -u "$APP_USER" mkdir -p "$APP_DIR/data" || true - # GPU memory per model (headless safe) + # GPU memory by model echo "Configuring GPU memory..." case "$PI_TYPE" in pi4|pi5) set_gpu_mem 256 ;; - pi3|unknown|*) set_gpu_mem 128 ;; + pi3|*) set_gpu_mem 128 ;; esac # systemd service @@ -184,7 +183,6 @@ Environment=FLASK_RUN_HOST=0.0.0.0 [Install] WantedBy=multi-user.target EOF - sudo systemctl daemon-reload sudo systemctl enable retroiptvguide sudo systemctl restart retroiptvguide @@ -220,19 +218,16 @@ EOF fi echo "" - # Optional reboot prompt - if [ "$AUTO_YES" = true ]; then - # For unattended runs, perform a quick service check and skip reboot by default - systemctl is-active --quiet retroiptvguide && echo "Service is active." || echo "Warning: service not active." - else - read -t 10 -p "Reboot now to ensure GPU memory takes effect? (Y/n, default Y in 10s): " R || R="Y" + # Optional reboot + if [ "$AUTO_YES" = false ]; then + read -t 10 -p "Reboot now to apply GPU memory? (Y/n, default Y in 10s): " R || R="Y" R=${R:-Y} if [[ "$R" =~ ^[Yy]$ ]]; then echo "Rebooting..." sleep 2 sudo reboot else - echo "Reboot skipped. Run 'sudo reboot' later to apply GPU memory if changed." + echo "Reboot skipped. Run 'sudo reboot' later if GPU memory changed." fi fi } From 999c8efd77194052991ae8029a6710b58afd7058 Mon Sep 17 00:00:00 2001 From: thehack904 <35552907+thehack904@users.noreply.github.com> Date: Thu, 9 Oct 2025 12:13:09 -0500 Subject: [PATCH 11/41] Update retroiptv_rpi.sh --- retroiptv_rpi.sh | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/retroiptv_rpi.sh b/retroiptv_rpi.sh index 7fda9bb..cac9547 100644 --- a/retroiptv_rpi.sh +++ b/retroiptv_rpi.sh @@ -52,12 +52,24 @@ done set_gpu_mem() { local val="$1" if command -v raspi-config >/dev/null 2>&1; then - sudo raspi-config nonint set_config_var gpu_mem "$val" "$CONFIG_FILE" + # Quietly apply GPU memory change and suppress unrelated warnings + sudo raspi-config nonint set_config_var gpu_mem "$val" "$CONFIG_FILE" 2>/dev/null || true + + # Verify it was written correctly + local current_val + current_val=$(grep -E "^gpu_mem=" "$CONFIG_FILE" 2>/dev/null | tail -n1 | cut -d'=' -f2) + if [ "$current_val" = "$val" ]; then + echo "✅ Verified: GPU memory successfully set to ${val}MB" | tee -a "$LOG_FILE" + else + echo "⚠️ Warning: Could not confirm gpu_mem=$val in $CONFIG_FILE" | tee -a "$LOG_FILE" + fi else + # Manual fallback if raspi-config missing sudo sed -i -E 's/^\s*gpu_mem\s*=.*/gpu_mem='"$val"'/g' "$CONFIG_FILE" 2>/dev/null || true if ! grep -qE '^\s*gpu_mem\s*=' "$CONFIG_FILE" 2>/dev/null; then echo "gpu_mem=$val" | sudo tee -a "$CONFIG_FILE" >/dev/null fi + echo "✅ Fallback: gpu_mem set manually to ${val}MB" | tee -a "$LOG_FILE" fi } ensure_owned_by_iptv() { sudo chown -R "$APP_USER:$APP_USER" "$APP_DIR"; } From b1718b3f52c5510a4ac5569e511353ee1ef91ba8 Mon Sep 17 00:00:00 2001 From: thehack904 <35552907+thehack904@users.noreply.github.com> Date: Thu, 9 Oct 2025 21:43:01 -0500 Subject: [PATCH 12/41] Update retroiptv_rpi.sh --- retroiptv_rpi.sh | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/retroiptv_rpi.sh b/retroiptv_rpi.sh index cac9547..81a4fdd 100644 --- a/retroiptv_rpi.sh +++ b/retroiptv_rpi.sh @@ -220,16 +220,28 @@ EOF sleep 3 if systemctl is-active --quiet retroiptvguide; then echo "✅ Service is active." - if curl -fs http://localhost:5000 >/dev/null 2>&1; then - echo "✅ Web interface responding on port 5000." - else - echo "⚠️ Service active, but no HTTP response. Check logs in $LOG_FILE." + echo "Waiting for web interface to start..." + local wait_time=0 + local max_wait=15 + while [ $wait_time -lt $max_wait ]; do + if curl -fs http://localhost:5000 >/dev/null 2>&1; then + echo "✅ Web interface responding on port 5000 (after ${wait_time}s)." + echo "✅ Verified: HTTP response received." | tee -a "$LOG_FILE" + break + fi + sleep 2 + wait_time=$((wait_time+2)) + done + if [ $wait_time -ge $max_wait ]; then + echo "⚠️ Service active, but no HTTP response after ${max_wait}s. Check logs in $LOG_FILE." + echo "⚠️ Possible slow startup on first run (SQLite or dependencies still initializing)." | tee -a "$LOG_FILE" fi else echo "❌ Service not active. Run: sudo systemctl status retroiptvguide" fi echo "" + # Optional reboot if [ "$AUTO_YES" = false ]; then read -t 10 -p "Reboot now to apply GPU memory? (Y/n, default Y in 10s): " R || R="Y" From 79ed758a49c410c16072e36defc0a6e3700c9539 Mon Sep 17 00:00:00 2001 From: thehack904 <35552907+thehack904@users.noreply.github.com> Date: Thu, 9 Oct 2025 21:57:31 -0500 Subject: [PATCH 13/41] Update install.sh --- install.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/install.sh b/install.sh index d17c79a..0197951 100644 --- a/install.sh +++ b/install.sh @@ -1,7 +1,9 @@ #!/bin/bash set -e -VERSION="3.0.1" +VERSION="3.1.0" # RetroIPTVGuide installer version +# RetroIPTVGuide Debian/Ubuntu Installer +# License: CC BY-NC-SA 4.0 TIMESTAMP=$(date +"%Y-%m-%d_%H-%M-%S") LOGFILE="install_${TIMESTAMP}.log" From c2db331afaf9c786818566449157b0e17e9b646e Mon Sep 17 00:00:00 2001 From: thehack904 <35552907+thehack904@users.noreply.github.com> Date: Thu, 9 Oct 2025 21:58:14 -0500 Subject: [PATCH 14/41] Update retroiptv_rpi.sh --- retroiptv_rpi.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/retroiptv_rpi.sh b/retroiptv_rpi.sh index 81a4fdd..8419932 100644 --- a/retroiptv_rpi.sh +++ b/retroiptv_rpi.sh @@ -1,9 +1,11 @@ #!/bin/bash +VERSION="3.1.0" # RetroIPTVGuide Raspberry Pi installer version # RetroIPTVGuide Raspberry Pi Installer (Headless, Pi3/4/5) # Installs to /home/iptv/iptv-server for consistency with Debian/Windows # Logs to /var/log/retroiptvguide/install-YYYYMMDD-HHMMSS.log # License: CC BY-NC-SA 4.0 + # --- Banner --- cat <<'EOF' ░█████████ ░██ ░██████░█████████ ░██████████░██ ░██ ░██████ ░██ ░██ From ba70c41fca8ec7e420a5d3fb60e9a5f89c2e61b0 Mon Sep 17 00:00:00 2001 From: thehack904 <35552907+thehack904@users.noreply.github.com> Date: Thu, 9 Oct 2025 21:58:40 -0500 Subject: [PATCH 15/41] Update app.py --- app.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app.py b/app.py index 47e405e..48e36ea 100644 --- a/app.py +++ b/app.py @@ -1,4 +1,4 @@ -APP_VERSION = "v3.0.1" +APP_VERSION = "v3.1.0" APP_RELEASE_DATE = "2025-09-26" from flask import Flask, render_template, request, redirect, url_for, flash From de15baea3f2e40c25aa5d5b9c1d64819475cf1a8 Mon Sep 17 00:00:00 2001 From: thehack904 <35552907+thehack904@users.noreply.github.com> Date: Thu, 9 Oct 2025 21:59:04 -0500 Subject: [PATCH 16/41] Update install_windows.ps1 --- install_windows.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/install_windows.ps1 b/install_windows.ps1 index 2bf2ccf..5e1d837 100644 --- a/install_windows.ps1 +++ b/install_windows.ps1 @@ -1,4 +1,4 @@ -$VERSION = "3.0.0" +$VERSION = "3.1.0" <# RetroIPTVGuide Windows Installer Clean version with only prerequisite checks and service setup From c77bcc36da880a5e811010ed49a00a4764822667 Mon Sep 17 00:00:00 2001 From: thehack904 <35552907+thehack904@users.noreply.github.com> Date: Thu, 9 Oct 2025 21:59:21 -0500 Subject: [PATCH 17/41] Update uninstall.sh --- uninstall.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/uninstall.sh b/uninstall.sh index dfd6b21..4532900 100644 --- a/uninstall.sh +++ b/uninstall.sh @@ -1,4 +1,4 @@ -VERSION="3.0.0" +VERSION="3.1.0" #!/usr/bin/env bash # RetroIPTVGuide uninstall script # Run with sudo on Linux; run from Administrator shell on Windows From 18bf4cd115c9ee28c16c69e3d6602480cc153399 Mon Sep 17 00:00:00 2001 From: thehack904 <35552907+thehack904@users.noreply.github.com> Date: Thu, 9 Oct 2025 21:59:37 -0500 Subject: [PATCH 18/41] Update uninstall_windows.ps1 --- uninstall_windows.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/uninstall_windows.ps1 b/uninstall_windows.ps1 index ff49b83..9b97334 100644 --- a/uninstall_windows.ps1 +++ b/uninstall_windows.ps1 @@ -1,4 +1,4 @@ -$VERSION = "3.0.0" +$VERSION = "3.1.0" # RetroIPTVGuide Windows Uninstaller # ================================== From 3d1c4a54340a0f8c73846f639decdcb7ade5c44f Mon Sep 17 00:00:00 2001 From: thehack904 <35552907+thehack904@users.noreply.github.com> Date: Thu, 9 Oct 2025 22:06:55 -0500 Subject: [PATCH 19/41] Update bump_version.py --- bump_version.py | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/bump_version.py b/bump_version.py index d62f28b..83b3f40 100644 --- a/bump_version.py +++ b/bump_version.py @@ -13,12 +13,16 @@ import subprocess from pathlib import Path +# --- FILE TARGETS --- APP_FILE = Path("app.py") CHANGELOG_FILE = Path("CHANGELOG.md") INSTALL_WIN = Path("install_windows.ps1") UNINSTALL_WIN = Path("uninstall_windows.ps1") UNINSTALL_SH = Path("uninstall.sh") +INSTALL_SH = Path("install.sh") +RPI_INSTALL_SH = Path("retroiptv_rpi.sh") +# ------------------------------------------------------- def update_app_py(new_version: str): """Update APP_VERSION in app.py, add if missing""" content = APP_FILE.read_text().splitlines() @@ -80,7 +84,6 @@ def update_script_version(file: Path, new_version: str, is_bash: bool): updated = [] found = False - # Regex for version line if is_bash: pattern = re.compile(r'^\s*VERSION\s*=\s*".*"') replacement = f'VERSION="{new_version}"' @@ -96,7 +99,6 @@ def update_script_version(file: Path, new_version: str, is_bash: bool): updated.append(line) if not found: - # Insert at top updated.insert(0, replacement) print(f"ℹ️ VERSION not found in {file}, added at top") @@ -107,8 +109,14 @@ def git_commit(new_version: str): """Commit changes with git""" try: subprocess.run( - ["git", "add", str(APP_FILE), str(CHANGELOG_FILE), - str(INSTALL_WIN), str(UNINSTALL_WIN), str(UNINSTALL_SH)], + ["git", "add", + str(APP_FILE), + str(CHANGELOG_FILE), + str(INSTALL_WIN), + str(UNINSTALL_WIN), + str(UNINSTALL_SH), + str(INSTALL_SH), + str(RPI_INSTALL_SH)], check=True ) subprocess.run( @@ -130,14 +138,15 @@ def main(): update_app_py(new_version) update_changelog(new_version) - # Update other scripts + # Update all installers/uninstallers update_script_version(INSTALL_WIN, new_version, is_bash=False) update_script_version(UNINSTALL_WIN, new_version, is_bash=False) update_script_version(UNINSTALL_SH, new_version, is_bash=True) + update_script_version(INSTALL_SH, new_version, is_bash=True) + update_script_version(RPI_INSTALL_SH, new_version, is_bash=True) if do_commit: git_commit(new_version) if __name__ == "__main__": main() - From 1b946c5aba2e18f716796a8db60808596a650841 Mon Sep 17 00:00:00 2001 From: thehack904 <35552907+thehack904@users.noreply.github.com> Date: Thu, 9 Oct 2025 22:11:12 -0500 Subject: [PATCH 20/41] Update CHANGELOG.md --- CHANGELOG.md | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 80d56f4..c8a64c4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -# đź“‘ Changelog +## Changelog All notable changes to this project will be documented here. Format based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). @@ -12,6 +12,30 @@ This project follows [Semantic Versioning](https://semver.org/). - Planned: move logs to SQLite DB. - Planned: log filtering and pagination. +--- +## v3.1.0 - 2025-10-09 +### Added +- New **RetroIPTVGuide Raspberry Pi headless installer** (`retroiptv_rpi.sh`) + - Detects Raspberry Pi 3 / 4 / 5 models and auto-configures GPU memory + - Creates dedicated `iptv` user and installs to `/home/iptv/iptv-server` + - Logs all activity to `/var/log/retroiptvguide/install-YYYYMMDD-HHMMSS.log` + - Adds `--yes` and `--agree` flags for fully unattended installs + - Includes automatic environment checks for SD card size, RAM, and swap + +### Changed +- **Installer alignment:** + - Raspberry Pi installer now mirrors Debian / Windows structure + - Replaced all `apt` usage with `apt-get` for stable scripting + - Added verified, silenced `set_gpu_mem()` function that suppresses `rfkill` Wi-Fi warnings + - Enhanced post-install verification loop (up to 15 s) to confirm Flask web service readiness +- **bump_version.py:** now updates both `install.sh` and `retroiptv_rpi.sh` versions automatically +- Unified version tagging across all installers (`VERSION="x.y.z"` format) + +### Fixed +- Eliminated false-positive Wi-Fi “blocked by rfkill” messages during GPU configuration +- Corrected early-trigger HTTP service check timing on slower Pi 3/4 boards +- Ensured consistent permissions and ownership under `/home/iptv` + --- ## [v3.0.1] - 2025-10-07 From 19fe669b01f3c2b7a49bfc4131d1a91529565be0 Mon Sep 17 00:00:00 2001 From: thehack904 <35552907+thehack904@users.noreply.github.com> Date: Thu, 9 Oct 2025 22:25:00 -0500 Subject: [PATCH 21/41] Document Updates for 3.1.0 --- INSTALL.md | 120 ++++++++++++++++++++++++++++++----------------------- README.md | 34 +++++++++++---- ROADMAP.md | 74 +++++++++++++++++++-------------- 3 files changed, 136 insertions(+), 92 deletions(-) diff --git a/INSTALL.md b/INSTALL.md index 827c03e..27036fa 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -1,10 +1,13 @@ # Installation Guide +**Version:** v3.1.0 +**Last Updated:** 2025-10-09 + ## Requirements - Python 3.10+ (Linux) / Python 3.12+ (Windows) -- **Linux (Debian/Ubuntu with systemd)** or **Windows 10/11** +- **Linux (Debian/Ubuntu with systemd)**, **Windows 10/11**, or **Raspberry Pi 3 / 4 / 5 (Headless OS)** - Administrative privileges: - - **Linux/WSL:** run install/uninstall with `sudo` + - **Linux/WSL/Raspberry Pi:** run install/uninstall with `sudo` - **Windows:** run from an Administrator **PowerShell** session --- @@ -30,19 +33,19 @@ sudo ./install.sh ``` **What the installer does (Linux/WSL):** -- Detects Linux/WSL environment -- Ensures script is run with sudo -- Creates a system user `iptv` -- Installs into `/home/iptv/iptv-server` -- Ensures `python3-venv` is installed -- Creates Python virtual environment and installs dependencies -- Creates and enables the `iptv-server` systemd service -- Starts the service +- Detects Linux/WSL environment +- Ensures script is run with sudo +- Creates a system user `iptv` +- Installs into `/home/iptv/iptv-server` +- Ensures `python3-venv` is installed +- Creates Python virtual environment and installs dependencies +- Creates and enables the `iptv-server` systemd service +- Starts the service - Logs the install to `install_YYYY-MM-DD_HH-MM-SS.log` --- -### Windows 10/11 +### Windows 10 / 11 Run this one-liner from an **Administrator PowerShell** prompt: @@ -51,18 +54,55 @@ Invoke-WebRequest https://github.com/thehack904/RetroIPTVGuide/archive/refs/head ``` **What the installer does (Windows):** -- Bootstraps Chocolatey (if missing) -- Installs dependencies: `python`, `git`, `nssm` -- Registers Windows App Paths for `python` / `python3` -- Adds Python to Git Bash (`~/.bashrc`) -- Clones RetroIPTVGuide and runs `install.sh` under Git Bash to set up venv + requirements -- Creates an NSSM service to run `venv\Scripts\python.exe app.py` -- Opens Windows Firewall port 5000 -- Starts the RetroIPTVGuide service +- Bootstraps Chocolatey (if missing) +- Installs dependencies: `python`, `git`, `nssm` +- Registers Windows App Paths for `python` / `python3` +- Adds Python to Git Bash (`~/.bashrc`) +- Clones RetroIPTVGuide and runs `install.sh` under Git Bash to set up venv + requirements +- Creates an NSSM service to run `venv\Scripts\python.exe app.py` +- Opens Windows Firewall port 5000 +- Starts the RetroIPTVGuide service - Logs the install to `install_YYYY-MM-DD_HH-MM-SS.log` --- +### Raspberry Pi 3 / 4 / 5 (Headless Edition) + +#### Interactive install +```bash +curl -sSL https://raw.githubusercontent.com/thehack904/RetroIPTVGuide/refs/heads/dev/retroiptv_rpi.sh | sudo bash -s install +``` + +#### Unattended / non-interactive +```bash +curl -sSL https://raw.githubusercontent.com/thehack904/RetroIPTVGuide/refs/heads/dev/retroiptv_rpi.sh | sudo bash -s install --yes --agree +``` + +**What the installer does (Raspberry Pi):** +- Detects Pi model (3 / 4 / 5) +- Installs required packages (`python3-venv`, `ffmpeg`, `git`, etc.) using `apt-get` +- Creates user `iptv` and installs into `/home/iptv/iptv-server` +- Configures GPU memory automatically (128 MB on Pi 3 / 256 MB on Pi 4/5) +- Sets up Python virtual environment and dependencies +- Creates systemd service `retroiptvguide` +- Performs post-install HTTP check (localhost:5000) with up-to-15 s polling +- Logs all activity to `/var/log/retroiptvguide/install-TIMESTAMP.log` +- Optionally reboots to apply GPU memory changes + +**Requirements** +- Raspberry Pi OS (Bookworm or later) +- Minimum 8 GB SD card and 1 GB RAM (512 MB swap recommended) +- SSH or console access with sudo + +**Access** +``` +http://:5000 +``` +Default login: `admin / strongpassword123` +⚠️ This is a **BETA** build for internal network use only. + +--- + ## Access Once installed, open your browser: @@ -85,22 +125,7 @@ sudo -u iptv bash -H -c "cd /home/iptv/iptv-server && git fetch --all && git res ``` or -#### Step-by-step -```bash -sudo -u iptv bash -H -cd /home/iptv/iptv-server -git fetch --all -git reset --hard origin/main -exit -sudo systemctl restart iptv-server.service -``` - ---- - -### Windows 10/11 - -From an **Administrator PowerShell** prompt, go to your RetroIPTVGuide folder and run: - +### Windows 10 / 11 ```powershell git fetch --all ; git reset --hard origin/main ; Restart-Service RetroIPTVGuide ``` @@ -128,13 +153,10 @@ sudo chmod +x uninstall.sh sudo ./uninstall.sh ``` -**What the uninstaller does (Linux/WSL):** -- Stops and disables the systemd service -- Removes the systemd unit file -- Deletes the `iptv` system user and related logs -- Removes the Python virtual environment - ---- +### Raspberry Pi +```bash +sudo ./retroiptv_rpi.sh uninstall --yes +``` ### Windows From an Administrator PowerShell prompt: @@ -142,22 +164,14 @@ From an Administrator PowerShell prompt: .\uninstall_windows.ps1 ``` -**What the uninstaller does (Windows):** -- Stops and removes the NSSM service -- Removes the Python virtual environment -- Deletes the Windows Firewall rule (port 5000) -- Lists remaining Chocolatey packages -- Prompts whether to uninstall **all Chocolatey packages (including Chocolatey itself)** - +**Each uninstaller stops its service, removes environment files, and cleans logs.** ⚠️ To completely remove the project, manually delete the project folder after uninstalling. - --- ## License -Licensed under CC BY-NC-SA 4.0. See LICENSE for details. +Licensed under CC BY-NC-SA 4.0. See `LICENSE` for details. --- ⚠️ **Initial BETA Notice** -This project is currently in **BETA**. -It should **not** be exposed directly to the Internet or used in production without additional hardening. +This project is currently in **BETA** and should **not** be exposed directly to the Internet or used in production without additional hardening. diff --git a/README.md b/README.md index 1cbdb8c..64a028e 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # RetroIPTVGuide -![Version](https://img.shields.io/badge/version-v3.0.1-blue) +![Version](https://img.shields.io/badge/version-v3.1.0-blue) RetroIPTVGuide is an IPTV Web Interface inspired by 90s/2000s cable TV guides. It is designed to work with [ErsatzTV](https://ersatztv.org/) [(GitRepo)](https://github.com/ErsatzTV/ErsatzTV/tree/main) but supports any `.m3u`, `.m3u8`, and `.xml` IPTV source. @@ -14,7 +14,19 @@ It is designed to work with [ErsatzTV](https://ersatztv.org/) [(GitRepo)](https: --- -## ✨ Features (v3.0.1) +## ✨ Features (v3.1.0) + +### 🆕 Raspberry Pi Headless Support +- Full **Raspberry Pi installer (`retroiptv_rpi.sh`)** added. +- Detects Pi 3 / 4 / 5 hardware and automatically sets GPU memory (128MB / 256MB). +- Installs to `/home/iptv/iptv-server` using system user `iptv`. +- Configures Python virtual environment and creates a systemd service `retroiptvguide`. +- Logs everything to `/var/log/retroiptvguide/install-TIMESTAMP.log`. +- Supports `--yes` (skip confirmations) and `--agree` (auto-accept license). +- Post-install check verifies Flask service on port 5000. +- Optional reboot prompt applies GPU memory changes. + +--- ### 🔑 User Authentication - Login/logout system with hashed passwords. @@ -62,9 +74,12 @@ It is designed to work with [ErsatzTV](https://ersatztv.org/) [(GitRepo)](https: - Automatic initialization of `users.db` and `tuners.db` on first run. - SQLite databases use WAL mode for better concurrency. - Preloads tuner/channel/guide data from DB on startup. -- **Cross-platform installers (Linux/Windows)**. -- **Uninstaller scripts (Linux/Windows)**. -- **Automated version bump tool (`bump_version.py`)**. +- **Cross-platform installers:** + - Linux / WSL (`install.sh`) + - Windows (`install_windows.ps1`) + - Raspberry Pi (`retroiptv_rpi.sh`) +- **Uninstaller scripts for all platforms** +- **Automated version bump tool (`bump_version.py`)** — now updates both `install.sh` and `retroiptv_rpi.sh`. --- @@ -72,6 +87,7 @@ It is designed to work with [ErsatzTV](https://ersatztv.org/) [(GitRepo)](https: | Version | Date | Key Features | |----------|------|---------------| +| **v3.1.0** | 2025-10-09 | Raspberry Pi installer, verified GPU setup, improved HTTP service check | | **v3.0.1** | 2025-10-07 | EPG fallback system, tuner refresh fix, login redesign | | **v3.0.0** | 2025-10-03 | Windows installer/uninstaller, cross-platform setup, unified UI | | **v2.3.x** | 2025-09 | Unified theming, About page, installer logging, tuner rename/delete | @@ -94,6 +110,7 @@ RetroIPTVGuide is compatible with all modern browsers: - **Ubuntu 24.04 (desktop/server)** - **TrueNAS SCALE (Docker/Podman)** - **Windows 10 / 11** +- **Raspberry Pi 3B+ / 4 / 5 (Raspberry Pi OS Bookworm)** - **macOS Monterey / Ventura** - **iOS (mobile/tablet)** - **Android (Samsung / Pixel)** @@ -103,7 +120,8 @@ RetroIPTVGuide is compatible with all modern browsers: ## 🛠️ Installation Platforms - Debian-based Linux (Ubuntu, Pop!\_OS, Mint) - Windows 10/11 (via PowerShell + NSSM) -- MacOS (manual install or future installer support) +- Raspberry Pi 3 / 4 / 5 (Headless OS, `retroiptv_rpi.sh`) +- macOS (manual install or future installer support) --- @@ -154,8 +172,8 @@ See [ROADMAP.md](ROADMAP.md) for full details. - **Repo:** [RetroIPTVGuide](https://github.com/thehack904/RetroIPTVGuide) - **Maintainer:** J.H. - **License:** [Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International (CC BY-NC-SA 4.0)](https://creativecommons.org/licenses/by-nc-sa/4.0/) -- **Version:** v3.0.1 -- **Release Date:** 2025-10-07 +- **Version:** v3.1.0 +- **Release Date:** 2025-10-09 --- diff --git a/ROADMAP.md b/ROADMAP.md index a659ab9..383886a 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -10,7 +10,7 @@ These are **not yet implemented**, but provide a development path for future rel ### 1. Tuner Management - [x] Add ability to **add/remove tuners** from the UI (v2.3.0). - [x] Add ability to rename tuners via the UI (v2.3.0). -- [ ] Support for **.m3u8 single-channel playlists** as tuner sources (planned v3.1.0). +- [ ] Support for **.m3u8 single-channel playlists** as tuner sources (planned v3.2.0). - Option A: Special-case `.m3u8` handling in parser. - Option B: Add explicit `hls` column to `tuners.db`. - [x] Validate tuner URLs (ping/check format before saving) (v2.0.0). @@ -22,6 +22,7 @@ These are **not yet implemented**, but provide a development path for future rel - [ ] Add system health checks (e.g., tuner reachability, XMLTV freshness) to logs. - [x] **Admin log management**: add button/route to clear logs (with confirmation) (v2.3.1). - [x] Display log file size on logs page (v2.3.1) +- [x] Post-install HTTP service verification added in Pi installer (v3.1.0) ### 3. Guide & Playback - [ ] Add **search/filter box** to guide for channels/programs. @@ -39,17 +40,22 @@ These are **not yet implemented**, but provide a development path for future rel - [ ] Unify CSS across all templates (minimize inline styles). - [ ] Make guide responsive (mobile/tablet view). - [ ] Add dark/light theme auto-detect from browser/system. -- [ ] Frozen header Timeline to prevent scrolling with channel listing +- [ ] Frozen header Timeline to prevent scrolling with channel listing - [x] About page under Settings menu (v2.3.1) ### 6. Cross-platform -- [ ] Create installable container. -- [ ] Create MacOS install/executable. -- [x] Create Microsoft Windows install/executable (full support via PowerShell + NSSM service) (v3.0.0) -- [x] Add uninstall_windows.ps1 and uninstall.bat (v3.0.0) -- [x] Windows installer now bootstraps Chocolatey, installs Python, Git, NSSM, and configures service (v3.0.0) +- [x] Create installable container. +- [ ] Create MacOS install/executable. +- [x] Create Microsoft Windows install/executable (full support via PowerShell + NSSM service) (v3.0.0) +- [x] Add uninstall_windows.ps1 and uninstall.bat (v3.0.0) +- [x] Windows installer bootstraps Chocolatey, installs Python, Git, NSSM, and configures service (v3.0.0) - [x] Windows uninstaller cleans service, firewall rule, and optionally removes Chocolatey (v3.0.0) - - [ ] Validate/test installer fully on Windows environments + - [ ] Validate/test installer fully on Windows environments +- [x] **Add Raspberry Pi headless installer (v3.1.0)** + - Detects Pi 3 / 4 / 5 models and sets GPU memory dynamically + - Installs under `/home/iptv/iptv-server` using user `iptv` + - Adds post-install HTTP verification and log summary + - Logs full install to `/var/log/retroiptvguide/install-TIMESTAMP.log` ### 7. New Features - [ ] Add the ability to have an auto play video stream upon login from a specific channel (Ersatz currently) to act similar to the 90/2000's tv guide that played "Commercials" until a channel was selected. @@ -59,28 +65,36 @@ These are **not yet implemented**, but provide a development path for future rel - [ ] Add **safety checks** in `add_tuner()`: - Prevent inserting duplicate tuner names. - Validate XML/M3U URLs are not empty before committing to DB. +- [x] Add **GPU verification** after `raspi-config` call (v3.1.0). +- [x] Suppress `rfkill` Wi-Fi message during GPU configuration (v3.1.0). +- [x] Post-install adaptive HTTP check loop (15s poll) (v3.1.0). --- ## ⚙️ Technical Improvements -- [x] Add uninstall.sh (v2.3.0) - - [ ] Validate/test uninstall script fully on Windows environments -- [ ] Add https support +- [x] Add uninstall.sh (v2.3.0). + - [ ] Validate/test uninstall script fully on Windows environments. +- [ ] Add HTTPS support. - [ ] Refactor tuner handling to rely only on DB (remove in-memory fallback). - [ ] Add migrations for DB changes (via Alembic or custom script). - [ ] Containerize app (Dockerfile + Compose for deployment). - [ ] Add test suite for tuner parsing, authentication, and logging. -- [x] **Automated version bump tool** (`bump_version.py`) that updates `APP_VERSION` in `app.py` and creates a new section in `CHANGELOG.md` (v2.3.1). +- [x] **Automated version bump tool** (`bump_version.py`) now updates: + - `APP_VERSION` in `app.py` + - `install.sh` + - `retroiptv_rpi.sh` + - Adds new section in `CHANGELOG.md` (v3.1.0). --- ## 📅 Priority Suggestions -- Short term: (none — unified UI headers already completed in v2.0.0). -- Medium term: log filtering (still pending). -- Medium term: Test and harden installer/uninstaller on mixed Windows environments (v3.0.0 complete, further refinements planned). -- Long term: .m3u8 support, DB logs, recording functionality. +- Short term: finalize Pi installer documentation and verify GPU/swap checks (v3.1.x). +- Medium term: `.m3u8` tuner support and DB-based logs (v3.2.x). +- Long term: full HTTPS and container deployment. -## 💻🥧 Installer Enhancement: Kiosk vs Headless Mode (Planned) +--- + +## 🍓 Installer Enhancement: Kiosk vs Headless Mode (Planned) **Target Version:** v3.2.0 **Status:** Planned **Effort:** Medium @@ -93,20 +107,18 @@ These are **not yet implemented**, but provide a development path for future rel --- -## ✅ Completed -- [x] Unified theming across all admin/user pages with Themes submenu and persistent setTheme logic (v2.3.2) -- [x] Tuner add/remove via UI (v2.3.0). -- [x] Tuner rename via UI (v2.3.0). -- [x] Tuner delete via UI (v2.3.0). -- [x] Tuner URL validation (v2.0.0). -- [x] Unified UI headers across templates (v2.0.0). -- [x] Installer logging (timestamped log files) (v2.3.0). -- [x] Environment detection in `install.sh` (Linux, WSL, Git Bash) (v2.3.0). -- [x] Unified cross-platform `install.sh` (v2.3.0). -- [x] Cross-platform `uninstall.sh` with sudo/admin checks and safe cleanup (v2.3.0). -- [x] Basic Windows installer support (Git Bash + PowerShell bootstrap) (v2.3.0). +## ✅ Completed (v3.1.0) +- [x] **Raspberry Pi headless installer completed** (`retroiptv_rpi.sh`). +- [x] Aligned Pi installer with Debian/Windows structure. +- [x] Added logging to `/var/log/retroiptvguide/`. +- [x] Added adaptive HTTP service verification. +- [x] Added GPU verification with silent `raspi-config` call. +- [x] Added system resource check (SD card size, RAM, swap). +- [x] Integrated `--yes` and `--agree` installer flags. +- [x] Verified functionality on Pi 3 and Pi 4. +--- ## ✅ Completed (v3.0.0) -- [x] Full Windows installer/uninstaller support with NSSM service, firewall rule, and Chocolatey integration (v3.0.0). -- [x] Documentation updates (README.md, INSTALL.md) to reflect Windows support (v3.0.0). +- [x] Full Windows installer/uninstaller support with NSSM service, firewall rule, and Chocolatey integration. +- [x] Documentation updates (README.md, INSTALL.md) to reflect Windows support. From 882ba1864c4ceaccc316760883908f4f7424d75a Mon Sep 17 00:00:00 2001 From: thehack904 <35552907+thehack904@users.noreply.github.com> Date: Thu, 9 Oct 2025 22:43:14 -0500 Subject: [PATCH 22/41] Update INSTALL.md --- INSTALL.md | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/INSTALL.md b/INSTALL.md index 27036fa..1716881 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -123,7 +123,11 @@ Default login: **admin / strongpassword123** ```bash sudo -u iptv bash -H -c "cd /home/iptv/iptv-server && git fetch --all && git reset --hard origin/main" && sudo systemctl daemon-reload && sudo systemctl restart iptv-server.service ``` -or + +### Raspberry Pi +```bash +sudo -u iptv bash -H -c "cd /home/iptv/iptv-server && git fetch --all && git reset --hard origin/main" && sudo systemctl daemon-reload && sudo systemctl restart retroiptvguide.service +``` ### Windows 10 / 11 ```powershell @@ -149,13 +153,12 @@ This will: ### Linux / WSL ```bash -sudo chmod +x uninstall.sh -sudo ./uninstall.sh +sudo -u iptv bash -H -c "cd /home/iptv/iptv-server && sudo bash /home/iptv/iptv-server/uninstall.sh ``` ### Raspberry Pi ```bash -sudo ./retroiptv_rpi.sh uninstall --yes +curl -sSL https://raw.githubusercontent.com/thehack904/RetroIPTVGuide/refs/heads/main/retroiptv_rpi.sh | sudo bash -s uninstall --yes ``` ### Windows From ee2c111e4e7da26937b82e4ef35e3b6fff864d5c Mon Sep 17 00:00:00 2001 From: thehack904 <35552907+thehack904@users.noreply.github.com> Date: Fri, 10 Oct 2025 15:33:20 -0500 Subject: [PATCH 23/41] Update INSTALL.md --- INSTALL.md | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/INSTALL.md b/INSTALL.md index 1716881..1e96847 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -94,13 +94,6 @@ curl -sSL https://raw.githubusercontent.com/thehack904/RetroIPTVGuide/refs/heads - Minimum 8 GB SD card and 1 GB RAM (512 MB swap recommended) - SSH or console access with sudo -**Access** -``` -http://:5000 -``` -Default login: `admin / strongpassword123` -⚠️ This is a **BETA** build for internal network use only. - --- ## Access @@ -112,6 +105,7 @@ http://:5000 ``` Default login: **admin / strongpassword123** +⚠️ This is a **BETA** build for internal network use only. --- @@ -153,7 +147,7 @@ This will: ### Linux / WSL ```bash -sudo -u iptv bash -H -c "cd /home/iptv/iptv-server && sudo bash /home/iptv/iptv-server/uninstall.sh +sudo -u iptv bash -H -c "cd /home/iptv/iptv-server" && sudo bash /home/iptv/iptv-server/uninstall.sh ``` ### Raspberry Pi From c59b3d4ba0a0a75b591d44d710f410df0bd07189 Mon Sep 17 00:00:00 2001 From: thehack904 <35552907+thehack904@users.noreply.github.com> Date: Fri, 10 Oct 2025 21:17:53 -0500 Subject: [PATCH 24/41] Update INSTALL.md --- INSTALL.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/INSTALL.md b/INSTALL.md index 1e96847..354c971 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -70,12 +70,12 @@ Invoke-WebRequest https://github.com/thehack904/RetroIPTVGuide/archive/refs/head #### Interactive install ```bash -curl -sSL https://raw.githubusercontent.com/thehack904/RetroIPTVGuide/refs/heads/dev/retroiptv_rpi.sh | sudo bash -s install +curl -sSL https://raw.githubusercontent.com/thehack904/RetroIPTVGuide/refs/heads/main/retroiptv_rpi.sh | sudo bash -s install ``` #### Unattended / non-interactive ```bash -curl -sSL https://raw.githubusercontent.com/thehack904/RetroIPTVGuide/refs/heads/dev/retroiptv_rpi.sh | sudo bash -s install --yes --agree +curl -sSL https://raw.githubusercontent.com/thehack904/RetroIPTVGuide/refs/heads/main/retroiptv_rpi.sh | sudo bash -s install --yes --agree ``` **What the installer does (Raspberry Pi):** From 413521b21a39c45e9d4b542efa0baf7895762a78 Mon Sep 17 00:00:00 2001 From: thehack904 <35552907+thehack904@users.noreply.github.com> Date: Sat, 11 Oct 2025 07:23:52 -0500 Subject: [PATCH 25/41] Create docker-publish.yml Add GHCR publish workflow --- .github/workflows/docker-publish.yml | 52 ++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 .github/workflows/docker-publish.yml diff --git a/.github/workflows/docker-publish.yml b/.github/workflows/docker-publish.yml new file mode 100644 index 0000000..a42b8b1 --- /dev/null +++ b/.github/workflows/docker-publish.yml @@ -0,0 +1,52 @@ +name: 🚀 Build and Publish RetroIPTVGuide to GHCR + +on: + push: + branches: [ main ] + tags: + - 'v*' + workflow_dispatch: + +env: + REGISTRY: ghcr.io + IMAGE_NAME: ${{ github.repository }} + +jobs: + build-and-push: + runs-on: ubuntu-latest + + permissions: + contents: read + packages: write + id-token: write + + steps: + - name: 🧾 Checkout repository + uses: actions/checkout@v4 + + - name: 🔑 Log in to GitHub Container Registry + uses: docker/login-action@v3 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: 🏗️ Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: 🧱 Build and Push Docker image + uses: docker/build-push-action@v6 + with: + context: . + push: true + tags: | + ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest + ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.ref_name }} + platforms: linux/amd64,linux/arm64 + labels: | + org.opencontainers.image.source=${{ github.repositoryUrl }} + org.opencontainers.image.description=RetroIPTVGuide Flask + SQLite Web App + org.opencontainers.image.licenses=CC-BY-NC-SA-4.0 + + - name: 🧹 Cleanup local images (optional) + run: docker image prune -af || true From db4be3d587a16b42af6b32564da6257548a51534 Mon Sep 17 00:00:00 2001 From: thehack904 <35552907+thehack904@users.noreply.github.com> Date: Sat, 11 Oct 2025 07:27:36 -0500 Subject: [PATCH 26/41] Update docker-publish.yml --- .github/workflows/docker-publish.yml | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/.github/workflows/docker-publish.yml b/.github/workflows/docker-publish.yml index a42b8b1..bd6dd07 100644 --- a/.github/workflows/docker-publish.yml +++ b/.github/workflows/docker-publish.yml @@ -9,7 +9,7 @@ on: env: REGISTRY: ghcr.io - IMAGE_NAME: ${{ github.repository }} + IMAGE_NAME: ${{ github.repository }} # We'll lowercase it below jobs: build-and-push: @@ -24,6 +24,12 @@ jobs: - name: 🧾 Checkout repository uses: actions/checkout@v4 + - name: 🔡 Normalize image name to lowercase + id: prep + run: | + IMAGE_NAME_LOWER=$(echo "${{ github.repository }}" | tr '[:upper:]' '[:lower:]') + echo "IMAGE_NAME_LOWER=${IMAGE_NAME_LOWER}" >> $GITHUB_ENV + - name: 🔑 Log in to GitHub Container Registry uses: docker/login-action@v3 with: @@ -40,13 +46,14 @@ jobs: context: . push: true tags: | - ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest - ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.ref_name }} + ${{ env.REGISTRY }}/${{ env.IMAGE_NAME_LOWER }}:latest + ${{ env.REGISTRY }}/${{ env.IMAGE_NAME_LOWER }}:${{ github.ref_name }} platforms: linux/amd64,linux/arm64 labels: | org.opencontainers.image.source=${{ github.repositoryUrl }} org.opencontainers.image.description=RetroIPTVGuide Flask + SQLite Web App org.opencontainers.image.licenses=CC-BY-NC-SA-4.0 - - name: 🧹 Cleanup local images (optional) + - name: 🧹 Cleanup local images run: docker image prune -af || true + From 2dddbe77b7e1dd41ca896fe84485c90dc8350d36 Mon Sep 17 00:00:00 2001 From: thehack904 <35552907+thehack904@users.noreply.github.com> Date: Sat, 11 Oct 2025 07:35:17 -0500 Subject: [PATCH 27/41] Create Dockerfile Add Dockerfile for GHCR + TrueNAS deployment --- Dockerfile | 57 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 Dockerfile diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..d91bdf4 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,57 @@ +# ============================================ +# RetroIPTVGuide - Dockerfile +# ============================================ +FROM python:3.12-slim + +LABEL maintainer="thehack904" +LABEL description="RetroIPTVGuide Flask + SQLite Web App" +LABEL version="3.1.0" + +# -------------------------------------------- +# Environment setup +# -------------------------------------------- +ENV PYTHONUNBUFFERED=1 \ + PIP_NO_CACHE_DIR=1 \ + APP_HOME=/app + +WORKDIR $APP_HOME + +# -------------------------------------------- +# Install minimal system dependencies +# -------------------------------------------- +RUN apt-get update && apt-get install -y --no-install-recommends \ + tini \ + curl \ + && rm -rf /var/lib/apt/lists/* + +# -------------------------------------------- +# Copy and install Python dependencies +# -------------------------------------------- +COPY requirements.txt ./ +RUN pip install --upgrade pip && pip install -r requirements.txt + +# -------------------------------------------- +# Copy application code +# -------------------------------------------- +COPY . . + +# -------------------------------------------- +# Create persistent directories for TrueNAS mounts +# -------------------------------------------- +RUN mkdir -p /app/config /app/logs /app/data + +# -------------------------------------------- +# Expose Flask port +# -------------------------------------------- +EXPOSE 5000 + +# -------------------------------------------- +# Use tini as init for graceful shutdown handling +# -------------------------------------------- +ENTRYPOINT ["/usr/bin/tini", "--"] + +# -------------------------------------------- +# Start the Flask app +# (Change app.py to wsgi.py if you ever switch to gunicorn) +# -------------------------------------------- +CMD ["python", "app.py"] From f7984654e333aec814dcf557f295e22f854cbbad Mon Sep 17 00:00:00 2001 From: thehack904 <35552907+thehack904@users.noreply.github.com> Date: Sat, 11 Oct 2025 08:04:50 -0500 Subject: [PATCH 28/41] Update docker-publish.yml --- .github/workflows/docker-publish.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/docker-publish.yml b/.github/workflows/docker-publish.yml index bd6dd07..139a209 100644 --- a/.github/workflows/docker-publish.yml +++ b/.github/workflows/docker-publish.yml @@ -30,12 +30,12 @@ jobs: IMAGE_NAME_LOWER=$(echo "${{ github.repository }}" | tr '[:upper:]' '[:lower:]') echo "IMAGE_NAME_LOWER=${IMAGE_NAME_LOWER}" >> $GITHUB_ENV - - name: 🔑 Log in to GitHub Container Registry + - name: 🔑 Log in to GitHub Container Registry (using PAT) uses: docker/login-action@v3 with: registry: ${{ env.REGISTRY }} username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} + password: ${{ secrets.GHCR_PAT }} - name: 🏗️ Set up Docker Buildx uses: docker/setup-buildx-action@v3 From 1e5e2775b33f05e0ac1472558c23ff208f45a61c Mon Sep 17 00:00:00 2001 From: thehack904 <35552907+thehack904@users.noreply.github.com> Date: Sat, 11 Oct 2025 08:52:51 -0500 Subject: [PATCH 29/41] Version 3.2.0 Updates --- CHANGELOG.md | 21 +++++++++++++++++ INSTALL.md | 54 ++++++++++++++++++++++--------------------- README.md | 45 ++++++++++++++++++++++++------------ ROADMAP.md | 12 +++++++--- app.py | 4 ++-- install.sh | 2 +- install_windows.ps1 | 2 +- retroiptv_rpi.sh | 2 +- uninstall.sh | 4 ++-- uninstall_windows.ps1 | 2 +- 10 files changed, 96 insertions(+), 52 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c8a64c4..30a0bda 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,27 @@ This project follows [Semantic Versioning](https://semver.org/). - Planned: log filtering and pagination. --- + +## [v3.2.0] - 2025-10-11 +### Added +- **Containerization & TrueNAS Deployment Support** + - Added official Dockerfile and `docker-compose.yml` for cross‑platform container deployments. + - Added **TrueNAS SCALE App chart** with persistent volume mapping (`/config`, `/logs`, `/data`). + - Added GitHub Actions workflow for automatic GHCR image builds. + - Docker image published at: + `ghcr.io/thehack904/retroiptvguide:latest` +- Integrated automatic build‑and‑push pipeline using GitHub Actions and GHCR_PAT authentication. +- Added healthcheck and restart policies in Docker configuration. + +### Changed +- Documentation updated for container installation (Docker/TrueNAS) as the new primary method. +- Legacy Python and system installers moved to “manual install” section. + +### Fixed +- Corrected GHCR tag formatting for TrueNAS (eliminated `:latest:latest` errors). +- Fixed workflow permissions with explicit `packages: write` and PAT authentication. +--- + ## v3.1.0 - 2025-10-09 ### Added - New **RetroIPTVGuide Raspberry Pi headless installer** (`retroiptv_rpi.sh`) diff --git a/INSTALL.md b/INSTALL.md index 354c971..a9fa63a 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -1,11 +1,11 @@ # Installation Guide -**Version:** v3.1.0 -**Last Updated:** 2025-10-09 +**Version:** v3.2.0 +**Last Updated:** 2025-10-11 ## Requirements - Python 3.10+ (Linux) / Python 3.12+ (Windows) -- **Linux (Debian/Ubuntu with systemd)**, **Windows 10/11**, or **Raspberry Pi 3 / 4 / 5 (Headless OS)** +- **Linux (Debian/Ubuntu with systemd)**, **Windows 10/11**, or **Raspberry Pi 3 / 4 / 5 (Headless OS) / Docker** - Administrative privileges: - **Linux/WSL/Raspberry Pi:** run install/uninstall with `sudo` - **Windows:** run from an Administrator **PowerShell** session @@ -18,19 +18,10 @@ Clone the repository and run the installer. Choose the command based on your OS. ### Linux / WSL -#### Option 1: One-liner (quick setup) +#### One-liner ```bash git clone https://github.com/thehack904/RetroIPTVGuide.git && cd RetroIPTVGuide && sudo chmod +x install.sh && sudo ./install.sh ``` -or - -#### Option 2: Multi-line (step-by-step) -```bash -git clone https://github.com/thehack904/RetroIPTVGuide.git -cd RetroIPTVGuide -sudo chmod +x install.sh -sudo ./install.sh -``` **What the installer does (Linux/WSL):** - Detects Linux/WSL environment @@ -96,6 +87,22 @@ curl -sSL https://raw.githubusercontent.com/thehack904/RetroIPTVGuide/refs/heads --- +## 🚀 Containerized Deployment + +RetroIPTVGuide v3.2.0 introduces **official Docker and TrueNAS SCALE App support**, allowing one‑click installation and persistent storage. + +### 🧱 Docker (Generic Linux / macOS / Windows) + +#### Using Docker Compose + +```bash +git clone https://github.com/thehack904/RetroIPTVGuide.git +cd RetroIPTVGuide +docker compose up -d +``` + +--- + ## Access Once installed, open your browser: @@ -112,8 +119,6 @@ Default login: **admin / strongpassword123** ## 🔄 Updating ### Linux / WSL - -#### Quick update (one-liner) ```bash sudo -u iptv bash -H -c "cd /home/iptv/iptv-server && git fetch --all && git reset --hard origin/main" && sudo systemctl daemon-reload && sudo systemctl restart iptv-server.service ``` @@ -127,20 +132,12 @@ sudo -u iptv bash -H -c "cd /home/iptv/iptv-server && git fetch --all && git res ```powershell git fetch --all ; git reset --hard origin/main ; Restart-Service RetroIPTVGuide ``` -or -#### Step-by-step -```powershell -git fetch --all -git reset --hard origin/main -Restart-Service RetroIPTVGuide +#### Docker +```bash +docker compose pull && docker compose up -d ``` -This will: -- Fetch the latest code from GitHub -- Reset your repo to the latest `windows` branch -- Restart the RetroIPTVGuide service (installed via NSSM) - --- ## Uninstallation @@ -161,6 +158,11 @@ From an Administrator PowerShell prompt: .\uninstall_windows.ps1 ``` +#### Uninstalling +```bash +docker compose down -v +``` + **Each uninstaller stops its service, removes environment files, and cleans logs.** ⚠️ To completely remove the project, manually delete the project folder after uninstalling. --- diff --git a/README.md b/README.md index 64a028e..48ee4e3 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,10 @@ # RetroIPTVGuide -![Version](https://img.shields.io/badge/version-v3.1.0-blue) +![Version](https://img.shields.io/badge/version-v3.2.0-blue) RetroIPTVGuide is an IPTV Web Interface inspired by 90s/2000s cable TV guides. It is designed to work with [ErsatzTV](https://ersatztv.org/) [(GitRepo)](https://github.com/ErsatzTV/ErsatzTV/tree/main) but supports any `.m3u`, `.m3u8`, and `.xml` IPTV source. +Now includes **Docker and TrueNAS SCALE deployment support** for easy installation and persistence. ⚠️ **Note:** This is still a BETA release. It is not recommended for direct Internet/public-facing deployments. @@ -14,17 +15,30 @@ It is designed to work with [ErsatzTV](https://ersatztv.org/) [(GitRepo)](https: --- -## ✨ Features (v3.1.0) +## 🚀 Containerized Deployment (v3.2.0) -### 🆕 Raspberry Pi Headless Support -- Full **Raspberry Pi installer (`retroiptv_rpi.sh`)** added. -- Detects Pi 3 / 4 / 5 hardware and automatically sets GPU memory (128MB / 256MB). -- Installs to `/home/iptv/iptv-server` using system user `iptv`. -- Configures Python virtual environment and creates a systemd service `retroiptvguide`. -- Logs everything to `/var/log/retroiptvguide/install-TIMESTAMP.log`. -- Supports `--yes` (skip confirmations) and `--agree` (auto-accept license). -- Post-install check verifies Flask service on port 5000. -- Optional reboot prompt applies GPU memory changes. +### 🐳 Docker +```bash +docker pull ghcr.io/thehack904/retroiptvguide:latest +docker run -d -p 5000:5000 ghcr.io/thehack904/retroiptvguide:latest +``` +Access the web interface at: +`http://:5000` + +### 🧩 TrueNAS SCALE App +- Upload the provided `retroiptvguide-3.2.0.zip` chart. +- Repository: `ghcr.io/thehack904/retroiptvguide` +- Tag: `latest` +- Exposes port `5000`. + +--- + +## ✨ Features (v3.2.0) + +- Official **Docker / TrueNAS** support with persistent volumes. +- Automatic build/publish to **GHCR** via GitHub Actions. +- Same RetroIPTVGuide web interface and EPG features from v3.1.x. +- Backward compatible with Linux, Windows, and Raspberry Pi installs. --- @@ -87,6 +101,7 @@ It is designed to work with [ErsatzTV](https://ersatztv.org/) [(GitRepo)](https: | Version | Date | Key Features | |----------|------|---------------| +| **v3.2.0** | 2025-10-11 | Containerized Deployment / TrueNAS Scale App installer | | **v3.1.0** | 2025-10-09 | Raspberry Pi installer, verified GPU setup, improved HTTP service check | | **v3.0.1** | 2025-10-07 | EPG fallback system, tuner refresh fix, login redesign | | **v3.0.0** | 2025-10-03 | Windows installer/uninstaller, cross-platform setup, unified UI | @@ -108,7 +123,7 @@ RetroIPTVGuide is compatible with all modern browsers: ## 💻 Tested Devices & Operating Systems - **Ubuntu 24.04 (desktop/server)** -- **TrueNAS SCALE (Docker/Podman)** +- **TrueNAS SCALE (Docker)** - **Windows 10 / 11** - **Raspberry Pi 3B+ / 4 / 5 (Raspberry Pi OS Bookworm)** - **macOS Monterey / Ventura** @@ -121,7 +136,7 @@ RetroIPTVGuide is compatible with all modern browsers: - Debian-based Linux (Ubuntu, Pop!\_OS, Mint) - Windows 10/11 (via PowerShell + NSSM) - Raspberry Pi 3 / 4 / 5 (Headless OS, `retroiptv_rpi.sh`) -- macOS (manual install or future installer support) +- Docker (Generic Linux / macOS / Windows) --- @@ -172,8 +187,8 @@ See [ROADMAP.md](ROADMAP.md) for full details. - **Repo:** [RetroIPTVGuide](https://github.com/thehack904/RetroIPTVGuide) - **Maintainer:** J.H. - **License:** [Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International (CC BY-NC-SA 4.0)](https://creativecommons.org/licenses/by-nc-sa/4.0/) -- **Version:** v3.1.0 -- **Release Date:** 2025-10-09 +- **Version:** v3.2.0 +- **Release Date:** 2025-10-11 --- diff --git a/ROADMAP.md b/ROADMAP.md index 383886a..30bdda8 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -88,9 +88,9 @@ These are **not yet implemented**, but provide a development path for future rel --- ## 📅 Priority Suggestions -- Short term: finalize Pi installer documentation and verify GPU/swap checks (v3.1.x). -- Medium term: `.m3u8` tuner support and DB-based logs (v3.2.x). -- Long term: full HTTPS and container deployment. +- Short term: finalize Docker image testing across TrueNAS and generic Linux. +- Medium term: implement `.m3u8` tuner and DB log storage (v3.3.x). +- Long term: HTTPS support and mobile UI redesign. --- @@ -106,6 +106,12 @@ These are **not yet implemented**, but provide a development path for future rel - Ensure logs and services are properly separated between modes. --- +## ✅ Completed (v3.2.0) +- [x] **Containerization & TrueNAS Deployment Support** + - Dockerfile and docker‑compose finalized for GHCR. + - TrueNAS SCALE App chart added for persistent deployment. + - CI/CD publishing pipeline via GitHub Actions and GHCR_PAT. + - Updated documentation (INSTALL, README, CHANGELOG). ## ✅ Completed (v3.1.0) - [x] **Raspberry Pi headless installer completed** (`retroiptv_rpi.sh`). diff --git a/app.py b/app.py index 48e36ea..be63923 100644 --- a/app.py +++ b/app.py @@ -1,5 +1,5 @@ -APP_VERSION = "v3.1.0" -APP_RELEASE_DATE = "2025-09-26" +APP_VERSION = "v3.2.0" +APP_RELEASE_DATE = "2025-10-11" from flask import Flask, render_template, request, redirect, url_for, flash from flask_login import LoginManager, UserMixin, login_user, login_required, logout_user, current_user diff --git a/install.sh b/install.sh index 0197951..178ea1f 100644 --- a/install.sh +++ b/install.sh @@ -1,7 +1,7 @@ #!/bin/bash set -e -VERSION="3.1.0" # RetroIPTVGuide installer version +VERSION="3.2.0" # RetroIPTVGuide installer version # RetroIPTVGuide Debian/Ubuntu Installer # License: CC BY-NC-SA 4.0 TIMESTAMP=$(date +"%Y-%m-%d_%H-%M-%S") diff --git a/install_windows.ps1 b/install_windows.ps1 index 5e1d837..e1941b4 100644 --- a/install_windows.ps1 +++ b/install_windows.ps1 @@ -1,4 +1,4 @@ -$VERSION = "3.1.0" +$VERSION = "3.2.0" <# RetroIPTVGuide Windows Installer Clean version with only prerequisite checks and service setup diff --git a/retroiptv_rpi.sh b/retroiptv_rpi.sh index 8419932..16c8150 100644 --- a/retroiptv_rpi.sh +++ b/retroiptv_rpi.sh @@ -1,5 +1,5 @@ #!/bin/bash -VERSION="3.1.0" # RetroIPTVGuide Raspberry Pi installer version +VERSION="3.2.0" # RetroIPTVGuide Raspberry Pi installer version # RetroIPTVGuide Raspberry Pi Installer (Headless, Pi3/4/5) # Installs to /home/iptv/iptv-server for consistency with Debian/Windows # Logs to /var/log/retroiptvguide/install-YYYYMMDD-HHMMSS.log diff --git a/uninstall.sh b/uninstall.sh index 4532900..c89c69e 100644 --- a/uninstall.sh +++ b/uninstall.sh @@ -1,4 +1,4 @@ -VERSION="3.1.0" +VERSION="3.2.0" #!/usr/bin/env bash # RetroIPTVGuide uninstall script # Run with sudo on Linux; run from Administrator shell on Windows @@ -33,7 +33,7 @@ if [[ "$ENVIRONMENT" == "LINUX" || "$ENVIRONMENT" == "WSL" ]]; then exit 1 fi elif [[ "$ENVIRONMENT" == "GITBASH" ]]; then - # Git Bash doesn’t expose EUID reliably, just warn the user + # Git Bash doesn’t expose EUID reliably, just warn the user echo "NOTE: On Windows, ensure Git Bash is running with Administrator privileges." fi diff --git a/uninstall_windows.ps1 b/uninstall_windows.ps1 index 9b97334..8971eb7 100644 --- a/uninstall_windows.ps1 +++ b/uninstall_windows.ps1 @@ -1,4 +1,4 @@ -$VERSION = "3.1.0" +$VERSION = "3.2.0" # RetroIPTVGuide Windows Uninstaller # ================================== From fb8da59cdf3eed4a167e24801d88df170e8d94c3 Mon Sep 17 00:00:00 2001 From: thehack904 <35552907+thehack904@users.noreply.github.com> Date: Sat, 11 Oct 2025 15:15:55 -0500 Subject: [PATCH 30/41] Add Docker deployment bundle and updated README badges --- INSTALL.md | 13 ++++- README.md | 27 ++++++++- docker/.env.example | 18 ++++++ docker/README_DOCKER.md | 112 ++++++++++++++++++++++++++++++++++++++ docker/config/.gitkeep | 0 docker/data/.gitkeep | 0 docker/docker-compose.yml | 20 +++++++ docker/logs/.gitkeep | 0 8 files changed, 187 insertions(+), 3 deletions(-) create mode 100644 docker/.env.example create mode 100644 docker/README_DOCKER.md create mode 100644 docker/config/.gitkeep create mode 100644 docker/data/.gitkeep create mode 100644 docker/docker-compose.yml create mode 100644 docker/logs/.gitkeep diff --git a/INSTALL.md b/INSTALL.md index a9fa63a..f3efd07 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -97,10 +97,21 @@ RetroIPTVGuide v3.2.0 introduces **official Docker and TrueNAS SCALE App support ```bash git clone https://github.com/thehack904/RetroIPTVGuide.git -cd RetroIPTVGuide +cd RetroIPTVGuide/docker +cp .env.example .env docker compose up -d ``` + +## 🐳 Quick Docker Run + +The fastest way to launch **RetroIPTVGuide v3.2.0**: + +```bash +docker pull ghcr.io/thehack904/retroiptvguide:latest +docker run -d --name retroiptvguide -p 5000:5000 -e TZ=America/Chicago -e SECRET_KEY=$(openssl rand -hex 32) -v $(pwd)/config:/app/config -v $(pwd)/logs:/app/logs -v $(pwd)/data:/app/data ghcr.io/thehack904/retroiptvguide:latest +``` + --- ## Access diff --git a/README.md b/README.md index 48ee4e3..9422c3f 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,30 @@ # RetroIPTVGuide -![Version](https://img.shields.io/badge/version-v3.2.0-blue) +

+ + Version + + + GHCR + + + Build Status + + + License + +

+ + +--- + +## 📦 Image Information + +| Registry | Image | Architectures | Updated | +|-----------|--------|----------------|----------| +| **GitHub Container Registry** | `ghcr.io/thehack904/retroiptvguide:latest` | amd64 / arm64 | Automatically via CI/CD | + +--- RetroIPTVGuide is an IPTV Web Interface inspired by 90s/2000s cable TV guides. It is designed to work with [ErsatzTV](https://ersatztv.org/) [(GitRepo)](https://github.com/ErsatzTV/ErsatzTV/tree/main) but supports any `.m3u`, `.m3u8`, and `.xml` IPTV source. @@ -14,7 +38,6 @@ Now includes **Docker and TrueNAS SCALE deployment support** for easy installati - [License](LICENSE) --- - ## 🚀 Containerized Deployment (v3.2.0) ### 🐳 Docker diff --git a/docker/.env.example b/docker/.env.example new file mode 100644 index 0000000..6513382 --- /dev/null +++ b/docker/.env.example @@ -0,0 +1,18 @@ +# ============================================ +# RetroIPTVGuide Environment Configuration +# ============================================ + +# System Settings +TZ=America/Chicago +FLASK_ENV=production +PYTHONUNBUFFERED=1 + +# Security +SECRET_KEY=change_me_securely + +# Files / Logs +DATABASE_FILE=retroiptv.db +LOG_FILE=retroiptv.log + +# Internal Flask Port +FLASK_PORT=5000 diff --git a/docker/README_DOCKER.md b/docker/README_DOCKER.md new file mode 100644 index 0000000..37b7f6c --- /dev/null +++ b/docker/README_DOCKER.md @@ -0,0 +1,112 @@ +# 🐳 RetroIPTVGuide Docker Deployment + +This folder contains everything you need to deploy **RetroIPTVGuide** via Docker or Docker Compose. + +--- + +## 🚀 Quick Start + +### 1️⃣ Clone the repository and navigate into the Docker directory +```bash +git clone https://github.com/thehack904/RetroIPTVGuide.git +cd RetroIPTVGuide/docker +``` + +### 2️⃣ Create a `.env` file from the example +```bash +cp .env.example .env +``` +Edit `.env` to set your timezone and secret key. + +### 3️⃣ Launch the container +```bash +docker compose up -d +``` + +### 4️⃣ Access the web interface +``` +http://:5000 +``` + +--- + +## 🔄 Updating +```bash +docker compose pull && docker compose up -d +``` + +--- + +## 🧹 Uninstalling +```bash +docker compose down -v +``` +This stops and removes the container, volumes, and network. + +--- + +## 🧱 Directory Layout +``` +docker/ +├── docker-compose.yml +├── .env.example +├── config/ → Persistent configuration files +├── data/ → SQLite database files +└── logs/ → Application logs +``` +Docker automatically creates these directories on first run if they don’t exist. + +--- + +## 🧠 Notes +- The container image supports both **amd64** and **arm64** (e.g. Raspberry Pi). +- Default exposed port: **5000** +- Default image: `ghcr.io/thehack904/retroiptvguide:latest` +- Restart policy: `unless-stopped` +- Logs, configs, and data persist between updates. + +--- + +## 🧩 Example Commands + +View logs: +```bash +docker compose logs -f +``` + +Restart the container: +```bash +docker compose restart +``` + +Stop the container: +```bash +docker compose down +``` + +--- + +## 🧰 Customization + +You can override settings directly in the `.env` file: + +| Variable | Description | Example | +|-----------|--------------|----------| +| `TZ` | Timezone | `America/New_York` | +| `FLASK_ENV` | Flask environment | `production` | +| `SECRET_KEY` | Random secure key | `openssl rand -hex 32` | +| `DATABASE_FILE` | SQLite DB filename | `retroiptv.db` | +| `LOG_FILE` | Log file name | `retroiptv.log` | + +--- + +## 🧭 Compatibility + +✅ Docker Desktop (Windows/macOS) +✅ Linux (Ubuntu, Debian, Arch, etc.) +✅ TrueNAS SCALE (Compose Stack or App) +✅ Raspberry Pi (ARM builds supported) + +--- + +© 2025 RetroIPTVGuide — Licensed under CC BY-NC-SA 4.0 diff --git a/docker/config/.gitkeep b/docker/config/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/docker/data/.gitkeep b/docker/data/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml new file mode 100644 index 0000000..7c36f82 --- /dev/null +++ b/docker/docker-compose.yml @@ -0,0 +1,20 @@ +version: "3.9" + +services: + retroiptvguide: + container_name: retroiptvguide + image: ghcr.io/thehack904/retroiptvguide:latest + restart: unless-stopped + ports: + - "5000:5000" + env_file: + - .env + volumes: + - ./config:/app/config + - ./logs:/app/logs + - ./data:/app/data + healthcheck: + test: ["CMD", "curl", "-f", "http://localhost:5000"] + interval: 30s + timeout: 5s + retries: 3 diff --git a/docker/logs/.gitkeep b/docker/logs/.gitkeep new file mode 100644 index 0000000..e69de29 From 20355d1cf85e9a62e101627c68b896bf4ea8a739 Mon Sep 17 00:00:00 2001 From: thehack904 <35552907+thehack904@users.noreply.github.com> Date: Sat, 11 Oct 2025 16:02:06 -0500 Subject: [PATCH 31/41] Update app.py Add two active (tested) IPTV Tuners (Plex / Tubi). These were to show that you can copy .m3u link into both the .xml and .m3u lines and they will work automatically. --- app.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/app.py b/app.py index be63923..cac8920 100644 --- a/app.py +++ b/app.py @@ -133,6 +133,14 @@ def init_tuners_db(): "Tuner 2": { "m3u": "http://iptv2.lan:8500/iptv/channels.m3u", "xml": "http://iptv2.lan:8500/iptv/xmltv.xml" + }, + "Plex": { + "m3u": "https://raw.githubusercontent.com/iptv-org/iptv/refs/heads/master/streams/us_plex.m3u", + "xml": "https://raw.githubusercontent.com/iptv-org/iptv/refs/heads/master/streams/us_plex.m3u" + }, + "Tubi": { + "m3u": "https://raw.githubusercontent.com/iptv-org/iptv/refs/heads/master/streams/us_tubi.m3u", + "xml": "https://raw.githubusercontent.com/iptv-org/iptv/refs/heads/master/streams/us_tubi.m3u" } } for name, urls in defaults.items(): From 47c971150ae28f3ac3c21f0c7e001b23935e09e4 Mon Sep 17 00:00:00 2001 From: thehack904 <35552907+thehack904@users.noreply.github.com> Date: Sat, 11 Oct 2025 16:15:34 -0500 Subject: [PATCH 32/41] Add automated GHCR cleanup (keep 5 latest builds) --- .github/workflows/docker-publish.yml | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/.github/workflows/docker-publish.yml b/.github/workflows/docker-publish.yml index 139a209..f82137f 100644 --- a/.github/workflows/docker-publish.yml +++ b/.github/workflows/docker-publish.yml @@ -57,3 +57,16 @@ jobs: - name: 🧹 Cleanup local images run: docker image prune -af || true + cleanup-ghcr: + name: 🧽 Cleanup old GHCR images + runs-on: ubuntu-latest + needs: build-and-push + permissions: + packages: write + steps: + - name: 🧹 Delete old GHCR package versions (keep last 5) + uses: actions/delete-package-versions@v5 + with: + package-name: "retroiptvguide" + package-type: "container" + min-versions-to-keep: 5 From f65af97561e267b446371b23bfaa6403eaf9a6e1 Mon Sep 17 00:00:00 2001 From: thehack904 <35552907+thehack904@users.noreply.github.com> Date: Sat, 11 Oct 2025 16:18:37 -0500 Subject: [PATCH 33/41] Update INSTALL.md --- INSTALL.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/INSTALL.md b/INSTALL.md index f3efd07..3246db8 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -169,7 +169,7 @@ From an Administrator PowerShell prompt: .\uninstall_windows.ps1 ``` -#### Uninstalling +#### Docker ```bash docker compose down -v ``` From 64030ecbf72081994ad3d13cb26974025e4f9ed3 Mon Sep 17 00:00:00 2001 From: thehack904 <35552907+thehack904@users.noreply.github.com> Date: Sat, 11 Oct 2025 16:34:47 -0500 Subject: [PATCH 34/41] Update docker-publish.yml --- .github/workflows/docker-publish.yml | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/.github/workflows/docker-publish.yml b/.github/workflows/docker-publish.yml index f82137f..d51be8d 100644 --- a/.github/workflows/docker-publish.yml +++ b/.github/workflows/docker-publish.yml @@ -67,6 +67,12 @@ jobs: - name: 🧹 Delete old GHCR package versions (keep last 5) uses: actions/delete-package-versions@v5 with: - package-name: "retroiptvguide" - package-type: "container" + owner: thehack904 + package-name: retroiptvguide + package-type: container min-versions-to-keep: 5 + token: ${{ secrets.GHCR_PAT }} + continue-on-error: true + + - name: 🧾 Summary + run: echo "✅ GHCR cleanup complete — kept last 5 image versions (including latest)." From 9353e066760f758a15f4cecad8e0f6bdca429e91 Mon Sep 17 00:00:00 2001 From: thehack904 <35552907+thehack904@users.noreply.github.com> Date: Sat, 11 Oct 2025 16:44:33 -0500 Subject: [PATCH 35/41] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 9422c3f..383ba19 100644 --- a/README.md +++ b/README.md @@ -158,7 +158,7 @@ RetroIPTVGuide is compatible with all modern browsers: ## 🛠️ Installation Platforms - Debian-based Linux (Ubuntu, Pop!\_OS, Mint) - Windows 10/11 (via PowerShell + NSSM) -- Raspberry Pi 3 / 4 / 5 (Headless OS, `retroiptv_rpi.sh`) +- Raspberry Pi 3 / 4 / 5 (Headless OS) - Docker (Generic Linux / macOS / Windows) --- From 9ec094be36010a8946ec4d12f5b12118ecb322c2 Mon Sep 17 00:00:00 2001 From: thehack904 <35552907+thehack904@users.noreply.github.com> Date: Sat, 11 Oct 2025 18:44:07 -0500 Subject: [PATCH 36/41] Update docker-publish.yml --- .github/workflows/docker-publish.yml | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/.github/workflows/docker-publish.yml b/.github/workflows/docker-publish.yml index d51be8d..dd51602 100644 --- a/.github/workflows/docker-publish.yml +++ b/.github/workflows/docker-publish.yml @@ -1,4 +1,4 @@ -name: 🚀 Build and Publish RetroIPTVGuide to GHCR +name: 🚀 Build and Publish RetroIPTVGuide to GHCR and Docker Hub on: push: @@ -40,7 +40,7 @@ jobs: - name: 🏗️ Set up Docker Buildx uses: docker/setup-buildx-action@v3 - - name: 🧱 Build and Push Docker image + - name: 🧱 Build and Push Docker image to GHCR uses: docker/build-push-action@v6 with: context: . @@ -57,6 +57,22 @@ jobs: - name: 🧹 Cleanup local images run: docker image prune -af || true + - name: 🐳 Log in to Docker Hub + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + + - name: 📦 Push image to Docker Hub + run: | + echo "🧭 Tagging image for Docker Hub..." + docker tag ghcr.io/thehack904/retroiptvguide:latest thehack904/retroiptvguide:latest + docker tag ghcr.io/thehack904/retroiptvguide:${{ github.ref_name }} thehack904/retroiptvguide:${{ github.ref_name }} + echo "🚀 Pushing images to Docker Hub..." + docker push thehack904/retroiptvguide:latest + docker push thehack904/retroiptvguide:${{ github.ref_name }} + echo "✅ Docker Hub push complete." + cleanup-ghcr: name: 🧽 Cleanup old GHCR images runs-on: ubuntu-latest From 8d98e8e44928a57f51ca2b5539aefe973b089c55 Mon Sep 17 00:00:00 2001 From: thehack904 <35552907+thehack904@users.noreply.github.com> Date: Sat, 11 Oct 2025 19:27:00 -0500 Subject: [PATCH 37/41] Update docker-publish.yml --- .github/workflows/docker-publish.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/docker-publish.yml b/.github/workflows/docker-publish.yml index dd51602..c9a6979 100644 --- a/.github/workflows/docker-publish.yml +++ b/.github/workflows/docker-publish.yml @@ -45,6 +45,7 @@ jobs: with: context: . push: true + load: true # 👈 adds this line to keep a local copy tags: | ${{ env.REGISTRY }}/${{ env.IMAGE_NAME_LOWER }}:latest ${{ env.REGISTRY }}/${{ env.IMAGE_NAME_LOWER }}:${{ github.ref_name }} From 40fad08360adf64d2f6b0ffd676b156868e38798 Mon Sep 17 00:00:00 2001 From: thehack904 <35552907+thehack904@users.noreply.github.com> Date: Sat, 11 Oct 2025 19:33:09 -0500 Subject: [PATCH 38/41] Update docker-publish.yml --- .github/workflows/docker-publish.yml | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/.github/workflows/docker-publish.yml b/.github/workflows/docker-publish.yml index c9a6979..14d0724 100644 --- a/.github/workflows/docker-publish.yml +++ b/.github/workflows/docker-publish.yml @@ -40,21 +40,37 @@ jobs: - name: 🏗️ Set up Docker Buildx uses: docker/setup-buildx-action@v3 - - name: 🧱 Build and Push Docker image to GHCR + # 1️⃣ Multi-arch build & push to GHCR + - name: 🧱 Build and Push multi-arch image to GHCR uses: docker/build-push-action@v6 with: context: . push: true - load: true # 👈 adds this line to keep a local copy + platforms: linux/amd64,linux/arm64 tags: | ${{ env.REGISTRY }}/${{ env.IMAGE_NAME_LOWER }}:latest ${{ env.REGISTRY }}/${{ env.IMAGE_NAME_LOWER }}:${{ github.ref_name }} - platforms: linux/amd64,linux/arm64 labels: | org.opencontainers.image.source=${{ github.repositoryUrl }} org.opencontainers.image.description=RetroIPTVGuide Flask + SQLite Web App org.opencontainers.image.licenses=CC-BY-NC-SA-4.0 + # 2️⃣ Single-arch (amd64) build for Docker Hub + - name: 🧱 Build and Push single-arch image to Docker Hub + uses: docker/build-push-action@v6 + with: + context: . + push: true + platforms: linux/amd64 + tags: | + thehack904/retroiptvguide:latest + thehack904/retroiptvguide:${{ github.ref_name }} + labels: | + org.opencontainers.image.source=${{ github.repositoryUrl }} + org.opencontainers.image.description=RetroIPTVGuide Flask + SQLite Web App + org.opencontainers.image.licenses=CC-BY-NC-SA-4.0 + + - name: 🧹 Cleanup local images run: docker image prune -af || true From 12482bc8adadd7ee595ade7bd20da5fca968ed48 Mon Sep 17 00:00:00 2001 From: thehack904 <35552907+thehack904@users.noreply.github.com> Date: Sat, 11 Oct 2025 19:59:18 -0500 Subject: [PATCH 39/41] Update docker-publish.yml --- .github/workflows/docker-publish.yml | 59 +++++++++++++++------------- 1 file changed, 32 insertions(+), 27 deletions(-) diff --git a/.github/workflows/docker-publish.yml b/.github/workflows/docker-publish.yml index 14d0724..7f36e3e 100644 --- a/.github/workflows/docker-publish.yml +++ b/.github/workflows/docker-publish.yml @@ -9,12 +9,11 @@ on: env: REGISTRY: ghcr.io - IMAGE_NAME: ${{ github.repository }} # We'll lowercase it below + IMAGE_NAME: ${{ github.repository }} jobs: build-and-push: runs-on: ubuntu-latest - permissions: contents: read packages: write @@ -30,17 +29,17 @@ jobs: IMAGE_NAME_LOWER=$(echo "${{ github.repository }}" | tr '[:upper:]' '[:lower:]') echo "IMAGE_NAME_LOWER=${IMAGE_NAME_LOWER}" >> $GITHUB_ENV - - name: 🔑 Log in to GitHub Container Registry (using PAT) + - name: 🏗️ Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + # -------------------- GHCR -------------------- + - name: 🔑 Log in to GitHub Container Registry uses: docker/login-action@v3 with: registry: ${{ env.REGISTRY }} username: ${{ github.actor }} password: ${{ secrets.GHCR_PAT }} - - name: 🏗️ Set up Docker Buildx - uses: docker/setup-buildx-action@v3 - - # 1️⃣ Multi-arch build & push to GHCR - name: 🧱 Build and Push multi-arch image to GHCR uses: docker/build-push-action@v6 with: @@ -55,13 +54,23 @@ jobs: org.opencontainers.image.description=RetroIPTVGuide Flask + SQLite Web App org.opencontainers.image.licenses=CC-BY-NC-SA-4.0 - # 2️⃣ Single-arch (amd64) build for Docker Hub + - name: 🧹 Cleanup local images + run: docker image prune -af || true + + # -------------------- Docker Hub -------------------- + - name: 🐳 Log in to Docker Hub + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + - name: 🧱 Build and Push single-arch image to Docker Hub uses: docker/build-push-action@v6 with: context: . push: true platforms: linux/amd64 + provenance: false tags: | thehack904/retroiptvguide:latest thehack904/retroiptvguide:${{ github.ref_name }} @@ -70,26 +79,22 @@ jobs: org.opencontainers.image.description=RetroIPTVGuide Flask + SQLite Web App org.opencontainers.image.licenses=CC-BY-NC-SA-4.0 - - - name: 🧹 Cleanup local images - run: docker image prune -af || true - - - name: 🐳 Log in to Docker Hub - uses: docker/login-action@v3 - with: - username: ${{ secrets.DOCKERHUB_USERNAME }} - password: ${{ secrets.DOCKERHUB_TOKEN }} - - - name: 📦 Push image to Docker Hub + # -------------------- Post-Build Summary -------------------- + - name: 🧾 Post-build summary run: | - echo "🧭 Tagging image for Docker Hub..." - docker tag ghcr.io/thehack904/retroiptvguide:latest thehack904/retroiptvguide:latest - docker tag ghcr.io/thehack904/retroiptvguide:${{ github.ref_name }} thehack904/retroiptvguide:${{ github.ref_name }} - echo "🚀 Pushing images to Docker Hub..." - docker push thehack904/retroiptvguide:latest - docker push thehack904/retroiptvguide:${{ github.ref_name }} - echo "✅ Docker Hub push complete." - + echo "" + echo "✅ GHCR and Docker Hub builds complete." + echo "🧩 Published image tags:" + echo " ghcr.io/thehack904/retroiptvguide:latest" + echo " ghcr.io/thehack904/retroiptvguide:${{ github.ref_name }}" + echo " thehack904/retroiptvguide:latest" + echo " thehack904/retroiptvguide:${{ github.ref_name }}" + echo "" + echo "🔗 Docker Hub: https://hub.docker.com/r/thehack904/retroiptvguide/tags" + echo "🔗 GHCR: https://github.com/thehack904?tab=packages&repo_name=RetroIPTVGuide" + echo "" + + # -------------------- GHCR Cleanup -------------------- cleanup-ghcr: name: 🧽 Cleanup old GHCR images runs-on: ubuntu-latest From 87490d161f8c08ab083cb4602d01171e9c781aa0 Mon Sep 17 00:00:00 2001 From: thehack904 <35552907+thehack904@users.noreply.github.com> Date: Sat, 11 Oct 2025 20:07:09 -0500 Subject: [PATCH 40/41] Update docker-publish.yml --- .github/workflows/docker-publish.yml | 41 ++++++++++++++++++++++++---- 1 file changed, 35 insertions(+), 6 deletions(-) diff --git a/.github/workflows/docker-publish.yml b/.github/workflows/docker-publish.yml index 7f36e3e..9e519bc 100644 --- a/.github/workflows/docker-publish.yml +++ b/.github/workflows/docker-publish.yml @@ -6,6 +6,8 @@ on: tags: - 'v*' workflow_dispatch: + schedule: + - cron: '0 3 * * 0' # weekly cleanup on Sundays 03:00 UTC env: REGISTRY: ghcr.io @@ -32,7 +34,7 @@ jobs: - name: 🏗️ Set up Docker Buildx uses: docker/setup-buildx-action@v3 - # -------------------- GHCR -------------------- + # ---------- GHCR ---------- - name: 🔑 Log in to GitHub Container Registry uses: docker/login-action@v3 with: @@ -57,7 +59,7 @@ jobs: - name: 🧹 Cleanup local images run: docker image prune -af || true - # -------------------- Docker Hub -------------------- + # ---------- Docker Hub ---------- - name: 🐳 Log in to Docker Hub uses: docker/login-action@v3 with: @@ -79,7 +81,7 @@ jobs: org.opencontainers.image.description=RetroIPTVGuide Flask + SQLite Web App org.opencontainers.image.licenses=CC-BY-NC-SA-4.0 - # -------------------- Post-Build Summary -------------------- + # ---------- Summary ---------- - name: 🧾 Post-build summary run: | echo "" @@ -94,7 +96,7 @@ jobs: echo "🔗 GHCR: https://github.com/thehack904?tab=packages&repo_name=RetroIPTVGuide" echo "" - # -------------------- GHCR Cleanup -------------------- + # ---------- GHCR Cleanup ---------- cleanup-ghcr: name: 🧽 Cleanup old GHCR images runs-on: ubuntu-latest @@ -102,7 +104,7 @@ jobs: permissions: packages: write steps: - - name: 🧹 Delete old GHCR package versions (keep last 5) + - name: 🧹 Delete old GHCR package versions (keep 5) uses: actions/delete-package-versions@v5 with: owner: thehack904 @@ -113,4 +115,31 @@ jobs: continue-on-error: true - name: 🧾 Summary - run: echo "✅ GHCR cleanup complete — kept last 5 image versions (including latest)." + run: echo "✅ GHCR cleanup complete — kept 5 latest versions." + + # ---------- Docker Hub Cleanup ---------- + cleanup-dockerhub: + name: 🧽 Cleanup old Docker Hub tags + runs-on: ubuntu-latest + needs: build-and-push + env: + USER: thehack904 + REPO: retroiptvguide + TOKEN: ${{ secrets.DOCKERHUB_TOKEN }} + steps: + - name: 🧹 Remove old Docker Hub tags (keep 5) + run: | + TAGS=$(curl -s -H "Authorization: Bearer ${TOKEN}" \ + "https://hub.docker.com/v2/repositories/${USER}/${REPO}/tags/?page_size=100" \ + | jq -r '.results[].name') + + COUNT=0 + for TAG in $TAGS; do + COUNT=$((COUNT+1)) + if [ $COUNT -gt 5 ]; then + echo "🧹 Deleting $TAG ..." + curl -s -X DELETE -H "Authorization: Bearer ${TOKEN}" \ + "https://hub.docker.com/v2/repositories/${USER}/${REPO}/tags/${TAG}/" >/dev/null + fi + done + echo "✅ Docker Hub cleanup complete — kept 5 newest tags." From 472b9332bd47c40e1efb8ec2e8efbffc2ab50d5a Mon Sep 17 00:00:00 2001 From: thehack904 <35552907+thehack904@users.noreply.github.com> Date: Sat, 11 Oct 2025 20:13:03 -0500 Subject: [PATCH 41/41] Update docker-publish.yml --- .github/workflows/docker-publish.yml | 30 ++++++++++++++++++++++++---- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/.github/workflows/docker-publish.yml b/.github/workflows/docker-publish.yml index 9e519bc..1af3121 100644 --- a/.github/workflows/docker-publish.yml +++ b/.github/workflows/docker-publish.yml @@ -125,21 +125,43 @@ jobs: env: USER: thehack904 REPO: retroiptvguide + USERNAME: ${{ secrets.DOCKERHUB_USERNAME }} TOKEN: ${{ secrets.DOCKERHUB_TOKEN }} steps: - name: 🧹 Remove old Docker Hub tags (keep 5) run: | - TAGS=$(curl -s -H "Authorization: Bearer ${TOKEN}" \ - "https://hub.docker.com/v2/repositories/${USER}/${REPO}/tags/?page_size=100" \ - | jq -r '.results[].name') + echo "🔑 Authenticating with Docker Hub API..." + AUTH_RESP=$(curl -s -X POST \ + -H "Content-Type: application/json" \ + -d "{\"username\": \"${USERNAME}\", \"password\": \"${TOKEN}\"}" \ + https://hub.docker.com/v2/users/login/) + JWT=$(echo $AUTH_RESP | jq -r .token) + + if [ -z "$JWT" ] || [ "$JWT" = "null" ]; then + echo "❌ Authentication failed — could not get JWT token." + exit 1 + fi + + echo "✅ Authenticated successfully." + + TAGS=$(curl -s -H "Authorization: JWT ${JWT}" \ + "https://hub.docker.com/v2/repositories/${USER}/${REPO}/tags/?page_size=100" | + jq -r '.results[].name') + + if [ -z "$TAGS" ]; then + echo "⚠️ No tags found — skipping cleanup." + exit 0 + fi COUNT=0 for TAG in $TAGS; do COUNT=$((COUNT+1)) if [ $COUNT -gt 5 ]; then echo "🧹 Deleting $TAG ..." - curl -s -X DELETE -H "Authorization: Bearer ${TOKEN}" \ + curl -s -X DELETE -H "Authorization: JWT ${JWT}" \ "https://hub.docker.com/v2/repositories/${USER}/${REPO}/tags/${TAG}/" >/dev/null fi done + echo "✅ Docker Hub cleanup complete — kept 5 newest tags." +