mirror of
https://github.com/jkaninda/mysql-bkup.git
synced 2025-12-06 13:39:41 +01:00
Compare commits
8 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 0df14f37b4 | |||
| 1b60ca6fd2 | |||
| d880f40108 | |||
|
|
c845b36797 | ||
| 63d615f838 | |||
| 6f31d35df2 | |||
| f36d01cc96 | |||
| 07b7f54a75 |
@@ -1,4 +1,4 @@
|
|||||||
FROM golang:1.23.3 AS build
|
FROM golang:1.23.4 AS build
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
ARG appVersion=""
|
ARG appVersion=""
|
||||||
|
|
||||||
|
|||||||
@@ -32,44 +32,46 @@ Backup, restore and migrate targets, schedule and retention are configured using
|
|||||||
|
|
||||||
## Environment variables
|
## Environment variables
|
||||||
|
|
||||||
| Name | Requirement | Description |
|
| Name | Requirement | Description |
|
||||||
|------------------------|---------------------------------------------------------------|-----------------------------------------------------------------|
|
|------------------------------|---------------------------------------------------------------|-----------------------------------------------------------------|
|
||||||
| DB_PORT | Optional, default 3306 | Database port number |
|
| DB_PORT | Optional, default 3306 | Database port number |
|
||||||
| DB_HOST | Required | Database host |
|
| DB_HOST | Required | Database host |
|
||||||
| DB_NAME | Optional if it was provided from the -d flag | Database name |
|
| DB_NAME | Optional if it was provided from the -d flag | Database name |
|
||||||
| DB_USERNAME | Required | Database user name |
|
| DB_USERNAME | Required | Database user name |
|
||||||
| DB_PASSWORD | Required | Database password |
|
| DB_PASSWORD | Required | Database password |
|
||||||
| AWS_ACCESS_KEY | Optional, required for S3 storage | AWS S3 Access Key |
|
| AWS_ACCESS_KEY | Optional, required for S3 storage | AWS S3 Access Key |
|
||||||
| AWS_SECRET_KEY | Optional, required for S3 storage | AWS S3 Secret Key |
|
| AWS_SECRET_KEY | Optional, required for S3 storage | AWS S3 Secret Key |
|
||||||
| AWS_BUCKET_NAME | Optional, required for S3 storage | AWS S3 Bucket Name |
|
| AWS_BUCKET_NAME | Optional, required for S3 storage | AWS S3 Bucket Name |
|
||||||
| AWS_BUCKET_NAME | Optional, required for S3 storage | AWS S3 Bucket Name |
|
| AWS_BUCKET_NAME | Optional, required for S3 storage | AWS S3 Bucket Name |
|
||||||
| AWS_REGION | Optional, required for S3 storage | AWS Region |
|
| AWS_REGION | Optional, required for S3 storage | AWS Region |
|
||||||
| AWS_DISABLE_SSL | Optional, required for S3 storage | Disable SSL |
|
| AWS_DISABLE_SSL | Optional, required for S3 storage | Disable SSL |
|
||||||
| AWS_FORCE_PATH_STYLE | Optional, required for S3 storage | Force path style |
|
| AWS_FORCE_PATH_STYLE | Optional, required for S3 storage | Force path style |
|
||||||
| FILE_NAME | Optional if it was provided from the --file flag | Database file to restore (extensions: .sql, .sql.gz) |
|
| FILE_NAME | Optional if it was provided from the --file flag | Database file to restore (extensions: .sql, .sql.gz) |
|
||||||
| GPG_PASSPHRASE | Optional, required to encrypt and restore backup | GPG passphrase |
|
| GPG_PASSPHRASE | Optional, required to encrypt and restore backup | GPG passphrase |
|
||||||
| GPG_PUBLIC_KEY | Optional, required to encrypt backup | GPG public key, used to encrypt backup (/config/public_key.asc) |
|
| GPG_PUBLIC_KEY | Optional, required to encrypt backup | GPG public key, used to encrypt backup (/config/public_key.asc) |
|
||||||
| BACKUP_CRON_EXPRESSION | Optional if it was provided from the `--cron-expression` flag | Backup cron expression for docker in scheduled mode |
|
| BACKUP_CRON_EXPRESSION | Optional if it was provided from the `--cron-expression` flag | Backup cron expression for docker in scheduled mode |
|
||||||
| BACKUP_RETENTION_DAYS | Optional | Delete old backup created more than specified days ago |
|
| BACKUP_RETENTION_DAYS | Optional | Delete old backup created more than specified days ago |
|
||||||
| SSH_HOST | Optional, required for SSH storage | ssh remote hostname or ip |
|
| SSH_HOST | Optional, required for SSH storage | ssh remote hostname or ip |
|
||||||
| SSH_USER | Optional, required for SSH storage | ssh remote user |
|
| SSH_USER | Optional, required for SSH storage | ssh remote user |
|
||||||
| SSH_PASSWORD | Optional, required for SSH storage | ssh remote user's password |
|
| SSH_PASSWORD | Optional, required for SSH storage | ssh remote user's password |
|
||||||
| SSH_IDENTIFY_FILE | Optional, required for SSH storage | ssh remote user's private key |
|
| SSH_IDENTIFY_FILE | Optional, required for SSH storage | ssh remote user's private key |
|
||||||
| SSH_PORT | Optional, required for SSH storage | ssh remote server port |
|
| SSH_PORT | Optional, required for SSH storage | ssh remote server port |
|
||||||
| REMOTE_PATH | Optional, required for SSH or FTP storage | remote path (/home/toto/backup) |
|
| REMOTE_PATH | Optional, required for SSH or FTP storage | remote path (/home/toto/backup) |
|
||||||
| FTP_HOST | Optional, required for FTP storage | FTP host name |
|
| FTP_HOST | Optional, required for FTP storage | FTP host name |
|
||||||
| FTP_PORT | Optional, required for FTP storage | FTP server port number |
|
| FTP_PORT | Optional, required for FTP storage | FTP server port number |
|
||||||
| FTP_USER | Optional, required for FTP storage | FTP user |
|
| FTP_USER | Optional, required for FTP storage | FTP user |
|
||||||
| FTP_PASSWORD | Optional, required for FTP storage | FTP user password |
|
| FTP_PASSWORD | Optional, required for FTP storage | FTP user password |
|
||||||
| TARGET_DB_HOST | Optional, required for database migration | Target database host |
|
| TARGET_DB_HOST | Optional, required for database migration | Target database host |
|
||||||
| TARGET_DB_PORT | Optional, required for database migration | Target database port |
|
| TARGET_DB_PORT | Optional, required for database migration | Target database port |
|
||||||
| TARGET_DB_NAME | Optional, required for database migration | Target database name |
|
| TARGET_DB_NAME | Optional, required for database migration | Target database name |
|
||||||
| TARGET_DB_USERNAME | Optional, required for database migration | Target database username |
|
| TARGET_DB_USERNAME | Optional, required for database migration | Target database username |
|
||||||
| TARGET_DB_PASSWORD | Optional, required for database migration | Target database password |
|
| TARGET_DB_PASSWORD | Optional, required for database migration | Target database password |
|
||||||
| TG_TOKEN | Optional, required for Telegram notification | Telegram token (`BOT-ID:BOT-TOKEN`) |
|
| TG_TOKEN | Optional, required for Telegram notification | Telegram token (`BOT-ID:BOT-TOKEN`) |
|
||||||
| TG_CHAT_ID | Optional, required for Telegram notification | Telegram Chat ID |
|
| TG_CHAT_ID | Optional, required for Telegram notification | Telegram Chat ID |
|
||||||
| TZ | Optional | Time Zone |
|
| TZ | Optional | Time Zone |
|
||||||
|
| AZURE_STORAGE_CONTAINER_NAME | Optional, required for Azure Blob Storage storage | Azure storage container name |
|
||||||
|
| AZURE_STORAGE_ACCOUNT_NAME | Optional, required for Azure Blob Storage storage | Azure storage account name |
|
||||||
|
| AZURE_STORAGE_ACCOUNT_KEY | Optional, required for Azure Blob Storage storage | Azure storage account key |
|
||||||
---
|
---
|
||||||
## Run in Scheduled mode
|
## Run in Scheduled mode
|
||||||
|
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func azureBackup(db *dbConfig, config *BackupConfig) {
|
func azureBackup(db *dbConfig, config *BackupConfig) {
|
||||||
utils.Info("Backup database to the remote FTP server")
|
utils.Info("Backup database to Azure Blob Storage")
|
||||||
startTime = time.Now().Format(utils.TimeFormat())
|
startTime = time.Now().Format(utils.TimeFormat())
|
||||||
|
|
||||||
// Backup database
|
// Backup database
|
||||||
@@ -83,12 +83,14 @@ func azureBackup(db *dbConfig, config *BackupConfig) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
utils.Info("Backup name is %s", finalFileName)
|
||||||
|
utils.Info("Backup size: %s", utils.ConvertBytes(uint64(backupSize)))
|
||||||
utils.Info("Uploading backup archive to Azure Blob storage ... done ")
|
utils.Info("Uploading backup archive to Azure Blob storage ... done ")
|
||||||
|
|
||||||
// Send notification
|
// Send notification
|
||||||
utils.NotifySuccess(&utils.NotificationData{
|
utils.NotifySuccess(&utils.NotificationData{
|
||||||
File: finalFileName,
|
File: finalFileName,
|
||||||
BackupSize: backupSize,
|
BackupSize: utils.ConvertBytes(uint64(backupSize)),
|
||||||
Database: db.dbName,
|
Database: db.dbName,
|
||||||
Storage: config.storage,
|
Storage: config.storage,
|
||||||
BackupLocation: filepath.Join(config.remotePath, finalFileName),
|
BackupLocation: filepath.Join(config.remotePath, finalFileName),
|
||||||
|
|||||||
@@ -268,7 +268,6 @@ func localBackup(db *dbConfig, config *BackupConfig) {
|
|||||||
utils.Error("Error: %s", err)
|
utils.Error("Error: %s", err)
|
||||||
}
|
}
|
||||||
backupSize = fileInfo.Size()
|
backupSize = fileInfo.Size()
|
||||||
utils.Info("Backup name is %s", finalFileName)
|
|
||||||
localStorage := local.NewStorage(local.Config{
|
localStorage := local.NewStorage(local.Config{
|
||||||
LocalPath: tmpPath,
|
LocalPath: tmpPath,
|
||||||
RemotePath: storagePath,
|
RemotePath: storagePath,
|
||||||
@@ -277,11 +276,13 @@ func localBackup(db *dbConfig, config *BackupConfig) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
utils.Fatal("Error copying backup file: %s", err)
|
utils.Fatal("Error copying backup file: %s", err)
|
||||||
}
|
}
|
||||||
|
utils.Info("Backup name is %s", finalFileName)
|
||||||
|
utils.Info("Backup size: %s", utils.ConvertBytes(uint64(backupSize)))
|
||||||
utils.Info("Backup saved in %s", filepath.Join(storagePath, finalFileName))
|
utils.Info("Backup saved in %s", filepath.Join(storagePath, finalFileName))
|
||||||
// Send notification
|
// Send notification
|
||||||
utils.NotifySuccess(&utils.NotificationData{
|
utils.NotifySuccess(&utils.NotificationData{
|
||||||
File: finalFileName,
|
File: finalFileName,
|
||||||
BackupSize: backupSize,
|
BackupSize: utils.ConvertBytes(uint64(backupSize)),
|
||||||
Database: db.dbName,
|
Database: db.dbName,
|
||||||
Storage: config.storage,
|
Storage: config.storage,
|
||||||
BackupLocation: filepath.Join(storagePath, finalFileName),
|
BackupLocation: filepath.Join(storagePath, finalFileName),
|
||||||
|
|||||||
@@ -46,7 +46,6 @@ func sshBackup(db *dbConfig, config *BackupConfig) {
|
|||||||
finalFileName = fmt.Sprintf("%s.%s", config.backupFileName, "gpg")
|
finalFileName = fmt.Sprintf("%s.%s", config.backupFileName, "gpg")
|
||||||
}
|
}
|
||||||
utils.Info("Uploading backup archive to remote storage ... ")
|
utils.Info("Uploading backup archive to remote storage ... ")
|
||||||
utils.Info("Backup name is %s", finalFileName)
|
|
||||||
sshConfig, err := loadSSHConfig()
|
sshConfig, err := loadSSHConfig()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.Fatal("Error loading ssh config: %s", err)
|
utils.Fatal("Error loading ssh config: %s", err)
|
||||||
@@ -74,6 +73,8 @@ func sshBackup(db *dbConfig, config *BackupConfig) {
|
|||||||
utils.Error("Error: %s", err)
|
utils.Error("Error: %s", err)
|
||||||
}
|
}
|
||||||
backupSize = fileInfo.Size()
|
backupSize = fileInfo.Size()
|
||||||
|
utils.Info("Backup name is %s", finalFileName)
|
||||||
|
utils.Info("Backup size: %s", utils.ConvertBytes(uint64(backupSize)))
|
||||||
utils.Info("Backup saved in %s", filepath.Join(config.remotePath, finalFileName))
|
utils.Info("Backup saved in %s", filepath.Join(config.remotePath, finalFileName))
|
||||||
|
|
||||||
// Delete backup file from tmp folder
|
// Delete backup file from tmp folder
|
||||||
@@ -93,7 +94,7 @@ func sshBackup(db *dbConfig, config *BackupConfig) {
|
|||||||
// Send notification
|
// Send notification
|
||||||
utils.NotifySuccess(&utils.NotificationData{
|
utils.NotifySuccess(&utils.NotificationData{
|
||||||
File: finalFileName,
|
File: finalFileName,
|
||||||
BackupSize: backupSize,
|
BackupSize: utils.ConvertBytes(uint64(backupSize)),
|
||||||
Database: db.dbName,
|
Database: db.dbName,
|
||||||
Storage: config.storage,
|
Storage: config.storage,
|
||||||
BackupLocation: filepath.Join(config.remotePath, finalFileName),
|
BackupLocation: filepath.Join(config.remotePath, finalFileName),
|
||||||
@@ -199,13 +200,14 @@ func ftpBackup(db *dbConfig, config *BackupConfig) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
utils.Info("Backup name is %s", finalFileName)
|
||||||
|
utils.Info("Backup size: %s", utils.ConvertBytes(uint64(backupSize)))
|
||||||
utils.Info("Uploading backup archive to the remote FTP server ... done ")
|
utils.Info("Uploading backup archive to the remote FTP server ... done ")
|
||||||
|
|
||||||
// Send notification
|
// Send notification
|
||||||
utils.NotifySuccess(&utils.NotificationData{
|
utils.NotifySuccess(&utils.NotificationData{
|
||||||
File: finalFileName,
|
File: finalFileName,
|
||||||
BackupSize: backupSize,
|
BackupSize: utils.ConvertBytes(uint64(backupSize)),
|
||||||
Database: db.dbName,
|
Database: db.dbName,
|
||||||
Storage: config.storage,
|
Storage: config.storage,
|
||||||
BackupLocation: filepath.Join(config.remotePath, finalFileName),
|
BackupLocation: filepath.Join(config.remotePath, finalFileName),
|
||||||
|
|||||||
@@ -94,7 +94,7 @@ func s3Backup(db *dbConfig, config *BackupConfig) {
|
|||||||
// Send notification
|
// Send notification
|
||||||
utils.NotifySuccess(&utils.NotificationData{
|
utils.NotifySuccess(&utils.NotificationData{
|
||||||
File: finalFileName,
|
File: finalFileName,
|
||||||
BackupSize: backupSize,
|
BackupSize: utils.ConvertBytes(uint64(backupSize)),
|
||||||
Database: db.dbName,
|
Database: db.dbName,
|
||||||
Storage: config.storage,
|
Storage: config.storage,
|
||||||
BackupLocation: filepath.Join(config.remotePath, finalFileName),
|
BackupLocation: filepath.Join(config.remotePath, finalFileName),
|
||||||
|
|||||||
@@ -45,14 +45,12 @@ var (
|
|||||||
// dbHVars Required environment variables for database
|
// dbHVars Required environment variables for database
|
||||||
var dbHVars = []string{
|
var dbHVars = []string{
|
||||||
"DB_HOST",
|
"DB_HOST",
|
||||||
"DB_PORT",
|
|
||||||
"DB_PASSWORD",
|
"DB_PASSWORD",
|
||||||
"DB_USERNAME",
|
"DB_USERNAME",
|
||||||
"DB_NAME",
|
"DB_NAME",
|
||||||
}
|
}
|
||||||
var tdbRVars = []string{
|
var tdbRVars = []string{
|
||||||
"TARGET_DB_HOST",
|
"TARGET_DB_HOST",
|
||||||
"TARGET_DB_PORT",
|
|
||||||
"TARGET_DB_NAME",
|
"TARGET_DB_NAME",
|
||||||
"TARGET_DB_USERNAME",
|
"TARGET_DB_USERNAME",
|
||||||
"TARGET_DB_PASSWORD",
|
"TARGET_DB_PASSWORD",
|
||||||
|
|||||||
@@ -45,16 +45,16 @@
|
|||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<h2>🔴 Urgent: Database Backup Failure Notification</h2>
|
<h2>🔴 Urgent: Database Backup Failure Notification</h2>
|
||||||
<p>Dear Team,</p>
|
<p>Hi,</p>
|
||||||
<p>An error occurred during the database backup process. Please review the details below and take the necessary actions:</p>
|
<p>An error occurred during the database backup process. Please review the details below and take the necessary actions:</p>
|
||||||
|
|
||||||
<div class="details">
|
<div class="details">
|
||||||
<h3>Failure Details:</h3>
|
<h3>Failure Details:</h3>
|
||||||
<ul>
|
<ul>
|
||||||
<li><strong>Database Name:</strong> {{.DatabaseName}}</li>
|
<li><strong>Database Name:</strong> {{.DatabaseName}}</li>
|
||||||
<li><strong>Error Message:</strong> {{.Error}}</li>
|
|
||||||
<li><strong>Date:</strong> {{.EndTime}}</li>
|
<li><strong>Date:</strong> {{.EndTime}}</li>
|
||||||
<li><strong>Backup Reference:</strong> {{.BackupReference}}</li>
|
<li><strong>Backup Reference:</strong> {{.BackupReference}}</li>
|
||||||
|
<li><strong>Error Message:</strong> {{.Error}}</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -45,7 +45,7 @@
|
|||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<h2>✅ Database Backup Successful</h2>
|
<h2>✅ Database Backup Successful</h2>
|
||||||
<p>Dear Team,</p>
|
<p>Hi,</p>
|
||||||
<p>The backup process for the <strong>{{.Database}}</strong> database was successfully completed. Please find the details below:</p>
|
<p>The backup process for the <strong>{{.Database}}</strong> database was successfully completed. Please find the details below:</p>
|
||||||
|
|
||||||
<div class="details">
|
<div class="details">
|
||||||
@@ -56,7 +56,7 @@
|
|||||||
<li><strong>Backup End Time:</strong> {{.EndTime}}</li>
|
<li><strong>Backup End Time:</strong> {{.EndTime}}</li>
|
||||||
<li><strong>Backup Storage:</strong> {{.Storage}}</li>
|
<li><strong>Backup Storage:</strong> {{.Storage}}</li>
|
||||||
<li><strong>Backup Location:</strong> {{.BackupLocation}}</li>
|
<li><strong>Backup Location:</strong> {{.BackupLocation}}</li>
|
||||||
<li><strong>Backup Size:</strong> {{.BackupSize}} bytes</li>
|
<li><strong>Backup Size:</strong> {{.BackupSize}}</li>
|
||||||
<li><strong>Backup Reference:</strong> {{.BackupReference}}</li>
|
<li><strong>Backup Reference:</strong> {{.BackupReference}}</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
🔴 Urgent: Database Backup Failure Notification
|
🔴 Urgent: Database Backup Failure Notification
|
||||||
|
|
||||||
Dear Team,
|
Hi,
|
||||||
An error occurred during the database backup process.
|
An error occurred during the database backup process.
|
||||||
Please review the details below and take the necessary actions:
|
Please review the details below and take the necessary actions:
|
||||||
Failure Details:
|
Failure Details:
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
✅ Database Backup Successful
|
✅ Database Backup Successful
|
||||||
|
|
||||||
Dear Team,
|
Hi,
|
||||||
The backup process for the {{.Database}} database was successfully completed.
|
The backup process for the {{.Database}} database was successfully completed.
|
||||||
Please find the details below:
|
Please find the details below:
|
||||||
|
|
||||||
@@ -10,7 +10,7 @@ Backup Details:
|
|||||||
- Backup EndTime: {{.EndTime}}
|
- Backup EndTime: {{.EndTime}}
|
||||||
- Backup Storage: {{.Storage}}
|
- Backup Storage: {{.Storage}}
|
||||||
- Backup Location: {{.BackupLocation}}
|
- Backup Location: {{.BackupLocation}}
|
||||||
- Backup Size: {{.BackupSize}} bytes
|
- Backup Size: {{.BackupSize}}
|
||||||
- Backup Reference: {{.BackupReference}}
|
- Backup Reference: {{.BackupReference}}
|
||||||
|
|
||||||
You can access the backup at the specified location if needed.
|
You can access the backup at the specified location if needed.
|
||||||
@@ -37,7 +37,7 @@ type MailConfig struct {
|
|||||||
}
|
}
|
||||||
type NotificationData struct {
|
type NotificationData struct {
|
||||||
File string
|
File string
|
||||||
BackupSize int64
|
BackupSize string
|
||||||
Database string
|
Database string
|
||||||
StartTime string
|
StartTime string
|
||||||
EndTime string
|
EndTime string
|
||||||
|
|||||||
@@ -254,3 +254,19 @@ func CronNextTime(cronExpr string) time.Time {
|
|||||||
next := schedule.Next(now)
|
next := schedule.Next(now)
|
||||||
return next
|
return next
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ConvertBytes converts bytes to a human-readable string with the appropriate unit (bytes, MiB, or GiB).
|
||||||
|
func ConvertBytes(bytes uint64) string {
|
||||||
|
const (
|
||||||
|
MiB = 1024 * 1024
|
||||||
|
GiB = MiB * 1024
|
||||||
|
)
|
||||||
|
switch {
|
||||||
|
case bytes >= GiB:
|
||||||
|
return fmt.Sprintf("%.2f GiB", float64(bytes)/float64(GiB))
|
||||||
|
case bytes >= MiB:
|
||||||
|
return fmt.Sprintf("%.2f MiB", float64(bytes)/float64(MiB))
|
||||||
|
default:
|
||||||
|
return fmt.Sprintf("%d bytes", bytes)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user