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}