diff --git a/.woodpecker/build.yml b/.woodpecker/build.yml new file mode 100644 index 0000000..94f5e41 --- /dev/null +++ b/.woodpecker/build.yml @@ -0,0 +1,15 @@ +when: + - event: push + branch: main + +steps: + - name: "PKGBUILD" + image: git.hydrar.de/jmarya/pacco-build:latest + commands: + - pacman -Syu --noconfirm + - buildpkg navos x86_64 pac.hydrar.de "$TOKEN" "$KEY" + environment: + TOKEN: + from_secret: pacco_token + KEY: + from_secret: sign_key diff --git a/PKGBUILD b/PKGBUILD new file mode 100644 index 0000000..b762766 --- /dev/null +++ b/PKGBUILD @@ -0,0 +1,41 @@ +# Maintainer: JMARyA +pkgname=bk +pkgver=2025.01.07_2e7d4aa +pkgrel=1 +pkgdesc="backup utility" +arch=('x86_64') +url="https://git.hydrar.de/jmarya/bk" +license=("MIT") +depends=("borg" "rsync") +makedepends=("rustup" "git") +source=("${pkgname}::git+https://git.hydrar.de/jmarya/bk.git") +sha256sums=("SKIP") + +pkgver() { + cd "$srcdir/$pkgname" + echo "$(date +%Y.%m.%d)_$(git rev-parse --short HEAD)" +} + +prepare() { + cd "$srcdir/$pkgname" + rustup default nightly + cargo fetch +} + +build() { + cd "$srcdir/$pkgname" + cargo build --release +} + +check() { + cd "$srcdir/$pkgname" + cargo test --release +} + +package() { + cd "$srcdir/$pkgname" + install -Dm755 "target/release/bk" "$pkgdir/usr/bin/bk" + install -Dm644 "src/systemd/bk.service" "/usr/lib/systemd/system/bk.service" + install -Dm644 "src/systemd/bk.timer" "/usr/lib/systemd/system/bk.timer" + install -Dm644 "config.toml" "/etc/bk.toml" +} diff --git a/config.toml b/config.toml index 44e9926..2b28851 100644 --- a/config.toml +++ b/config.toml @@ -1,91 +1,91 @@ # Run a script before backup -start_script = "before.sh" +# start_script = "before.sh" # Run a script after backup -end_script = "after.sh" +# end_script = "after.sh" # Rsync Operation -[[rsync]] +# [[rsync]] # Directories SHOULD have trailing `/` -src = "/home/me/" -dest = "/backup/home/me/" +# src = "/home/me/" +# dest = "/backup/home/me/" # Excludes -exclude = [".cache", ".local"] +# exclude = [".cache", ".local"] # Delete entries not present in `src` from `destination` -delete = true +# delete = true # Ensure this directory exists and it not empty before running rsync -ensure_exists = "/home" +# ensure_exists = "/home" # Make a CephFS snapshot before rsync -cephfs_snap = true +# cephfs_snap = true # Borg Operation -[[borg]] +# [[borg]] # Repo to backup to -repo = "/backup/repo.borg" +# repo = "/backup/repo.borg" # Passphrase -passphrase = "pass" +# passphrase = "pass" # Source Directories -src = [ "/home/me/.config" ] +# src = [ "/home/me/.config" ] # Excludes -exclude = [ - "some/dir" -] +# exclude = [ +# "some/dir" +# ] # Exclude if present (example: Do not backup directories with `.nobackup`) -exclude_if_present = [".nobackup"] +# exclude_if_present = [".nobackup"] # Stay in one filesystem -one_file_system = true +# one_file_system = true # Backup change time -ctime = false +# ctime = false # Do not backup ACLs -no_acls = true +# no_acls = true # Do not backup extended attributes -no_xattrs = true +# no_xattrs = true # Comment to add to the backup -comment = "Backup of /home/me/" +# comment = "Backup of /home/me/" # Compression -compression = "zstd,10" +# compression = "zstd,10" # Ensure directory exists before backup -ensure_exists = "/home/me" +# ensure_exists = "/home/me" # Make a CephFS snapshot before backup -cephfs_snap = true +# cephfs_snap = true # Borg Check Operation -[[borg_check]] +# [[borg_check]] # Repository to check -repo = "/backup/repo.borg" +# repo = "/backup/repo.borg" # Full Data Verify -verify_data = true +# verify_data = true # Repair Attempt -repair = false +# repair = false # Borg Prune Operation -[[borg_prune]] +# [[borg_prune]] # Repository to prune -repo = "/backup/repo.borg" +# repo = "/backup/repo.borg" # Passphrase -passphrase = "pass" +# passphrase = "pass" -keep_within = "30d" -keep_last = 20 +# keep_within = "30d" +# keep_last = 20 # keep_secondly = 3 # keep_minutely = 3 # keep_hourly = 10 diff --git a/src/config.rs b/src/config.rs index a01d5a1..d443cdd 100644 --- a/src/config.rs +++ b/src/config.rs @@ -1,64 +1,138 @@ use serde::Deserialize; +/// Configuration structure for the backup system. #[derive(Debug, Clone, Deserialize)] pub struct Config { - /// Run a script before backup + /// Optional script to run before starting the backup process. pub start_script: Option, - // Run a script after backup + /// Optional script to run after completing the backup process. pub end_script: Option, + /// Configuration for rsync jobs. pub rsync: Option>, + + /// Configuration for Borg backup jobs. pub borg: Option>, + + /// Configuration for Borg check jobs to verify repository integrity. pub borg_check: Option>, + + /// Configuration for Borg prune jobs to manage repository snapshots. pub borg_prune: Option>, } +/// Configuration for an individual rsync job. #[derive(Debug, Clone, Deserialize)] pub struct RsyncConfig { + /// Source path for rsync. pub src: String, + + /// Destination path for rsync. pub dest: String, + + /// List of patterns to exclude from synchronization. pub exclude: Option>, + + /// Whether to delete files at the destination that are not in the source. pub delete: Option, + + /// Ensure a specific directory exists before running the rsync job. pub ensure_exists: Option, + + /// Create CephFS snapshot before the rsync job. pub cephfs_snap: Option, } +/// Configuration for an individual Borg backup job. #[derive(Debug, Clone, Deserialize)] pub struct BorgConfig { + /// Borg repository path. pub repo: String, + + /// Optional passphrase for the repository. pub passphrase: Option, + + /// List of source paths to include in the backup. pub src: Vec, + + /// List of patterns to exclude from the backup. pub exclude: Option>, + + /// List of marker files; directories containing these will be excluded. pub exclude_if_present: Option>, + + /// Whether to limit the backup to a single filesystem. pub one_file_system: Option, + + /// Whether to backup ctime pub ctime: Option, + + /// Disable backup of ACLs (Access Control Lists). pub no_acls: Option, + + /// Disable backup of extended attributes. pub no_xattrs: Option, + + /// Optional comment to associate with the backup. pub comment: Option, + + /// Compression mode to use for the backup. pub compression: Option, + + /// Ensure a specific directory exists before running the backup. pub ensure_exists: Option, - pub cephfs_snap: Option, + + /// Create CephFS snapshots before the backup. + pub cephfs_snap: Option } +/// Configuration for a Borg repository integrity check job. #[derive(Debug, Clone, Deserialize)] pub struct BorgCheckConfig { + /// Borg repository path. pub repo: String, + + /// Whether to verify the repository's data integrity. pub verify_data: Option, + + /// Whether to attempt repairs on detected issues. pub repair: Option, } +/// Configuration for a Borg repository pruning job. #[derive(Debug, Clone, Deserialize)] pub struct BorgPruneConfig { + /// Borg repository path. pub repo: String, + + /// Passphrase for accessing the repository. pub passphrase: String, + + /// Retain all archives within this time period. pub keep_within: String, + + /// Retain the last `n` archives. pub keep_last: Option, + + /// Retain the last `n` secondly archives. pub keep_secondly: Option, + + /// Retain the last `n` minutely archives. pub keep_minutely: Option, + + /// Retain the last `n` hourly archives. pub keep_hourly: Option, + + /// Retain the last `n` daily archives. pub keep_daily: Option, + + /// Retain the last `n` weekly archives. pub keep_weekly: Option, + + /// Retain the last `n` monthly archives. pub keep_monthly: Option, + + /// Retain the last `n` yearly archives. pub keep_yearly: Option, } diff --git a/src/systemd/bk.service b/src/systemd/bk.service new file mode 100644 index 0000000..ff398ed --- /dev/null +++ b/src/systemd/bk.service @@ -0,0 +1,9 @@ +[Unit] +Description=Backup + +[Service] +Type=simple +ExecStart=/usr/bin/bk /etc/bk.toml +User=root +StandardOutput=journal +StandardError=journal diff --git a/src/systemd/bk.timer b/src/systemd/bk.timer new file mode 100644 index 0000000..49ba998 --- /dev/null +++ b/src/systemd/bk.timer @@ -0,0 +1,9 @@ +[Unit] +Description=Scheduled backup + +[Timer] +OnCalendar=daily +Persistent=true + +[Install] +WantedBy=timers.target