mirror of
https://github.com/dani-garcia/vaultwarden.git
synced 2026-05-08 21:12:04 +02:00
Add option to specify backup path
This commit is contained in:
parent
8801b47d80
commit
7c86e28619
3 changed files with 28 additions and 8 deletions
|
|
@ -790,7 +790,7 @@ async fn delete_config(_token: AdminToken) -> EmptyResult {
|
|||
#[post("/config/backup_db", format = "application/json")]
|
||||
fn backup_db(_token: AdminToken) -> ApiResult<String> {
|
||||
if *CAN_BACKUP {
|
||||
match backup_sqlite() {
|
||||
match backup_sqlite(None) {
|
||||
Ok(f) => Ok(format!("Backup to '{f}' was successful")),
|
||||
Err(e) => err!(format!("Backup was unsuccessful {e}")),
|
||||
}
|
||||
|
|
|
|||
|
|
@ -384,8 +384,13 @@ pub mod models;
|
|||
|
||||
/// Creates a back-up of the sqlite database
|
||||
/// MySQL/MariaDB and PostgreSQL are not supported.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `backup_dir` - Optional custom directory path where the backup file will be created.
|
||||
/// If `None`, the backup will be created in the same directory as the database file.
|
||||
#[cfg(sqlite)]
|
||||
pub fn backup_sqlite() -> Result<String, Error> {
|
||||
pub fn backup_sqlite(backup_dir: Option<String>) -> Result<String, Error> {
|
||||
use diesel::Connection;
|
||||
use std::{fs::File, io::Write};
|
||||
|
||||
|
|
@ -395,8 +400,21 @@ pub fn backup_sqlite() -> Result<String, Error> {
|
|||
// This way we can set a readonly flag on the opening mode without issues.
|
||||
let mut conn = diesel::sqlite::SqliteConnection::establish(&format!("sqlite://{db_url}?mode=ro"))?;
|
||||
|
||||
let db_path = std::path::Path::new(&db_url).parent().unwrap();
|
||||
let backup_file = db_path
|
||||
let backup_path = match backup_dir {
|
||||
Some(dir) => {
|
||||
let path = std::path::Path::new(dir.as_str()).to_path_buf();
|
||||
|
||||
// Ensure the backup directory exists
|
||||
if let Err(e) = std::fs::create_dir_all(&path) {
|
||||
err_silent!(format!("Unable to create backup directory: {e:?}"))
|
||||
}
|
||||
|
||||
path
|
||||
},
|
||||
None => std::path::Path::new(&db_url).parent().unwrap().to_path_buf(),
|
||||
};
|
||||
|
||||
let backup_file = backup_path
|
||||
.join(format!("db_{}.sqlite3", chrono::Utc::now().format("%Y%m%d_%H%M%S")))
|
||||
.to_string_lossy()
|
||||
.into_owned();
|
||||
|
|
@ -417,7 +435,7 @@ pub fn backup_sqlite() -> Result<String, Error> {
|
|||
}
|
||||
|
||||
#[cfg(not(sqlite))]
|
||||
pub fn backup_sqlite() -> Result<String, Error> {
|
||||
pub fn backup_sqlite(_backup_dir: Option<&str>) -> Result<String, Error> {
|
||||
err_silent!("The database type is not SQLite. Backups only works for SQLite databases")
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -105,7 +105,7 @@ FLAGS:
|
|||
|
||||
COMMAND:
|
||||
hash [--preset {bitwarden|owasp}] Generate an Argon2id PHC ADMIN_TOKEN
|
||||
backup Create a backup of the SQLite database
|
||||
backup [--path] Create a backup of the SQLite database
|
||||
You can also send the USR1 signal to trigger a backup
|
||||
|
||||
PRESETS: m= t= p=
|
||||
|
|
@ -187,7 +187,9 @@ fn parse_args() {
|
|||
exit(1);
|
||||
}
|
||||
} else if command == "backup" {
|
||||
match db::backup_sqlite() {
|
||||
let backup_path: Option<String> = pargs.opt_value_from_str(["-p", "--path"]).unwrap_or_default();
|
||||
|
||||
match db::backup_sqlite(backup_path) {
|
||||
Ok(f) => {
|
||||
println!("Backup to '{f}' was successful");
|
||||
exit(0);
|
||||
|
|
@ -606,7 +608,7 @@ async fn launch_rocket(pool: db::DbPool, extra_debug: bool) -> Result<(), Error>
|
|||
// If we need more signals to act upon, we might want to use select! here.
|
||||
// With only one item to listen for this is enough.
|
||||
let _ = signal_user1.recv().await;
|
||||
match db::backup_sqlite() {
|
||||
match db::backup_sqlite(None) {
|
||||
Ok(f) => info!("Backup to '{f}' was successful"),
|
||||
Err(e) => error!("Backup failed. {e:?}"),
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue