From eb28667d90d95781d36ac433ed5fe5a4c65079c3 Mon Sep 17 00:00:00 2001 From: Renan Bernordi Date: Sat, 15 Nov 2025 23:32:26 -0300 Subject: [PATCH] add mysql, mariadb, postgresql, sqlite volumes support --- Dockerfile | 8 +- app/client/components/create-volume-form.tsx | 302 +++++++++++++++++- app/client/components/volume-icon.tsx | 26 +- .../modules/volumes/routes/volume-details.tsx | 11 +- app/client/modules/volumes/routes/volumes.tsx | 5 + app/schemas/volumes.ts | 49 ++- app/server/modules/backends/backend.ts | 19 ++ .../backends/mariadb/mariadb-backend.ts | 57 ++++ .../modules/backends/mysql/mysql-backend.ts | 57 ++++ .../backends/postgres/postgres-backend.ts | 57 ++++ .../modules/backends/sqlite/sqlite-backend.ts | 57 ++++ app/server/modules/backups/backups.service.ts | 39 ++- app/server/modules/volumes/helpers.ts | 35 ++ app/server/utils/database-dump.ts | 282 ++++++++++++++++ app/server/utils/spawn.ts | 43 ++- 15 files changed, 1022 insertions(+), 25 deletions(-) create mode 100644 app/server/modules/backends/mariadb/mariadb-backend.ts create mode 100644 app/server/modules/backends/mysql/mysql-backend.ts create mode 100644 app/server/modules/backends/postgres/postgres-backend.ts create mode 100644 app/server/modules/backends/sqlite/sqlite-backend.ts create mode 100644 app/server/utils/database-dump.ts diff --git a/Dockerfile b/Dockerfile index 2803f68..404599f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,8 +2,12 @@ ARG BUN_VERSION="1.3.1" FROM oven/bun:${BUN_VERSION}-alpine AS base -RUN apk add --no-cache davfs2=1.6.1-r2 - +RUN apk add --no-cache \ + davfs2=1.6.1-r2 \ + mariadb-client \ + mysql-client \ + postgresql-client \ + sqlite # ------------------------------ # DEPENDENCIES diff --git a/app/client/components/create-volume-form.tsx b/app/client/components/create-volume-form.tsx index 4f2c588..4a56079 100644 --- a/app/client/components/create-volume-form.tsx +++ b/app/client/components/create-volume-form.tsx @@ -35,6 +35,10 @@ const defaultValuesForType = { nfs: { backend: "nfs" as const, port: 2049, version: "4.1" as const }, smb: { backend: "smb" as const, port: 445, vers: "3.0" as const }, webdav: { backend: "webdav" as const, port: 80, ssl: false }, + mariadb: { backend: "mariadb" as const, port: 3306 }, + mysql: { backend: "mysql" as const, port: 3306 }, + postgres: { backend: "postgres" as const, port: 5432, dumpFormat: "custom" as const }, + sqlite: { backend: "sqlite" as const, path: "/" }, }; export const CreateVolumeForm = ({ onSubmit, mode = "create", initialValues, formId, loading, className }: Props) => { @@ -81,7 +85,14 @@ export const CreateVolumeForm = ({ onSubmit, mode = "create", initialValues, for const handleTestConnection = async () => { const formValues = getValues(); - if (formValues.backend === "nfs" || formValues.backend === "smb" || formValues.backend === "webdav") { + if ( + formValues.backend === "nfs" || + formValues.backend === "smb" || + formValues.backend === "webdav" || + formValues.backend === "mariadb" || + formValues.backend === "mysql" || + formValues.backend === "postgres" + ) { testBackendConnection.mutate({ body: { config: formValues }, }); @@ -130,6 +141,10 @@ export const CreateVolumeForm = ({ onSubmit, mode = "create", initialValues, for NFS SMB WebDAV + MariaDB + MySQL + PostgreSQL + SQLite Choose the storage backend for this volume. @@ -536,7 +551,290 @@ export const CreateVolumeForm = ({ onSubmit, mode = "create", initialValues, for )} - {watchedBackend !== "directory" && ( + {watchedBackend === "mariadb" && ( + <> + ( + + Host + + + + MariaDB server hostname or IP address. + + + )} + /> + ( + + Port + + + + MariaDB server port (default: 3306). + + + )} + /> + ( + + Username + + + + Database user with backup privileges. + + + )} + /> + ( + + Password + + + + Password for database authentication. + + + )} + /> + ( + + Database + + + + Name of the database to backup. + + + )} + /> + + )} + + {watchedBackend === "mysql" && ( + <> + ( + + Host + + + + MySQL server hostname or IP address. + + + )} + /> + ( + + Port + + + + MySQL server port (default: 3306). + + + )} + /> + ( + + Username + + + + Database user with backup privileges. + + + )} + /> + ( + + Password + + + + Password for database authentication. + + + )} + /> + ( + + Database + + + + Name of the database to backup. + + + )} + /> + + )} + + {watchedBackend === "postgres" && ( + <> + ( + + Host + + + + PostgreSQL server hostname or IP address. + + + )} + /> + ( + + Port + + + + PostgreSQL server port (default: 5432). + + + )} + /> + ( + + Username + + + + Database user with backup privileges. + + + )} + /> + ( + + Password + + + + Password for database authentication. + + + )} + /> + ( + + Database + + + + Name of the database to backup. + + + )} + /> + ( + + Dump Format + + Format for database dumps (custom recommended). + + + )} + /> + + )} + + {watchedBackend === "sqlite" && ( + { + return ( + + Database File Path + + {field.value ? ( +
+
+
Selected database:
+
{field.value}
+
+ +
+ ) : ( + field.onChange(path)} selectedPath={field.value} /> + )} +
+ Path to the SQLite database file (.db, .sqlite, .sqlite3). + +
+ ); + }} + /> + )} + + {watchedBackend !== "directory" && watchedBackend !== "sqlite" && (