Compare commits
10 Commits
9a163b3bf2
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 3cd5d2d266 | |||
| f43880d4ea | |||
| e4b7b8dec7 | |||
| 60500e6bc4 | |||
|
|
f1d6a102da | ||
|
|
21aebb7860 | ||
|
|
58cf7995b8 | ||
|
|
4a8d816a82 | ||
|
|
426d4f4c75 | ||
|
|
2613e684c1 |
@@ -9,3 +9,6 @@ DB_PASS=password_mysql
|
|||||||
# Gotify
|
# Gotify
|
||||||
GOTIFY_URL="https://alert.qwince.com/message"
|
GOTIFY_URL="https://alert.qwince.com/message"
|
||||||
GOTIFY_TOKEN="ABnq7pJSSPrFRjx"
|
GOTIFY_TOKEN="ABnq7pJSSPrFRjx"
|
||||||
|
|
||||||
|
# Upload HTTP endpoint
|
||||||
|
UPLOAD_URL="http://192.168.0.10:8080/upload"
|
||||||
|
|||||||
90
README.md
90
README.md
@@ -2,62 +2,84 @@
|
|||||||
|
|
||||||
Script bash per eseguire il backup automatico di un database MySQL e della cartella del sito web.
|
Script bash per eseguire il backup automatico di un database MySQL e della cartella del sito web.
|
||||||
|
|
||||||
|
## Avvio rapido
|
||||||
|
```bash
|
||||||
|
git clone https://git.pyconetwork.it/francesco/cloudpanel-backup.git && cd cloudpanel-backup && chmod +x *.sh && ./init.sh
|
||||||
|
```
|
||||||
|
|
||||||
## Configurazione
|
## Configurazione
|
||||||
|
|
||||||
1. Crea il file `.secret` nella stessa cartella dello script:
|
1. Esegui lo script di inizializzazione:
|
||||||
```bash
|
```bash
|
||||||
cp .secret.example .secret
|
chmod +x init.sh
|
||||||
|
./init.sh
|
||||||
```
|
```
|
||||||
|
|
||||||
2. Modifica il file `.secret` con le tue credenziali:
|
2. Lo script ti chiederà:
|
||||||
|
- Nome utente
|
||||||
|
- Host del database (default: localhost)
|
||||||
|
- Nome del database
|
||||||
|
- Utente del database (default: nome del database)
|
||||||
|
- Password del database
|
||||||
|
|
||||||
|
3. Il file `.secret.UTENTE` verrà creato automaticamente con le credenziali fornite.
|
||||||
|
|
||||||
|
4. (Opzionale) Modifica il file per configurare Gotify e upload remoto:
|
||||||
```bash
|
```bash
|
||||||
DB_HOST=localhost
|
nano .secret.UTENTE
|
||||||
DB_NAME=nome_del_tuo_database
|
|
||||||
DB_USER=tuo_utente
|
|
||||||
DB_PASS=tua_password
|
|
||||||
```
|
```
|
||||||
|
|
||||||
3. Rendi eseguibile lo script:
|
5. Rendi eseguibile lo script di backup:
|
||||||
```bash
|
```bash
|
||||||
chmod +x backup.sh
|
chmod +x backup.sh
|
||||||
```
|
```
|
||||||
|
|
||||||
## Utilizzo
|
## Utilizzo
|
||||||
|
|
||||||
Esegui lo script specificando il dominio come parametro:
|
Esegui lo script specificando utente e dominio:
|
||||||
```bash
|
```bash
|
||||||
./backup.sh nome_dominio
|
./backup.sh utente dominio
|
||||||
```
|
```
|
||||||
|
|
||||||
Esempio:
|
Esempio:
|
||||||
```bash
|
```bash
|
||||||
./backup.sh esempio.com
|
./backup.sh myuser esempio.com
|
||||||
```
|
```
|
||||||
|
|
||||||
## Cosa fa lo script
|
## Configurazione su Webmin/Cron
|
||||||
|
|
||||||
1. Accetta il dominio come parametro da riga di comando
|
1. Scarica il progetto:
|
||||||
2. Legge le credenziali dal file `.secret`
|
```bash
|
||||||
3. Esegue il dump del database MySQL specificato
|
cd /home/_UTENTE_/
|
||||||
4. Copia la cartella `/home/utente_DOMINIO/htdocs/DOMINIO`
|
git clone https://git.pyconetwork.it/francesco/cloudpanel-backup.git
|
||||||
5. Crea un archivio ZIP contenente:
|
cd cloudpanel-backup
|
||||||
- Dump del database (formato .sql)
|
```
|
||||||
- Copia completa della cartella htdocs
|
|
||||||
6. Il file ZIP finale ha il formato: `backup_DOMINIO_YYYYMMDD_HHMMSS.zip`
|
2. Configura con init.sh:
|
||||||
7. Pulisce i file temporanei
|
```bash
|
||||||
|
chmod +x init.sh
|
||||||
|
./init.sh
|
||||||
|
chmod +x backup.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
3. Su cron manager inserisci:
|
||||||
|
```bash
|
||||||
|
/home/UTENTE/cloudpanel-backup/backup.sh UTENTE dominio.com
|
||||||
|
```
|
||||||
|
|
||||||
|
## Funzionalità
|
||||||
|
|
||||||
|
1. Esegue il dump del database MySQL specificato
|
||||||
|
2. Copia la cartella `/home/UTENTE/htdocs/DOMINIO`
|
||||||
|
3. Crea un archivio ZIP contenente database e file del sito
|
||||||
|
4. (Opzionale) Trasferisce il backup su server remoto
|
||||||
|
5. (Opzionale) Invia notifiche via Gotify
|
||||||
|
6. Pulisce i file temporanei
|
||||||
|
7. Il file ZIP ha il formato: `backup_DOMINIO_YYYYMMDD_HHMMSS.zip`
|
||||||
|
|
||||||
## Note di sicurezza
|
## Note di sicurezza
|
||||||
|
|
||||||
- Il file `.secret` contiene credenziali sensibili
|
- Il file `.secret.UTENTE` contiene credenziali sensibili
|
||||||
- Assicurati che abbia permessi appropriati: `chmod 600 .secret`
|
- Assicurati che abbia permessi appropriati: `chmod 600 .secret.*`
|
||||||
- Non versionare il file `.secret` su repository pubblici
|
- Non versionare i file `.secret.*` su repository pubblici
|
||||||
- Aggiungi `.secret` al tuo `.gitignore`
|
- Sono già inclusi nel `.gitignore`
|
||||||
|
|
||||||
## Percorso delle cartelle
|
|
||||||
|
|
||||||
Lo script costruisce automaticamente il percorso basandosi sul dominio fornito:
|
|
||||||
- Utente: `utente_DOMINIO`
|
|
||||||
- Percorso: `/home/utente_DOMINIO/htdocs/DOMINIO`
|
|
||||||
|
|
||||||
Esempio per il dominio `esempio.com`:
|
|
||||||
- Percorso completo: `/home/utente_esempio.com/htdocs/esempio.com`
|
|
||||||
|
|||||||
95
backup.sh
95
backup.sh
@@ -2,21 +2,22 @@
|
|||||||
|
|
||||||
# Script di backup per database MySQL e cartella htdocs
|
# Script di backup per database MySQL e cartella htdocs
|
||||||
# Le credenziali del database devono essere nel file .secret
|
# Le credenziali del database devono essere nel file .secret
|
||||||
# Uso: ./backup.sh dominio
|
# Uso: ./backup.sh user dominio
|
||||||
|
|
||||||
# Verifica parametro dominio
|
# Verifica parametri user e dominio
|
||||||
if [ -z "$1" ]; then
|
if [ -z "$1" ] || [ -z "$2" ]; then
|
||||||
echo "Errore: Specificare il dominio come parametro"
|
echo "Errore: Specificare user e dominio come parametri"
|
||||||
echo "Uso: $0 dominio"
|
echo "Uso: $0 user dominio"
|
||||||
echo "Esempio: $0 esempio.com"
|
echo "Esempio: $0 utente esempio.com"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
DOMAIN="$1"
|
USER="$1"
|
||||||
|
DOMAIN="$2"
|
||||||
|
|
||||||
# Ottieni la directory dello script
|
# Ottieni la directory dello script
|
||||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
SECRET_FILE="$SCRIPT_DIR/.secret"
|
SECRET_FILE="$SCRIPT_DIR/.secret.$USER"
|
||||||
|
|
||||||
# Verifica che il file .secret esista
|
# Verifica che il file .secret esista
|
||||||
if [ ! -f "$SECRET_FILE" ]; then
|
if [ ! -f "$SECRET_FILE" ]; then
|
||||||
@@ -54,10 +55,57 @@ send_gotify_notification() {
|
|||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Funzione per trasferire il backup su server remoto via HTTP
|
||||||
|
transfer_to_remote() {
|
||||||
|
local file="$1"
|
||||||
|
|
||||||
|
if [ -z "$UPLOAD_URL" ]; then
|
||||||
|
echo "Attenzione: URL di upload non configurato, trasferimento saltato"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Verifica disponibilità del server
|
||||||
|
echo "Verifica disponibilità server remoto..."
|
||||||
|
SERVER_CHECK=$(curl -s -o /dev/null -w "%{http_code}" --connect-timeout 5 --max-time 10 "$UPLOAD_URL" 2>/dev/null)
|
||||||
|
|
||||||
|
if [ $? -ne 0 ] || [ -z "$SERVER_CHECK" ]; then
|
||||||
|
echo "⚠️ Server remoto non raggiungibile"
|
||||||
|
send_gotify_notification "⚠️ [ $DOMAIN ] Backup Locale" "Data: $DATE_FORMAT\nBackup di $DOMAIN completato\nServer remoto non disponibile\nFile mantenuto in locale: backup_${DOMAIN}_$TIMESTAMP.zip" 6
|
||||||
|
return 2
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Server disponibile (HTTP $SERVER_CHECK)"
|
||||||
|
echo "Trasferimento backup su server remoto via HTTP..."
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Upload del file via curl con barra di progresso
|
||||||
|
RESPONSE=$(curl -X POST "$UPLOAD_URL" -F "file=@$file" -#)
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
echo "Errore durante il trasferimento del backup"
|
||||||
|
send_gotify_notification "⚠️ [ $DOMAIN ] Backup Parziale" "Data: $DATE_FORMAT\nBackup di $DOMAIN completato ma trasferimento remoto fallito" 6
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Verifica la risposta
|
||||||
|
if echo "$RESPONSE" | grep -q '"status":"ok"'; then
|
||||||
|
echo "Backup trasferito con successo"
|
||||||
|
echo "Risposta server: $RESPONSE"
|
||||||
|
return 0
|
||||||
|
else
|
||||||
|
echo "Errore: Risposta server non valida"
|
||||||
|
echo "Risposta: $RESPONSE"
|
||||||
|
send_gotify_notification "⚠️ [ $DOMAIN ] Backup Parziale" "Data: $DATE_FORMAT\nBackup di $DOMAIN completato ma upload fallito" 6
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
# Configurazione
|
# Configurazione
|
||||||
TIMESTAMP=$(date +"%Y%m%d_%H%M%S")
|
TIMESTAMP=$(date +"%Y%m%d_%H%M%S")
|
||||||
|
DATE_FORMAT=$(date +"%d/%m/%Y")
|
||||||
BACKUP_DIR="$SCRIPT_DIR/backup_${DOMAIN}_$TIMESTAMP"
|
BACKUP_DIR="$SCRIPT_DIR/backup_${DOMAIN}_$TIMESTAMP"
|
||||||
SITE_DIR="/home/$(whoami)/htdocs/${DOMAIN}"
|
SITE_DIR="/home/${USER}/htdocs/${DOMAIN}"
|
||||||
DB_DUMP_FILE="$BACKUP_DIR/database_$TIMESTAMP.sql"
|
DB_DUMP_FILE="$BACKUP_DIR/database_$TIMESTAMP.sql"
|
||||||
ZIP_FILE="$SCRIPT_DIR/backup_${DOMAIN}_$TIMESTAMP.zip"
|
ZIP_FILE="$SCRIPT_DIR/backup_${DOMAIN}_$TIMESTAMP.zip"
|
||||||
|
|
||||||
@@ -71,7 +119,7 @@ mysqldump --no-tablespaces -h "$DB_HOST" -u "$DB_USER" -p"$DB_PASS" "$DB_NAME" >
|
|||||||
|
|
||||||
if [ $? -ne 0 ]; then
|
if [ $? -ne 0 ]; then
|
||||||
echo "Errore durante il dump del database"
|
echo "Errore durante il dump del database"
|
||||||
send_gotify_notification "❌ Backup Fallito" "Errore durante il dump del database $DB_NAME per $DOMAIN" 8
|
send_gotify_notification "❌ [ $DOMAIN ] Backup Fallito" "Data: $DATE_FORMAT\nErrore durante il dump del database $DB_NAME per $DOMAIN" 8
|
||||||
rm -rf "$BACKUP_DIR"
|
rm -rf "$BACKUP_DIR"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
@@ -89,7 +137,7 @@ else
|
|||||||
|
|
||||||
if [ $? -ne 0 ]; then
|
if [ $? -ne 0 ]; then
|
||||||
echo "Errore durante la copia della cartella del sito"
|
echo "Errore durante la copia della cartella del sito"
|
||||||
send_gotify_notification "❌ Backup Fallito" "Errore durante la copia della cartella $SITE_DIR" 8
|
send_gotify_notification "❌ [ $DOMAIN ] Backup Fallito" "Data: $DATE_FORMAT\nErrore durante la copia della cartella $SITE_DIR" 8
|
||||||
rm -rf "$BACKUP_DIR"
|
rm -rf "$BACKUP_DIR"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
@@ -104,7 +152,7 @@ zip -r "$ZIP_FILE" "backup_${DOMAIN}_$TIMESTAMP"
|
|||||||
|
|
||||||
if [ $? -ne 0 ]; then
|
if [ $? -ne 0 ]; then
|
||||||
echo "Errore durante la creazione dell'archivio zip"
|
echo "Errore durante la creazione dell'archivio zip"
|
||||||
send_gotify_notification "❌ Backup Fallito" "Errore durante la creazione dell'archivio zip per $DOMAIN" 8
|
send_gotify_notification "❌ [ $DOMAIN ] Backup Fallito" "Data: $DATE_FORMAT\nErrore durante la creazione dell'archivio zip per $DOMAIN" 8
|
||||||
rm -rf "$BACKUP_DIR"
|
rm -rf "$BACKUP_DIR"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
@@ -124,5 +172,24 @@ echo "File: $ZIP_FILE"
|
|||||||
echo "Dimensione: $BACKUP_SIZE"
|
echo "Dimensione: $BACKUP_SIZE"
|
||||||
echo "=========================================="
|
echo "=========================================="
|
||||||
|
|
||||||
# Invia notifica di successo
|
# Trasferisci il backup su server remoto
|
||||||
send_gotify_notification "✅ Backup Completato" "Backup di $DOMAIN completato con successo\nFile: backup_${DOMAIN}_$TIMESTAMP.zip\nDimensione: $BACKUP_SIZE" 5
|
transfer_to_remote "$ZIP_FILE"
|
||||||
|
TRANSFER_STATUS=$?
|
||||||
|
|
||||||
|
# Se il trasferimento è riuscito, rimuovi il file locale
|
||||||
|
if [ $TRANSFER_STATUS -eq 0 ]; then
|
||||||
|
echo "Rimozione file locale..."
|
||||||
|
rm -f "$ZIP_FILE"
|
||||||
|
echo "File zip rimosso dal locale, disponibile solo sul server remoto"
|
||||||
|
send_gotify_notification "✅ [ $DOMAIN ] Backup Completato" "Data: $DATE_FORMAT\nBackup di $DOMAIN completato con successo\nFile: backup_${DOMAIN}_$TIMESTAMP.zip\nDimensione: $BACKUP_SIZE\nCaricato sul server remoto" 5
|
||||||
|
elif [ $TRANSFER_STATUS -eq 2 ]; then
|
||||||
|
# Server non disponibile - mantieni solo l'ultima copia locale
|
||||||
|
echo "Pulizia backup precedenti..."
|
||||||
|
find "$SCRIPT_DIR" -name "backup_${DOMAIN}_*.zip" -type f ! -name "backup_${DOMAIN}_$TIMESTAMP.zip" -delete
|
||||||
|
echo "Mantenuta solo l'ultima copia locale"
|
||||||
|
else
|
||||||
|
# Errore durante il trasferimento - mantieni solo l'ultima copia locale
|
||||||
|
echo "Pulizia backup precedenti..."
|
||||||
|
find "$SCRIPT_DIR" -name "backup_${DOMAIN}_*.zip" -type f ! -name "backup_${DOMAIN}_$TIMESTAMP.zip" -delete
|
||||||
|
send_gotify_notification "⚠️ Backup Parziale" "Data: $DATE_FORMAT\nBackup di $DOMAIN completato localmente\nFile: backup_${DOMAIN}_$TIMESTAMP.zip\nDimensione: $BACKUP_SIZE\nTrasferimento remoto fallito - File mantenuto in locale" 6
|
||||||
|
fi
|
||||||
|
|||||||
85
init.sh
Normal file
85
init.sh
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Script di inizializzazione per creare il file .secret personalizzato
|
||||||
|
|
||||||
|
echo "=========================================="
|
||||||
|
echo "Inizializzazione configurazione backup"
|
||||||
|
echo "=========================================="
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Richiedi nome utente
|
||||||
|
read -p "Inserisci il nome utente: " USERNAME
|
||||||
|
|
||||||
|
if [ -z "$USERNAME" ]; then
|
||||||
|
echo "Errore: Nome utente non può essere vuoto"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "Configurazione database:"
|
||||||
|
echo "------------------------"
|
||||||
|
|
||||||
|
# Richiedi host del database
|
||||||
|
read -p "Host del database [localhost]: " DB_HOST
|
||||||
|
DB_HOST=${DB_HOST:-localhost}
|
||||||
|
|
||||||
|
# Richiedi nome del database
|
||||||
|
read -p "Nome del database: " DB_NAME
|
||||||
|
if [ -z "$DB_NAME" ]; then
|
||||||
|
echo "Errore: Nome database non può essere vuoto"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Richiedi utente del database
|
||||||
|
read -p "Utente del database [$DB_NAME]: " DB_USER
|
||||||
|
DB_USER=${DB_USER:-$DB_NAME}
|
||||||
|
|
||||||
|
# Richiedi password del database
|
||||||
|
read -sp "Password del database: " DB_PASS
|
||||||
|
echo ""
|
||||||
|
if [ -z "$DB_PASS" ]; then
|
||||||
|
echo "Errore: Password non può essere vuota"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Ottieni la directory dello script
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
SECRET_FILE="$SCRIPT_DIR/.secret.$USERNAME"
|
||||||
|
EXAMPLE_FILE="$SCRIPT_DIR/.secret.example"
|
||||||
|
|
||||||
|
# Verifica che il file example esista
|
||||||
|
if [ ! -f "$EXAMPLE_FILE" ]; then
|
||||||
|
echo "Errore: File .secret.example non trovato"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Verifica se il file esiste già
|
||||||
|
if [ -f "$SECRET_FILE" ]; then
|
||||||
|
echo ""
|
||||||
|
read -p "Il file .secret.$USERNAME esiste già. Sovrascrivere? (s/n): " CONFIRM
|
||||||
|
if [ "$CONFIRM" != "s" ] && [ "$CONFIRM" != "S" ]; then
|
||||||
|
echo "Operazione annullata"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Copia il file example
|
||||||
|
cp "$EXAMPLE_FILE" "$SECRET_FILE"
|
||||||
|
|
||||||
|
# Sostituisci i valori nel file
|
||||||
|
sed -i "s/^DB_HOST=.*/DB_HOST=$DB_HOST/" "$SECRET_FILE"
|
||||||
|
sed -i "s/^DB_NAME=.*/DB_NAME=$DB_NAME/" "$SECRET_FILE"
|
||||||
|
sed -i "s/^DB_USER=.*/DB_USER=$DB_USER/" "$SECRET_FILE"
|
||||||
|
sed -i "s/^DB_PASS=.*/DB_PASS=$DB_PASS/" "$SECRET_FILE"
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "=========================================="
|
||||||
|
echo "File $SECRET_FILE creato con successo!"
|
||||||
|
echo "=========================================="
|
||||||
|
echo ""
|
||||||
|
echo "Configurazione salvata:"
|
||||||
|
echo " - Host: $DB_HOST"
|
||||||
|
echo " - Database: $DB_NAME"
|
||||||
|
echo " - Utente: $DB_USER"
|
||||||
|
echo ""
|
||||||
|
echo "=========================================="
|
||||||
Reference in New Issue
Block a user