150 lines
4.3 KiB
JavaScript
150 lines
4.3 KiB
JavaScript
/**
|
|
* S3 Backup Script for Weight Tracker
|
|
*
|
|
* This script creates automated backups of the Weight Tracker data
|
|
* and uploads them to an S3-compatible storage (like Minio)
|
|
*/
|
|
|
|
const fs = require('fs');
|
|
const path = require('path');
|
|
const { S3Client, PutObjectCommand, ListObjectsV2Command, DeleteObjectCommand } = require('@aws-sdk/client-s3');
|
|
const cron = require('node-cron');
|
|
|
|
// Configuration (can be overridden by environment variables)
|
|
const config = {
|
|
// S3 Configuration
|
|
s3: {
|
|
endpoint: process.env.S3_ENDPOINT || 'https://your-minio-server.example.com',
|
|
region: process.env.S3_REGION || 'us-east-1', // Default region, can be any value for Minio
|
|
bucket: process.env.S3_BUCKET || 'weight-tracker-backups',
|
|
accessKey: process.env.S3_ACCESS_KEY || 'your-access-key',
|
|
secretKey: process.env.S3_SECRET_KEY || 'your-secret-key',
|
|
useSSL: process.env.S3_USE_SSL !== 'false' // Default to true unless explicitly set to 'false'
|
|
},
|
|
|
|
// Backup Configuration
|
|
backup: {
|
|
dataPath: process.env.DATA_PATH || '/data/weight-tracker-data.json',
|
|
schedule: process.env.BACKUP_SCHEDULE || '0 0 * * *', // Default: daily at midnight
|
|
retention: parseInt(process.env.BACKUP_RETENTION || '7') // Default: keep 7 backups
|
|
}
|
|
};
|
|
|
|
// Initialize S3 client
|
|
const s3Client = new S3Client({
|
|
endpoint: config.s3.endpoint,
|
|
region: config.s3.region,
|
|
credentials: {
|
|
accessKeyId: config.s3.accessKey,
|
|
secretAccessKey: config.s3.secretKey
|
|
},
|
|
forcePathStyle: true, // Required for Minio
|
|
tls: config.s3.useSSL
|
|
});
|
|
|
|
/**
|
|
* Create a backup and upload to S3
|
|
*/
|
|
async function createBackup() {
|
|
try {
|
|
// Check if data file exists
|
|
if (!fs.existsSync(config.backup.dataPath)) {
|
|
console.error(`Data file not found: ${config.backup.dataPath}`);
|
|
return;
|
|
}
|
|
|
|
// Read data file
|
|
const data = fs.readFileSync(config.backup.dataPath, 'utf8');
|
|
|
|
// Generate backup filename with timestamp
|
|
const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
|
|
const backupFilename = `weight-tracker-backup-${timestamp}.json`;
|
|
|
|
// Upload to S3
|
|
const uploadParams = {
|
|
Bucket: config.s3.bucket,
|
|
Key: backupFilename,
|
|
Body: data,
|
|
ContentType: 'application/json'
|
|
};
|
|
|
|
const uploadCommand = new PutObjectCommand(uploadParams);
|
|
await s3Client.send(uploadCommand);
|
|
|
|
console.log(`Backup created successfully: ${backupFilename}`);
|
|
|
|
// Cleanup old backups
|
|
await cleanupOldBackups();
|
|
|
|
} catch (error) {
|
|
console.error('Error creating backup:', error);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Clean up old backups based on retention policy
|
|
*/
|
|
async function cleanupOldBackups() {
|
|
try {
|
|
// List all backups
|
|
const listParams = {
|
|
Bucket: config.s3.bucket,
|
|
Prefix: 'weight-tracker-backup-'
|
|
};
|
|
|
|
const listCommand = new ListObjectsV2Command(listParams);
|
|
const response = await s3Client.send(listCommand);
|
|
|
|
if (!response.Contents || response.Contents.length <= config.backup.retention) {
|
|
return; // No cleanup needed
|
|
}
|
|
|
|
// Sort by date (oldest first)
|
|
const backups = response.Contents.sort((a, b) =>
|
|
new Date(a.LastModified) - new Date(b.LastModified)
|
|
);
|
|
|
|
// Delete oldest backups that exceed retention count
|
|
const backupsToDelete = backups.slice(0, backups.length - config.backup.retention);
|
|
|
|
for (const backup of backupsToDelete) {
|
|
const deleteParams = {
|
|
Bucket: config.s3.bucket,
|
|
Key: backup.Key
|
|
};
|
|
|
|
const deleteCommand = new DeleteObjectCommand(deleteParams);
|
|
await s3Client.send(deleteCommand);
|
|
|
|
console.log(`Deleted old backup: ${backup.Key}`);
|
|
}
|
|
|
|
} catch (error) {
|
|
console.error('Error cleaning up old backups:', error);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Initialize the backup system
|
|
*/
|
|
function init() {
|
|
console.log('Starting Weight Tracker S3 backup system');
|
|
console.log(`Backup schedule: ${config.backup.schedule}`);
|
|
console.log(`Backup retention: ${config.backup.retention} backups`);
|
|
console.log(`S3 endpoint: ${config.s3.endpoint}`);
|
|
console.log(`S3 bucket: ${config.s3.bucket}`);
|
|
|
|
// Schedule regular backups
|
|
cron.schedule(config.backup.schedule, () => {
|
|
console.log('Running scheduled backup...');
|
|
createBackup();
|
|
});
|
|
|
|
// Create initial backup
|
|
console.log('Creating initial backup...');
|
|
createBackup();
|
|
}
|
|
|
|
// Start the backup system
|
|
init();
|