server_forge/
backup.rs

1//! # Backup Module
2//!
3//! This module provides functionality for setting up and configuring an automated backup system
4//! for a Linux server. It uses `restic` as the backup tool, which provides efficient, encrypted,
5//! and incremental backups.
6//!
7//! The module includes functions for installing backup tools, configuring backup schedules,
8//! and setting up backup locations based on the server's role.
9
10use crate::config::Config;
11use crate::distro::{get_package_manager, PackageManager};
12use crate::rollback::RollbackManager;
13use crate::utils::run_command;
14use log::info;
15use std::error::Error;
16
17/// Sets up the backup system based on the provided configuration.
18///
19/// This function orchestrates the entire backup setup process, including:
20/// - Installing necessary backup tools
21/// - Configuring the backup schedule
22/// - Setting up backup locations
23///
24/// It creates a snapshot before starting the setup process for potential rollback.
25///
26/// # Arguments
27///
28/// * `config` - A reference to the `Config` struct containing backup configuration
29/// * `rollback` - A reference to the `RollbackManager` for creating snapshots
30///
31/// # Returns
32///
33/// Returns `Ok(())` if the backup system is set up successfully, or an error if setup fails.
34pub fn setup_backup_system(
35    config: &Config,
36    rollback: &RollbackManager,
37) -> Result<(), Box<dyn Error>> {
38    info!("Setting up backup system...");
39
40    let snapshot = rollback.create_snapshot()?;
41
42    install_backup_tools()?;
43    configure_backup_schedule(config)?;
44    setup_backup_locations(config)?;
45
46    rollback.commit_snapshot(snapshot)?;
47
48    info!("Backup system setup completed");
49    Ok(())
50}
51
52/// Installs the necessary backup tools (restic) on the system.
53///
54/// This function uses the appropriate package manager for the current Linux distribution
55/// to install restic.
56///
57/// # Returns
58///
59/// Returns `Ok(())` if restic is installed successfully, or an error if installation fails.
60pub fn install_backup_tools() -> Result<(), Box<dyn Error>> {
61    let package_manager = get_package_manager()?;
62    match package_manager {
63        PackageManager::Apt => run_command("apt", &["install", "-y", "restic"])?,
64        PackageManager::Yum => run_command("yum", &["install", "-y", "restic"])?,
65        PackageManager::Dnf => run_command("dnf", &["install", "-y", "restic"])?,
66    }
67    Ok(())
68}
69
70/// Configures the backup schedule based on the provided configuration.
71///
72/// This function creates a cron job for running backups at the specified frequency
73/// (hourly, daily, or weekly).
74///
75/// # Arguments
76///
77/// * `config` - A reference to the `Config` struct containing the backup frequency
78///
79/// # Returns
80///
81/// Returns `Ok(())` if the backup schedule is configured successfully, or an error if configuration fails.
82pub fn configure_backup_schedule(config: &Config) -> Result<(), Box<dyn Error>> {
83    let cron_job = match config.backup_frequency.as_str() {
84        "hourly" => {
85            "0 * * * * root /usr/bin/restic backup /path/to/backup >> /var/log/restic.log 2>&1\n"
86        }
87        "daily" => {
88            "0 2 * * * root /usr/bin/restic backup /path/to/backup >> /var/log/restic.log 2>&1\n"
89        }
90        "weekly" => {
91            "0 2 * * 0 root /usr/bin/restic backup /path/to/backup >> /var/log/restic.log 2>&1\n"
92        }
93        _ => return Err("Invalid backup frequency".into()),
94    };
95
96    std::fs::write("/etc/cron.d/restic-backup", cron_job)?;
97    Ok(())
98}
99
100/// Sets up backup locations based on the server's role.
101///
102/// This function determines which directories to back up based on the server's role
103/// (web, database, or application server). It then initializes a restic repository
104/// and creates a backup script that includes these locations.
105///
106/// # Arguments
107///
108/// * `config` - A reference to the `Config` struct containing the server role
109///
110/// # Returns
111///
112/// Returns `Ok(())` if backup locations are set up successfully, or an error if setup fails.
113pub fn setup_backup_locations(config: &Config) -> Result<(), Box<dyn Error>> {
114    // Define backup locations based on server role
115    let backup_dirs = match config.server_role.as_str() {
116        "web" => vec!["/var/www", "/etc/nginx", "/etc/apache2"],
117        "database" => vec!["/var/lib/mysql", "/var/lib/postgresql"],
118        "application" => vec!["/opt/myapp", "/etc/myapp"],
119        _ => vec![],
120    };
121
122    // Create restic repository
123    run_command("restic", &["init", "--repo", "/path/to/backup/repository"])?;
124
125    // Create backup script
126    let mut backup_script = String::from("#!/bin/bash\n\n");
127    backup_script.push_str("export RESTIC_PASSWORD='your_restic_password'\n\n");
128    backup_script.push_str("restic backup");
129    for dir in backup_dirs {
130        backup_script.push_str(&format!(" {}", dir));
131    }
132    backup_script.push_str(" --tag serverforge\n");
133
134    std::fs::write("/usr/local/bin/run-backup.sh", backup_script)?;
135    run_command("chmod", &["+x", "/usr/local/bin/run-backup.sh"])?;
136
137    Ok(())
138}