diff --git a/README.md b/README.md index 9a3cfc6..c1013c1 100644 --- a/README.md +++ b/README.md @@ -71,7 +71,7 @@ Update them any time with `sudo ./setup.sh configure`. | `media` | `arm`, `audiobookshelf`, `emby`, `immich`, `jellyfin`, `lyrion` | | `cameras` | `frigate`, `frigate-audio`, `frigate-notify`, `sky-cam` | | `gaming` | `js99er`, `minecraft`, `wolf`, `wolf-pair` | -| `extras` | `silent-send`, `sync-cc` | +| `extras` | `kdeconnect`, `silent-send`, `sync-cc` | | `backup` | `backup` — complete recovery: entire `~/docker//` for every service via Kopia (Minecraft: flush+snap, no downtime; others: stop/snap/start for DB consistency); `borg-backup` — same coverage via Borg (chunk dedup, SSH remote repos, Borgmatic/Vorta compatible); `gaming-backup` — frequent game-save snapshots (Minecraft world data, emulator saves, Steam — no downtime, run hourly) | Run `./setup.sh --list` to see descriptions. diff --git a/services/kdeconnect.sh b/services/kdeconnect.sh new file mode 100644 index 0000000..4d0c7cb --- /dev/null +++ b/services/kdeconnect.sh @@ -0,0 +1,153 @@ +#!/bin/bash +# services/kdeconnect.sh — Phone/desktop integration via KDE Connect. +# Part of the modular post-install system (sourced by setup.sh). +# +# Can also be run standalone on any machine: +# sudo bash kdeconnect.sh +# +# KDE Connect is an APT package — NOT a Docker service. +# It enables Android/iPhone ↔ Linux integration: +# • Shared clipboard • File transfer +# • Phone notifications on desktop • Remote input (trackpad/keyboard) +# • SMS from desktop • Battery status +# +# NOTE: setup.sh is_installed() needs a case entry for this service: +# kdeconnect) command -v kdeconnect >/dev/null 2>&1 ;; + +# ── Standalone bootstrap ────────────────────────────────────────────────────── +# Detected when the script is executed directly rather than sourced by setup.sh. +# Sets up helpers and globals, then defers execution until after the function +# definition at the bottom of this file. +if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then + [[ "$(id -u)" == "0" ]] || { echo "Run with sudo: sudo bash $0"; exit 1; } + + _SELF_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + _COMMON="$_SELF_DIR/../lib/common.sh" + + if [[ -f "$_COMMON" ]]; then + # Full repo present — use the real helpers (picks up ~/docker/.config too) + # shellcheck source=../lib/common.sh + source "$_COMMON" + else + # One-off copy — inline minimal stubs so the script works without the repo + log_info() { echo -e "\033[0;34m[INFO]\033[0m $*"; } + log_success() { echo -e "\033[0;32m[OK]\033[0m $*"; } + log_warning() { echo -e "\033[1;33m[WARN]\033[0m $*"; } + log_error() { echo -e "\033[0;31m[ERROR]\033[0m $*" >&2; } + + # Match common.sh's eval-based pattern so local vars in install_* are set correctly + prompt_text() { + local _q="$1" _def="$2" _var="$3" _r + [[ "${UNATTENDED:-false}" == "true" ]] && { eval "$_var='$_def'"; return; } + read -r -p " $_q " _r + eval "$_var='${_r:-$_def}'" + } + + prompt_yn() { + local _q="$1" _def="$2" _var="$3" _r + [[ "${UNATTENDED:-false}" == "true" ]] && { eval "$_var='$_def'"; return; } + read -r -p " $_q " _r + eval "$_var='${_r:-$_def}'" + } + fi + + # Globals — ACTUAL_USER/ACTUAL_HOME must come before DOCKER_DIR + # ($HOME under sudo is /root, not the real user's home) + ACTUAL_USER="${ACTUAL_USER:-${SUDO_USER:-$USER}}" + ACTUAL_HOME="$(getent passwd "$ACTUAL_USER" 2>/dev/null | cut -d: -f6 || echo "${HOME:-/root}")" + DOCKER_DIR="${DOCKER_DIR:-$ACTUAL_HOME/docker}" + DRY_RUN="${DRY_RUN:-false}" + UNATTENDED="${UNATTENDED:-false}" + + register_service() { :; } # no-op — no wizard to register into + _RUN_STANDALONE=1 +fi +# ───────────────────────────────────────────────────────────────────────────── + +register_service kdeconnect extras "Phone/desktop integration — notifications, clipboard, file transfer (KDE Connect)" + +install_kdeconnect() { + log_info "Installing KDE Connect phone/desktop integration..." + + echo "" + echo "┌─────────────────────────────────────────────────────────────────┐" + echo "│ KDE CONNECT — Phone / Desktop Integration │" + echo "│ Shared clipboard, notifications, file transfer, remote input │" + echo "│ Works with Android (Play Store / F-Droid) and iPhone (App Store)│" + echo "└─────────────────────────────────────────────────────────────────┘" + echo "" + + # ── Already installed? ──────────────────────────────────────────────────── + if command -v kdeconnect &>/dev/null; then + log_info "KDE Connect is already installed — skipping." + return 0 + fi + + # ── DRY-RUN: describe the plan and bail before touching anything real ───── + if [ "$DRY_RUN" = true ]; then + echo "[DRY-RUN] Would install: kdeconnect" + if dpkg -l gnome-shell 2>/dev/null | grep -q ^ii; then + echo "[DRY-RUN] Would install: indicator-kdeconnect (GNOME/Ubuntu detected)" + fi + if command -v ufw &>/dev/null && ufw status 2>/dev/null | grep -q "Status: active"; then + echo "[DRY-RUN] Would open UFW ports 1714:1764/tcp and 1714:1764/udp" + fi + return 0 + fi + + # ── 1. Install kdeconnect ───────────────────────────────────────────────── + log_info "Installing kdeconnect package..." + if apt-get install -y kdeconnect; then + log_success "kdeconnect installed" + else + log_error "Failed to install kdeconnect — check apt output above" + return 1 + fi + + # ── 2. GNOME indicator (Ubuntu/GNOME only) ──────────────────────────────── + if dpkg -l gnome-shell 2>/dev/null | grep -q ^ii; then + log_info "GNOME detected — installing indicator-kdeconnect for system tray support..." + if apt-get install -y indicator-kdeconnect; then + log_success "indicator-kdeconnect installed" + else + log_warning "Could not install indicator-kdeconnect — continuing without it" + fi + fi + + # ── 3. Open UFW firewall ports (KDE Connect port range) ─────────────────── + if command -v ufw &>/dev/null && ufw status 2>/dev/null | grep -q "Status: active"; then + log_info "Opening UFW ports 1714:1764/tcp and 1714:1764/udp (KDE Connect)..." + ufw allow 1714:1764/tcp + ufw allow 1714:1764/udp + log_success "UFW ports 1714-1764 opened" + else + log_info "UFW not active — skipping firewall rules" + echo " If you enable UFW later, run:" + echo " sudo ufw allow 1714:1764/tcp" + echo " sudo ufw allow 1714:1764/udp" + fi + + # ── 4. Usage instructions ───────────────────────────────────────────────── + echo "" + echo " ┌─ Next steps ────────────────────────────────────────────────────┐" + echo " │ 1. Install KDE Connect on your phone: │" + echo " │ Android: Play Store or F-Droid → search 'KDE Connect' │" + echo " │ iPhone: App Store → search 'KDE Connect' │" + echo " │ │" + echo " │ 2. Ensure your phone and computer are on the same WiFi network. │" + echo " │ │" + echo " │ 3. Open KDE Connect on your phone — your computer should │" + echo " │ appear automatically. Tap it and accept the pairing request │" + echo " │ on both devices. │" + echo " │ │" + echo " │ Linux Mint Cinnamon: a system tray applet is available — │" + echo " │ right-click the desktop → Applets → search 'KDE Connect' │" + echo " │ and add it to your panel. │" + echo " └──────────────────────────────────────────────────────────────────┘" + echo "" + + log_success "KDE Connect installation complete" +} + +# Run immediately when executed directly (deferred until after function definition) +[[ "${_RUN_STANDALONE:-0}" == 1 ]] && install_kdeconnect diff --git a/setup.sh b/setup.sh index 27b8a7b..15e2d98 100755 --- a/setup.sh +++ b/setup.sh @@ -79,6 +79,7 @@ is_installed() { base) command -v ncdu >/dev/null 2>&1 ;; glow) command -v glow >/dev/null 2>&1 ;; crowdsec) command -v cscli >/dev/null 2>&1 ;; + kdeconnect) command -v kdeconnect >/dev/null 2>&1 ;; silent-send) [ -d "$ACTUAL_HOME/silent-send/.git" ] ;; sync-cc) [ -f "$ACTUAL_HOME/sync-cc/sync_cc.py" ] ;; sky-cam) [ -d "$ACTUAL_HOME/sky-cam/.git" ] ;;