Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 1 addition & 33 deletions USAGE.md
Original file line number Diff line number Diff line change
Expand Up @@ -1216,40 +1216,8 @@ Next scheduled operations:
With multi-job support, each history record includes which job performed the operation:

```bash
# View history for specific job
# View history for a specific job
sudo backupd job show production # Includes recent history

# Filter history by job (programmatic)
# In scripts, use the get_job_history function:
source /etc/backupd/lib/history.sh
get_job_history "production" "all" 20 # Last 20 ops for production job
get_job_history "staging" "database" 10 # Last 10 DB backups for staging
```

**Job history summary:**

```bash
# Get summary statistics for all jobs (programmatic)
source /etc/backupd/lib/history.sh
get_history_by_jobs
```

Returns:
```json
{
"default": {
"total": 45,
"success": 43,
"failed": 2,
"last_backup": "2026-01-07T03:00:46+00:00"
},
"production": {
"total": 20,
"success": 20,
"failed": 0,
"last_backup": "2026-01-07T02:00:15+00:00"
}
}
```

---
Expand Down
31 changes: 0 additions & 31 deletions install.sh
100755 → 100644
Original file line number Diff line number Diff line change
Expand Up @@ -180,37 +180,6 @@ pkg_install() {
esac
}

# Get the install command hint for user-facing error messages
get_install_hint() {
local package="$1"
local pm
pm=$(detect_package_manager)

case "$pm" in
apt)
echo "sudo apt install $package"
;;
dnf)
echo "sudo dnf install $package"
;;
yum)
echo "sudo yum install $package"
;;
pacman)
echo "sudo pacman -S $package"
;;
apk)
echo "sudo apk add $package"
;;
zypper)
echo "sudo zypper install $package"
;;
*)
echo "Install '$package' using your system's package manager"
;;
esac
}

print_banner() {
echo -e "${CYAN}"
echo "╔═══════════════════════════════════════════════════════════╗"
Expand Down
171 changes: 0 additions & 171 deletions lib/core.sh
100755 → 100644
Original file line number Diff line number Diff line change
Expand Up @@ -63,19 +63,6 @@ if [[ -z "${BACKUPD_TRAP_SET:-}" ]]; then
BACKUPD_TRAP_SET=1
fi

# Helper to run a command and track its PID for cleanup
# Usage: run_tracked_command restic check -r "$repo"
run_tracked_command() {
"$@" &
local pid=$!
BACKUPD_CHILD_PIDS+=("$pid")
wait "$pid"
local exit_code=$?
# Remove PID from tracking array
BACKUPD_CHILD_PIDS=("${BACKUPD_CHILD_PIDS[@]/$pid/}")
return $exit_code
}

# ---------- Package Manager Functions ----------

# Package manager detection (cached)
Expand Down Expand Up @@ -292,19 +279,6 @@ json_output() {
echo "$1"
}

# Build simple JSON key-value pair - usage: json_kv "key" "value"
json_kv() {
local key="$1"
local value="$2"
# Escape special characters in value
value="${value//\\/\\\\}"
value="${value//\"/\\\"}"
value="${value//$'\n'/\\n}"
value="${value//$'\r'/\\r}"
value="${value//$'\t'/\\t}"
printf '"%s": "%s"' "$key" "$value"
}

# Check if JSON output mode is enabled
is_json_output() {
[[ "${JSON_OUTPUT:-0}" -eq 1 ]]
Expand Down Expand Up @@ -429,54 +403,6 @@ validate_password() {

# ---------- System Check Functions ----------

# Check available disk space (in MB)
check_disk_space() {
local path="$1"
local required_mb="${2:-1000}" # Default 1GB

local available_mb
available_mb=$(df -m "$path" 2>/dev/null | awk 'NR==2 {print $4}')

if [[ -z "$available_mb" ]]; then
print_warning "Could not check disk space - proceeding anyway"
log_warn "df output could not be parsed for path: $path"
return 0
fi

if [[ "$available_mb" -lt "$required_mb" ]]; then
print_error "Insufficient disk space. Available: ${available_mb}MB, Required: ${required_mb}MB"
return 1
fi

return 0
}

# Check network connectivity (supports curl/wget fallback)
# BACKUPD-007 FIX: Add wget fallback for systems without curl
check_network() {
local host="${1:-1.1.1.1}"
local timeout="${2:-5}"

# Try curl first (ICMP often blocked on servers)
if command -v curl &>/dev/null; then
if curl -s --connect-timeout "$timeout" "https://www.google.com" &>/dev/null; then
return 0
fi
elif command -v wget &>/dev/null; then
if wget -q --timeout="$timeout" -O /dev/null "https://www.google.com" 2>/dev/null; then
return 0
fi
fi

# Fallback to ping
if ! ping -c 1 -W "$timeout" "$host" &>/dev/null; then
print_error "No network connectivity"
return 1
fi

return 0
}

# Download file with curl/wget fallback
# Usage: download_to_file URL OUTPUT_FILE [TIMEOUT]
# BACKUPD-007 FIX: Support both curl and wget for maximum compatibility
Expand Down Expand Up @@ -510,26 +436,6 @@ fetch_url() {
fi
}

# ---------- MySQL Helper Functions ----------

# Create MySQL credentials file (more secure than command line)
create_mysql_auth_file() {
local user="$1"
local pass="$2"
local auth_file

auth_file="$(mktemp)"
chmod 600 "$auth_file"

cat > "$auth_file" << EOF
[client]
user=$user
password=$pass
EOF

echo "$auth_file"
}

# ---------- Logging Functions ----------

# Maximum log file size (10MB)
Expand Down Expand Up @@ -583,24 +489,6 @@ create_secure_temp() {
echo "$temp_dir"
}

# Safe file write (atomic)
safe_write_file() {
local target="$1"
local content="$2"
local temp_file

temp_file="$(mktemp "${target}.XXXXXXXXXX")"

if echo "$content" > "$temp_file" 2>/dev/null; then
chmod 600 "$temp_file"
mv "$temp_file" "$target"
return 0
else
rm -f "$temp_file"
return 1
fi
}

# ---------- Panel Detection Functions ----------

# Panel definitions: name|pattern|webroot_subdir|detection_method
Expand Down Expand Up @@ -804,11 +692,6 @@ get_panel_info() {
esac
}

# Get all panel keys
get_all_panel_keys() {
echo "${!PANEL_DEFINITIONS[@]}" | tr ' ' '\n' | sort
}

# Count sites for a given pattern
count_sites_for_pattern() {
local pattern="$1"
Expand All @@ -821,60 +704,6 @@ count_sites_for_pattern() {
echo "$count"
}

# ---------- Site Naming Functions ----------

# Get site name/URL from various app types
get_site_name() {
local site_path="$1"
local owner="${2:-www-data}"
local name=""

# 1. WordPress: wp option get siteurl
if [[ -f "$site_path/wp-config.php" ]]; then
if su -l -s /bin/bash "$owner" -c "command -v wp >/dev/null 2>&1" 2>/dev/null; then
name="$(su -l -s /bin/bash "$owner" -c "cd '$site_path' && wp option get siteurl 2>/dev/null" 2>/dev/null || true)"
fi
if [[ -z "$name" ]]; then
name="$(grep -E "define\s*\(\s*['\"]WP_HOME['\"]" "$site_path/wp-config.php" 2>/dev/null | head -1 | sed -E "s/.*['\"]https?:\/\/([^'\"]+)['\"].*/https:\/\/\1/" || true)"
fi
[[ -n "$name" ]] && echo "$name" && return 0
fi

# 2. Laravel: APP_URL from .env
if [[ -f "$site_path/.env" ]] && [[ -f "$site_path/artisan" ]]; then
name="$(grep -E "^APP_URL=" "$site_path/.env" 2>/dev/null | cut -d'=' -f2 | tr -d '"' | tr -d "'" || true)"
[[ -n "$name" ]] && echo "$name" && return 0
fi

# 3. Node.js: name from package.json
if [[ -f "$site_path/package.json" ]]; then
name="$(grep -E '"name"\s*:' "$site_path/package.json" 2>/dev/null | head -1 | sed -E 's/.*"name"\s*:\s*"([^"]+)".*/\1/' || true)"
[[ -n "$name" ]] && echo "$name" && return 0
fi

# 4. Generic: try to extract from nginx/apache configs in common locations
# Check for server_name in nginx configs
if [[ -d "/etc/nginx/sites-enabled" ]]; then
local nginx_name
nginx_name="$(grep -rh "server_name" /etc/nginx/sites-enabled/ 2>/dev/null | grep -i "$(basename "$site_path")" | head -1 | awk '{print $2}' | tr -d ';' || true)"
[[ -n "$nginx_name" && "$nginx_name" != "_" ]] && echo "$nginx_name" && return 0
fi

# 5. Fallback: use folder name
echo "$(basename "$site_path")"
}

# Sanitize name for use as filename
sanitize_for_filename() {
local s="$1"
s="$(echo -n "$s" | tr -d '[:space:]' | tr '[:upper:]' '[:lower:]')"
s="${s//:\/\//__}"; s="${s//\//__}"
s="$(echo -n "$s" | sed -E 's/[^a-z0-9._-]+/_/g')"
s="${s%.}"
[[ -z "$s" ]] && s="unknown-site"
printf "%s" "$s"
}

# ---------- Dependency Installation ----------

# Install rclone with SHA256 verification
Expand Down
25 changes: 0 additions & 25 deletions lib/crypto.sh
100755 → 100644
Original file line number Diff line number Diff line change
Expand Up @@ -435,28 +435,3 @@ migrate_secrets() {
echo "Migration complete!"
return 0
}

# Check if migration is recommended
migration_recommended() {
local secrets_dir="$1"
local current_version best_version

current_version="$(get_crypto_version "$secrets_dir")"
best_version="$(get_best_crypto_version)"

[[ "$current_version" -lt "$best_version" ]]
}

# Get migration recommendation message
get_migration_recommendation() {
local secrets_dir="$1"
local current_version best_version

current_version="$(get_crypto_version "$secrets_dir")"
best_version="$(get_best_crypto_version)"

if [[ "$current_version" -lt "$best_version" ]]; then
echo "Encryption upgrade available: $(get_crypto_name "$current_version") → $(get_crypto_name "$best_version")"
echo "Run 'backupd --migrate-encryption' to upgrade"
fi
}
38 changes: 0 additions & 38 deletions lib/generators.sh
100755 → 100644
Original file line number Diff line number Diff line change
Expand Up @@ -2111,41 +2111,3 @@ regenerate_all_job_scripts() {

return 0
}

# Generate scripts for default job from global config
# Used for backward compatibility during migration
# Usage: generate_default_job_scripts_from_config
generate_default_job_scripts_from_config() {
local install_dir="${INSTALL_DIR:-/etc/backupd}"

# Source jobs module
if ! declare -f job_exists &>/dev/null; then
source "$LIB_DIR/jobs.sh" 2>/dev/null || source "$install_dir/lib/jobs.sh" 2>/dev/null || {
print_error "Jobs module not found"
return 1
}
fi

# Create default job if it doesn't exist
if ! job_exists "default"; then
create_job "default" || return 1
fi

# Copy global config values to default job
local config_file="$install_dir/.config"
if [[ -f "$config_file" ]]; then
local keys=("RCLONE_REMOTE" "RCLONE_DB_PATH" "RCLONE_FILES_PATH" "RETENTION_DAYS" "RETENTION_DESC"
"WEB_PATH_PATTERN" "WEBROOT_SUBDIR" "DO_DATABASE" "DO_FILES" "PANEL_KEY")
local key value

for key in "${keys[@]}"; do
value="$(grep "^${key}=" "$config_file" 2>/dev/null | cut -d'=' -f2- | tr -d '"')" || value=""
if [[ -n "$value" ]]; then
save_job_config "default" "$key" "$value"
fi
done
fi

# Generate scripts for default job
generate_job_scripts "default"
}
Loading