#!/bin/sh # RPCD backend for Nextcloud LuCI app (LXC version) # Copyright (C) 2025 CyberMind.fr CONFIG="nextcloud" LXC_NAME="nextcloud" LXC_ROOTFS="/srv/lxc/nextcloud/rootfs" uci_get() { uci -q get ${CONFIG}.$1; } uci_set() { uci set ${CONFIG}.$1="$2" && uci commit ${CONFIG}; } # Check if LXC container is running lxc_running() { lxc-info -n "$LXC_NAME" -s 2>/dev/null | grep -q "RUNNING" } # Check if container is installed lxc_installed() { [ -d "$LXC_ROOTFS" ] && [ -f "/srv/lxc/$LXC_NAME/config" ] } # Get service status get_status() { local enabled=$(uci_get main.enabled) local http_port=$(uci_get main.http_port) local data_path=$(uci_get main.data_path) local domain=$(uci_get main.domain) local ssl_enabled=$(uci_get ssl.enabled) local ssl_domain=$(uci_get ssl.domain) # Container status local running=0 local installed=0 local version="" local user_count=0 local disk_used="0" lxc_installed && installed=1 lxc_running && running=1 # Get Nextcloud info if running if [ "$running" = "1" ]; then version=$(lxc-attach -n "$LXC_NAME" -- su -s /bin/bash www-data -c "php /var/www/nextcloud/occ -V" 2>/dev/null | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' || echo "") user_count=$(lxc-attach -n "$LXC_NAME" -- su -s /bin/bash www-data -c "php /var/www/nextcloud/occ user:list --output=json" 2>/dev/null | jsonfilter -e '@[*]' 2>/dev/null | wc -l || echo 0) fi # Get disk usage if [ -d "${data_path:-/srv/nextcloud}/data" ]; then disk_used=$(du -sh "${data_path:-/srv/nextcloud}/data" 2>/dev/null | awk '{print $1}' || echo "0") fi # Get LAN IP local lan_ip lan_ip=$(uci -q get network.lan.ipaddr || echo "192.168.255.1") # Check web accessibility local web_accessible=0 if [ "$running" = "1" ]; then wget -q -O /dev/null --timeout=2 "http://127.0.0.1:${http_port:-8080}/status.php" 2>/dev/null && web_accessible=1 fi cat </dev/null) local data_path=$(echo "$input" | jsonfilter -e '@.data_path' 2>/dev/null) local domain=$(echo "$input" | jsonfilter -e '@.domain' 2>/dev/null) local admin_user=$(echo "$input" | jsonfilter -e '@.admin_user' 2>/dev/null) local memory_limit=$(echo "$input" | jsonfilter -e '@.memory_limit' 2>/dev/null) local upload_max=$(echo "$input" | jsonfilter -e '@.upload_max' 2>/dev/null) [ -n "$http_port" ] && uci_set main.http_port "$http_port" [ -n "$data_path" ] && uci_set main.data_path "$data_path" [ -n "$domain" ] && uci_set main.domain "$domain" [ -n "$admin_user" ] && uci_set main.admin_user "$admin_user" [ -n "$memory_limit" ] && uci_set main.memory_limit "$memory_limit" [ -n "$upload_max" ] && uci_set main.upload_max "$upload_max" echo '{"success": true}' } # Install Nextcloud do_install() { if command -v nextcloudctl >/dev/null 2>&1; then nextcloudctl install >/tmp/nextcloud-install.log 2>&1 & echo '{"success": true, "message": "Installation started in background"}' else echo '{"success": false, "error": "nextcloudctl not found"}' fi } # Start service do_start() { if [ -x /etc/init.d/nextcloud ]; then uci_set main.enabled '1' /etc/init.d/nextcloud start >/dev/null 2>&1 sleep 2 echo '{"success": true}' else echo '{"success": false, "error": "Service not installed"}' fi } # Stop service do_stop() { if [ -x /etc/init.d/nextcloud ]; then /etc/init.d/nextcloud stop >/dev/null 2>&1 echo '{"success": true}' else echo '{"success": false, "error": "Service not installed"}' fi } # Restart service do_restart() { if [ -x /etc/init.d/nextcloud ]; then /etc/init.d/nextcloud restart >/dev/null 2>&1 echo '{"success": true}' else echo '{"success": false, "error": "Service not installed"}' fi } # Update container do_update() { if command -v nextcloudctl >/dev/null 2>&1; then nextcloudctl update >/tmp/nextcloud-update.log 2>&1 & echo '{"success": true, "message": "Update started in background"}' else echo '{"success": false, "error": "nextcloudctl not found"}' fi } # Create backup do_backup() { local input read -r input local name=$(echo "$input" | jsonfilter -e '@.name' 2>/dev/null) if command -v nextcloudctl >/dev/null 2>&1; then local result if [ -n "$name" ]; then result=$(nextcloudctl backup "$name" 2>&1) else result=$(nextcloudctl backup 2>&1) fi echo "{\"success\": true, \"backup_name\": \"$result\"}" else echo '{"success": false, "error": "nextcloudctl not found"}' fi } # Restore backup do_restore() { local input read -r input local name=$(echo "$input" | jsonfilter -e '@.name' 2>/dev/null) if [ -z "$name" ]; then echo '{"success": false, "error": "No backup name specified"}' return fi if command -v nextcloudctl >/dev/null 2>&1; then nextcloudctl restore "$name" >/tmp/nextcloud-restore.log 2>&1 & echo '{"success": true, "message": "Restore started in background"}' else echo '{"success": false, "error": "nextcloudctl not found"}' fi } # List backups list_backups() { local data_path=$(uci_get main.data_path) local backup_dir="${data_path:-/srv/nextcloud}/backups" local backups="[]" if [ -d "$backup_dir" ]; then backups=$(ls -1 "$backup_dir"/*-db.sql 2>/dev/null | while read f; do local name=$(basename "$f" -db.sql) local data_file="$backup_dir/$name-data.tar.gz" local size="N/A" local timestamp=0 if [ -f "$data_file" ]; then size=$(ls -lh "$data_file" | awk '{print $5}') fi timestamp=$(stat -c %Y "$f" 2>/dev/null || echo 0) printf '{"name":"%s","size":"%s","timestamp":%d},' "$name" "$size" "$timestamp" done | sed 's/,$//' | sed 's/^/[/;s/$/]/') fi [ -z "$backups" ] && backups="[]" echo "{\"backups\": $backups}" } # Enable SSL do_ssl_enable() { local input read -r input local domain=$(echo "$input" | jsonfilter -e '@.domain' 2>/dev/null) if [ -z "$domain" ]; then echo '{"success": false, "error": "No domain specified"}' return fi if command -v nextcloudctl >/dev/null 2>&1; then nextcloudctl ssl-enable "$domain" >/tmp/nextcloud-ssl.log 2>&1 echo '{"success": true, "message": "SSL enabled for '$domain'"}' else echo '{"success": false, "error": "nextcloudctl not found"}' fi } # Disable SSL do_ssl_disable() { if command -v nextcloudctl >/dev/null 2>&1; then nextcloudctl ssl-disable >/dev/null 2>&1 echo '{"success": true}' else echo '{"success": false, "error": "nextcloudctl not found"}' fi } # Run OCC command do_occ() { local input read -r input local cmd=$(echo "$input" | jsonfilter -e '@.command' 2>/dev/null) if [ -z "$cmd" ]; then echo '{"success": false, "error": "No command specified"}' return fi if command -v nextcloudctl >/dev/null 2>&1; then local output=$(nextcloudctl occ $cmd 2>&1) local escaped=$(echo "$output" | sed 's/"/\\"/g' | tr '\n' ' ') echo "{\"success\": true, \"output\": \"$escaped\"}" else echo '{"success": false, "error": "nextcloudctl not found"}' fi } # Get logs get_logs() { local lines=100 local log_content="" # Check install log if [ -f /tmp/nextcloud-install.log ]; then log_content=$(tail -n $lines /tmp/nextcloud-install.log 2>/dev/null | sed 's/"/\\"/g' | tr '\n' '|') fi echo "{\"logs\": \"$log_content\"}" } # RPCD list method list_methods() { cat <<'EOF' { "status": {}, "get_config": {}, "save_config": {"http_port": "string", "data_path": "string", "domain": "string", "admin_user": "string", "memory_limit": "string", "upload_max": "string"}, "install": {}, "start": {}, "stop": {}, "restart": {}, "update": {}, "backup": {"name": "string"}, "restore": {"name": "string"}, "list_backups": {}, "ssl_enable": {"domain": "string"}, "ssl_disable": {}, "occ": {"command": "string"}, "logs": {} } EOF } # Main entry point case "$1" in list) list_methods ;; call) case "$2" in status) get_status ;; get_config) get_config ;; save_config) save_config ;; install) do_install ;; start) do_start ;; stop) do_stop ;; restart) do_restart ;; update) do_update ;; backup) do_backup ;; restore) do_restore ;; list_backups) list_backups ;; ssl_enable) do_ssl_enable ;; ssl_disable) do_ssl_disable ;; occ) do_occ ;; logs) get_logs ;; *) echo '{"error": "Unknown method"}' ;; esac ;; *) echo '{"error": "Unknown command"}' ;; esac