#!/bin/bash locationAdd() { local name="$1" local type="${2:-local}" if [[ -z "$name" ]]; then isError "locationAdd requires a name" return 1 fi case "$type" in local|sftp|rest|s3|b2|gs|azure|rclone) ;; *) isError "Unsupported location type: $type"; return 1 ;; esac local idx idx=$(resticNextFreeIndex) local default_engine="${CFG_BACKUP_ENGINE:-restic}" local default_path_mode="auto" local default_path="" backupLocationEnsureDir "$idx" local cfg_file cfg_file=$(backupLocationConfig "$idx") local owner owner=$(backupLocationOwner) { echo "# Backup location $idx — added $(date -Iseconds)." echo "# Edit via the Locations page on /backup, or directly here." echo "CFG_BACKUP_LOC_${idx}_NAME=\"${name}\" # Location Name - Friendly label shown in the UI" echo "CFG_BACKUP_LOC_${idx}_ENABLED=false # Enabled - Snapshot to this location" echo "CFG_BACKUP_LOC_${idx}_ENGINE=${default_engine} # Engine - Backup engine used at this location [restic:Restic|borg:BorgBackup|kopia:Kopia] **ADVANCED**" echo "CFG_BACKUP_LOC_${idx}_PASSWORD=RANDOMIZEDPASSWORD1 # Repository Password - Used to encrypt/decrypt snapshots — back up offline!" echo "CFG_BACKUP_LOC_${idx}_TYPE=${type} # Type - Backend [local:Local / mounted path|sftp:SFTP|rest:REST|s3:S3|b2:Backblaze B2|gs:Google Cloud Storage|azure:Azure|rclone:rclone]" echo "CFG_BACKUP_LOC_${idx}_PATH_MODE=${default_path_mode} # Path Mode - Automatic uses the Default Backup Location from the Backup Engine config (one subfolder per location); Custom uses the path below [auto:Automatic|custom:Custom path]" echo "CFG_BACKUP_LOC_${idx}_PATH=${default_path} # Custom Path - Filesystem path on this server (used when Path Mode = Custom)" echo "CFG_BACKUP_LOC_${idx}_URI= # URI Override - Custom restic URI (leave blank to build from the fields below) **ADVANCED**" echo "CFG_BACKUP_LOC_${idx}_SSH_USER= # SSH User - For sftp type" echo "CFG_BACKUP_LOC_${idx}_SSH_HOST= # SSH Host - For sftp type" echo "CFG_BACKUP_LOC_${idx}_SSH_PORT=22 # SSH Port - For sftp type **ADVANCED**" echo "CFG_BACKUP_LOC_${idx}_SSH_PATH= # SSH Remote Path - Path on the remote host where the repo lives" echo "CFG_BACKUP_LOC_${idx}_SSH_AUTH=key # SSH Authentication - [key:SSH key (managed by LibrePortal)|password:Password (via sshpass)]" echo "CFG_BACKUP_LOC_${idx}_SSH_PASS= # SSH Password - Used only when SSH Authentication is set to Password" echo "CFG_BACKUP_LOC_${idx}_S3_ACCESS_KEY=" echo "CFG_BACKUP_LOC_${idx}_S3_SECRET_KEY=" echo "CFG_BACKUP_LOC_${idx}_B2_ACCOUNT_ID=" echo "CFG_BACKUP_LOC_${idx}_B2_ACCOUNT_KEY=" echo "CFG_BACKUP_LOC_${idx}_APPEND_ONLY=false # Append-only - Refuse forget/prune for this location (ransomware-safe) **ADVANCED**" echo "CFG_BACKUP_LOC_${idx}_CUSTOM_RETENTION=false" echo "CFG_BACKUP_LOC_${idx}_KEEP_LAST=" echo "CFG_BACKUP_LOC_${idx}_KEEP_DAILY=" echo "CFG_BACKUP_LOC_${idx}_KEEP_WEEKLY=" echo "CFG_BACKUP_LOC_${idx}_KEEP_MONTHLY=" echo "CFG_BACKUP_LOC_${idx}_KEEP_YEARLY=" } | runFileWrite "$cfg_file" >/dev/null runFileOp chown "$owner":"$owner" "$cfg_file" runFileOp chmod 0640 "$cfg_file" if declare -f replacePlainPasswords >/dev/null 2>&1; then replacePlainPasswords "$cfg_file" fi source "$cfg_file" isSuccessful "Location $idx '$name' added at $(backupLocationDir "$idx") (type: $type, engine: $default_engine, disabled by default)" if declare -f webuiGenerateBackupLocations >/dev/null 2>&1; then webuiGenerateBackupLocations fi echo "$idx" }