diff --git a/packages/server/src/services/application.ts b/packages/server/src/services/application.ts index ac1fbb449..c8ebb3be7 100644 --- a/packages/server/src/services/application.ts +++ b/packages/server/src/services/application.ts @@ -95,26 +95,22 @@ export const findApplicationById = async (applicationId: string) => { const application = await db.query.applications.findFirst({ where: eq(applications.applicationId, applicationId), with: { - environment: { - with: { - project: true, - }, - }, + environment: { with: { project: true } }, domains: true, deployments: true, mounts: true, redirects: true, security: true, ports: true, - registry: true, gitlab: true, github: true, bitbucket: true, gitea: true, server: true, previewDeployments: true, - buildRegistry: true, - rollbackRegistry: true, + registry: { columns: { password: false } }, + buildRegistry: { columns: { password: false } }, + rollbackRegistry: { columns: { password: false } }, }, }); if (!application) { diff --git a/packages/server/src/services/backup.ts b/packages/server/src/services/backup.ts index e3951a89e..0e05d4080 100644 --- a/packages/server/src/services/backup.ts +++ b/packages/server/src/services/backup.ts @@ -34,7 +34,12 @@ export const findBackupById = async (backupId: string) => { mariadb: true, mongo: true, libsql: true, - destination: true, + destination: { + columns: { + accessKey: false, + secretAccessKey: false, + }, + }, compose: true, }, }); @@ -83,7 +88,12 @@ export const findBackupsByDbId = async ( mariadb: true, mongo: true, libsql: true, - destination: true, + destination: { + columns: { + accessKey: false, + secretAccessKey: false, + }, + }, }, }); return result || []; diff --git a/packages/server/src/services/compose.ts b/packages/server/src/services/compose.ts index 0cec3418b..7a887cdc4 100644 --- a/packages/server/src/services/compose.ts +++ b/packages/server/src/services/compose.ts @@ -131,7 +131,12 @@ export const findComposeById = async (composeId: string) => { server: true, backups: { with: { - destination: true, + destination: { + columns: { + accessKey: false, + secretAccessKey: false, + }, + }, deployments: true, }, }, diff --git a/packages/server/src/services/libsql.ts b/packages/server/src/services/libsql.ts index 8cd61b4af..dd2b82667 100644 --- a/packages/server/src/services/libsql.ts +++ b/packages/server/src/services/libsql.ts @@ -63,7 +63,12 @@ export const findLibsqlById = async (libsqlId: string) => { server: true, backups: { with: { - destination: true, + destination: { + columns: { + accessKey: false, + secretAccessKey: false, + }, + }, deployments: true, }, }, diff --git a/packages/server/src/services/mariadb.ts b/packages/server/src/services/mariadb.ts index 40f9add9b..189ab39ad 100644 --- a/packages/server/src/services/mariadb.ts +++ b/packages/server/src/services/mariadb.ts @@ -68,7 +68,12 @@ export const findMariadbById = async (mariadbId: string) => { server: true, backups: { with: { - destination: true, + destination: { + columns: { + accessKey: false, + secretAccessKey: false, + }, + }, deployments: true, }, }, diff --git a/packages/server/src/services/mongo.ts b/packages/server/src/services/mongo.ts index 2f4dd9af8..ad47cf04a 100644 --- a/packages/server/src/services/mongo.ts +++ b/packages/server/src/services/mongo.ts @@ -63,7 +63,12 @@ export const findMongoById = async (mongoId: string) => { server: true, backups: { with: { - destination: true, + destination: { + columns: { + accessKey: false, + secretAccessKey: false, + }, + }, deployments: true, }, }, diff --git a/packages/server/src/services/mysql.ts b/packages/server/src/services/mysql.ts index 9590e1394..974f72f19 100644 --- a/packages/server/src/services/mysql.ts +++ b/packages/server/src/services/mysql.ts @@ -66,7 +66,12 @@ export const findMySqlById = async (mysqlId: string) => { server: true, backups: { with: { - destination: true, + destination: { + columns: { + accessKey: false, + secretAccessKey: false, + }, + }, deployments: true, }, }, diff --git a/packages/server/src/services/postgres.ts b/packages/server/src/services/postgres.ts index 0900524d8..d4dddfdaf 100644 --- a/packages/server/src/services/postgres.ts +++ b/packages/server/src/services/postgres.ts @@ -76,7 +76,12 @@ export const findPostgresById = async (postgresId: string) => { server: true, backups: { with: { - destination: true, + destination: { + columns: { + accessKey: false, + secretAccessKey: false, + }, + }, deployments: true, }, }, diff --git a/packages/server/src/services/registry.ts b/packages/server/src/services/registry.ts index 65ba80921..4bbc61136 100644 --- a/packages/server/src/services/registry.ts +++ b/packages/server/src/services/registry.ts @@ -162,6 +162,19 @@ export const findRegistryById = async (registryId: string) => { return registryResponse; }; +export const findRegistryByIdWithCredentials = async (registryId: string) => { + const registryResponse = await db.query.registry.findFirst({ + where: eq(registry.registryId, registryId), + }); + if (!registryResponse) { + throw new TRPCError({ + code: "NOT_FOUND", + message: "Registry not found", + }); + } + return registryResponse; +}; + export const findAllRegistryByOrganizationId = async ( organizationId: string, ) => { diff --git a/packages/server/src/services/rollbacks.ts b/packages/server/src/services/rollbacks.ts index 51d978572..97fa4b1c5 100644 --- a/packages/server/src/services/rollbacks.ts +++ b/packages/server/src/services/rollbacks.ts @@ -7,7 +7,6 @@ import { deployments as deploymentsSchema, rollbacks, } from "../db/schema"; -import type { ApplicationNested } from "../utils/builders"; import { getRegistryTag } from "../utils/cluster/upload"; import { calculateResources, @@ -23,7 +22,11 @@ import { findDeploymentById } from "./deployment"; import type { Mount } from "./mount"; import type { Port } from "./port"; import type { Project } from "./project"; -import { type Registry, safeDockerLoginCommand } from "./registry"; +import { + findRegistryByIdWithCredentials, + type Registry, + safeDockerLoginCommand, +} from "./registry"; export const createRollback = async ( input: z.infer, @@ -56,11 +59,29 @@ export const createRollback = async ( ...rest } = await findApplicationById(deployment.applicationId); + const registry = rest.registryId + ? await findRegistryByIdWithCredentials(rest.registryId) + : rest.registry; + const buildRegistry = rest.buildRegistryId + ? await findRegistryByIdWithCredentials(rest.buildRegistryId) + : rest.buildRegistry; + const rollbackRegistry = rest.rollbackRegistryId + ? await findRegistryByIdWithCredentials(rest.rollbackRegistryId) + : rest.rollbackRegistry; + + const fullContextWithCredentials = { + ...rest, + registry, + buildRegistry, + rollbackRegistry, + }; + await tx .update(rollbacks) .set({ image: tagImage, - fullContext: rest, + // eslint-disable-next-line @typescript-eslint/no-explicit-any + fullContext: fullContextWithCredentials as any, }) .where(eq(rollbacks.rollbackId, rollback.rollbackId)); @@ -162,7 +183,6 @@ export const rollback = async (rollbackId: string) => { if (!result.fullContext) { throw new Error("Rollback context not found"); } - // Use the full context for rollback await rollbackApplication( application.appName, result.image || "", @@ -198,24 +218,25 @@ const rollbackApplication = async ( }; mounts: Mount[]; ports: Port[]; - rollbackRegistry?: Registry; + rollbackRegistry?: Registry | null; }, ) => { if (!fullContext) { throw new Error("Full context is required for rollback"); } + const rollbackRegistry = fullContext.rollbackRegistry ?? undefined; + // Ensure Docker daemon is authenticated with the rollback registry // before updating the swarm service. The authconfig in CreateServiceOptions // alone is not sufficient — Docker Swarm also relies on the daemon's // cached credentials (~/.docker/config.json) to distribute auth to nodes. - if (fullContext.rollbackRegistry) { - await dockerLoginForRegistry(fullContext.rollbackRegistry, serverId); + if (rollbackRegistry) { + await dockerLoginForRegistry(rollbackRegistry, serverId); } const docker = await getRemoteDocker(serverId); - // Use the same configuration as mechanizeDockerContainer const { env, mounts, @@ -246,7 +267,9 @@ const rollbackApplication = async ( UpdateConfig, Networks, Ulimits, - } = generateConfigContainer(fullContext as ApplicationNested); + } = generateConfigContainer( + fullContext as Parameters[0], + ); const bindsMount = generateBindMounts(mounts); const envVariables = prepareEnvironmentVariables( @@ -254,18 +277,16 @@ const rollbackApplication = async ( fullContext.environment.project.env, ); - // Build the full registry image path if rollbackRegistry is available - // e.g., "appName:v5" -> "siumauricio/appName:v5" or "registry.com/prefix/appName:v5" let rollbackImage = image; - if (fullContext.rollbackRegistry) { - rollbackImage = getRegistryTag(fullContext.rollbackRegistry, image); + if (rollbackRegistry) { + rollbackImage = getRegistryTag(rollbackRegistry, image); } const settings: CreateServiceOptions = { authconfig: { - password: fullContext.rollbackRegistry?.password || "", - username: fullContext.rollbackRegistry?.username || "", - serveraddress: fullContext.rollbackRegistry?.registryUrl || "", + password: rollbackRegistry?.password || "", + username: rollbackRegistry?.username || "", + serveraddress: rollbackRegistry?.registryUrl || "", }, Name: appName, TaskTemplate: { diff --git a/packages/server/src/services/volume-backups.ts b/packages/server/src/services/volume-backups.ts index b91aedc7c..abd29df1f 100644 --- a/packages/server/src/services/volume-backups.ts +++ b/packages/server/src/services/volume-backups.ts @@ -84,7 +84,12 @@ export const findVolumeBackupById = async (volumeBackupId: string) => { }, }, }, - destination: true, + destination: { + columns: { + accessKey: false, + secretAccessKey: false, + }, + }, }, }); diff --git a/packages/server/src/utils/backups/compose.ts b/packages/server/src/utils/backups/compose.ts index 6640590b0..296498ff3 100644 --- a/packages/server/src/utils/backups/compose.ts +++ b/packages/server/src/utils/backups/compose.ts @@ -4,6 +4,7 @@ import { createDeploymentBackup, updateDeploymentStatus, } from "@dokploy/server/services/deployment"; +import { findDestinationById } from "@dokploy/server/services/destination"; import { findEnvironmentById } from "@dokploy/server/services/environment"; import { findProjectById } from "@dokploy/server/services/project"; import { sendDatabaseBackupNotifications } from "../notifications/database-backup"; @@ -23,7 +24,7 @@ export const runComposeBackup = async ( const environment = await findEnvironmentById(environmentId); const project = await findProjectById(environment.projectId); const { prefix, databaseType, serviceName } = backup; - const destination = backup.destination; + const destination = await findDestinationById(backup.destinationId); const backupFileName = `${getBackupTimestamp()}.${databaseType === "mongo" ? "bson" : "sql"}.gz`; const s3AppName = serviceName ? `${appName}_${serviceName}` : appName; const bucketDestination = `${s3AppName}/${normalizeS3Path(prefix)}${backupFileName}`; diff --git a/packages/server/src/utils/backups/index.ts b/packages/server/src/utils/backups/index.ts index 876579cb1..8f0e0b6dd 100644 --- a/packages/server/src/utils/backups/index.ts +++ b/packages/server/src/utils/backups/index.ts @@ -1,6 +1,7 @@ import { CLEANUP_CRON_JOB } from "@dokploy/server/constants"; import { member } from "@dokploy/server/db/schema"; import type { BackupSchedule } from "@dokploy/server/services/backup"; +import { findDestinationById } from "@dokploy/server/services/destination"; import { getAllServers } from "@dokploy/server/services/server"; import { getWebServerSettings } from "@dokploy/server/services/web-server-settings"; import { eq } from "drizzle-orm"; @@ -131,9 +132,10 @@ export const keepLatestNBackups = async ( if (!backup.keepLatestCount) return; try { - const rcloneFlags = getS3Credentials(backup.destination); + const destination = await findDestinationById(backup.destinationId); + const rcloneFlags = getS3Credentials(destination); const appName = getServiceAppName(backup); - const backupFilesPath = `:s3:${backup.destination.bucket}/${appName}/${normalizeS3Path(backup.prefix)}`; + const backupFilesPath = `:s3:${destination.bucket}/${appName}/${normalizeS3Path(backup.prefix)}`; // --include "*.bson.gz" or "*.sql.gz" or "*.zip" ensures nothing else other than the dokploy backup files are touched by rclone const rcloneList = `rclone lsf ${rcloneFlags.join(" ")} --include "*${backup.databaseType === "web-server" ? ".zip" : ".{sql.gz,bson.gz}"}" ${backupFilesPath}`; diff --git a/packages/server/src/utils/backups/libsql.ts b/packages/server/src/utils/backups/libsql.ts index a994db8bd..7f6c85f48 100644 --- a/packages/server/src/utils/backups/libsql.ts +++ b/packages/server/src/utils/backups/libsql.ts @@ -3,6 +3,7 @@ import { createDeploymentBackup, updateDeploymentStatus, } from "@dokploy/server/services/deployment"; +import { findDestinationById } from "@dokploy/server/services/destination"; import { findEnvironmentById } from "@dokploy/server/services/environment"; import type { Libsql } from "@dokploy/server/services/libsql"; import { findProjectById } from "@dokploy/server/services/project"; @@ -29,7 +30,7 @@ export const runLibsqlBackup = async ( description: "Initializing Backup", }); const { prefix } = backup; - const destination = backup.destination; + const destination = await findDestinationById(backup.destinationId); const backupFileName = `${getBackupTimestamp()}.sql.gz`; const bucketDestination = `${appName}/${normalizeS3Path(prefix)}${backupFileName}`; try { diff --git a/packages/server/src/utils/backups/mariadb.ts b/packages/server/src/utils/backups/mariadb.ts index dea22ff18..121910ee8 100644 --- a/packages/server/src/utils/backups/mariadb.ts +++ b/packages/server/src/utils/backups/mariadb.ts @@ -3,6 +3,7 @@ import { createDeploymentBackup, updateDeploymentStatus, } from "@dokploy/server/services/deployment"; +import { findDestinationById } from "@dokploy/server/services/destination"; import { findEnvironmentById } from "@dokploy/server/services/environment"; import type { Mariadb } from "@dokploy/server/services/mariadb"; import { findProjectById } from "@dokploy/server/services/project"; @@ -23,7 +24,7 @@ export const runMariadbBackup = async ( const environment = await findEnvironmentById(environmentId); const project = await findProjectById(environment.projectId); const { prefix } = backup; - const destination = backup.destination; + const destination = await findDestinationById(backup.destinationId); const backupFileName = `${getBackupTimestamp()}.sql.gz`; const bucketDestination = `${appName}/${normalizeS3Path(prefix)}${backupFileName}`; const deployment = await createDeploymentBackup({ diff --git a/packages/server/src/utils/backups/mongo.ts b/packages/server/src/utils/backups/mongo.ts index cebece14f..4b212d70c 100644 --- a/packages/server/src/utils/backups/mongo.ts +++ b/packages/server/src/utils/backups/mongo.ts @@ -3,6 +3,7 @@ import { createDeploymentBackup, updateDeploymentStatus, } from "@dokploy/server/services/deployment"; +import { findDestinationById } from "@dokploy/server/services/destination"; import { findEnvironmentById } from "@dokploy/server/services/environment"; import type { Mongo } from "@dokploy/server/services/mongo"; import { findProjectById } from "@dokploy/server/services/project"; @@ -20,7 +21,7 @@ export const runMongoBackup = async (mongo: Mongo, backup: BackupSchedule) => { const environment = await findEnvironmentById(environmentId); const project = await findProjectById(environment.projectId); const { prefix } = backup; - const destination = backup.destination; + const destination = await findDestinationById(backup.destinationId); const backupFileName = `${getBackupTimestamp()}.bson.gz`; const bucketDestination = `${appName}/${normalizeS3Path(prefix)}${backupFileName}`; const deployment = await createDeploymentBackup({ diff --git a/packages/server/src/utils/backups/mysql.ts b/packages/server/src/utils/backups/mysql.ts index a72f59880..8d0e6188a 100644 --- a/packages/server/src/utils/backups/mysql.ts +++ b/packages/server/src/utils/backups/mysql.ts @@ -3,6 +3,7 @@ import { createDeploymentBackup, updateDeploymentStatus, } from "@dokploy/server/services/deployment"; +import { findDestinationById } from "@dokploy/server/services/destination"; import { findEnvironmentById } from "@dokploy/server/services/environment"; import type { MySql } from "@dokploy/server/services/mysql"; import { findProjectById } from "@dokploy/server/services/project"; @@ -20,7 +21,7 @@ export const runMySqlBackup = async (mysql: MySql, backup: BackupSchedule) => { const environment = await findEnvironmentById(environmentId); const project = await findProjectById(environment.projectId); const { prefix } = backup; - const destination = backup.destination; + const destination = await findDestinationById(backup.destinationId); const backupFileName = `${getBackupTimestamp()}.sql.gz`; const bucketDestination = `${appName}/${normalizeS3Path(prefix)}${backupFileName}`; const deployment = await createDeploymentBackup({ diff --git a/packages/server/src/utils/backups/postgres.ts b/packages/server/src/utils/backups/postgres.ts index 30a88db2b..e57682f39 100644 --- a/packages/server/src/utils/backups/postgres.ts +++ b/packages/server/src/utils/backups/postgres.ts @@ -3,6 +3,7 @@ import { createDeploymentBackup, updateDeploymentStatus, } from "@dokploy/server/services/deployment"; +import { findDestinationById } from "@dokploy/server/services/destination"; import { findEnvironmentById } from "@dokploy/server/services/environment"; import type { Postgres } from "@dokploy/server/services/postgres"; import { findProjectById } from "@dokploy/server/services/project"; @@ -29,7 +30,7 @@ export const runPostgresBackup = async ( description: "Initializing Backup", }); const { prefix } = backup; - const destination = backup.destination; + const destination = await findDestinationById(backup.destinationId); const backupFileName = `${getBackupTimestamp()}.sql.gz`; const bucketDestination = `${appName}/${normalizeS3Path(prefix)}${backupFileName}`; try { diff --git a/packages/server/src/utils/builders/index.ts b/packages/server/src/utils/builders/index.ts index 69bde1b99..82bbf4eff 100644 --- a/packages/server/src/utils/builders/index.ts +++ b/packages/server/src/utils/builders/index.ts @@ -1,3 +1,4 @@ +import { findRegistryByIdWithCredentials } from "@dokploy/server/services/registry"; import type { InferResultType } from "@dokploy/server/types/with"; import type { CreateServiceOptions } from "dockerode"; import { getRegistryTag, uploadImageRemoteCommand } from "../cluster/upload"; @@ -28,9 +29,9 @@ export type ApplicationNested = InferResultType< security: true; redirects: true; ports: true; - registry: true; - buildRegistry: true; - rollbackRegistry: true; + registry: { columns: { password: false } }; + buildRegistry: { columns: { password: false } }; + rollbackRegistry: { columns: { password: false } }; deployments: true; environment: { with: { project: true } }; } @@ -121,8 +122,8 @@ export const mechanizeDockerContainer = async ( application.environment.env, ); - const image = getImageName(application); - const authConfig = getAuthConfig(application); + const image = await getImageName(application); + const authConfig = await getAuthConfig(application); const docker = await getRemoteDocker(application.serverId); const settings: CreateServiceOptions = { @@ -190,7 +191,7 @@ export const mechanizeDockerContainer = async ( } }; -const getImageName = (application: ApplicationNested) => { +const getImageName = async (application: ApplicationNested) => { const { appName, sourceType, dockerImage, registry, buildRegistry } = application; const imageName = `${appName}:latest`; @@ -199,18 +200,18 @@ const getImageName = (application: ApplicationNested) => { } if (registry) { - const registryTag = getRegistryTag(registry, imageName); - return registryTag; + const r = await findRegistryByIdWithCredentials(registry.registryId); + return getRegistryTag(r, imageName); } if (buildRegistry) { - const registryTag = getRegistryTag(buildRegistry, imageName); - return registryTag; + const r = await findRegistryByIdWithCredentials(buildRegistry.registryId); + return getRegistryTag(r, imageName); } return imageName; }; -export const getAuthConfig = (application: ApplicationNested) => { +export const getAuthConfig = async (application: ApplicationNested) => { const { registry, buildRegistry, @@ -222,23 +223,21 @@ export const getAuthConfig = (application: ApplicationNested) => { if (sourceType === "docker") { if (username && password) { - return { - password, - username, - serveraddress: registryUrl || "", - }; + return { password, username, serveraddress: registryUrl || "" }; } } else if (registry) { + const r = await findRegistryByIdWithCredentials(registry.registryId); return { - password: registry.password, - username: registry.username, - serveraddress: registry.registryUrl, + password: r.password, + username: r.username, + serveraddress: r.registryUrl, }; } else if (buildRegistry) { + const r = await findRegistryByIdWithCredentials(buildRegistry.registryId); return { - password: buildRegistry.password, - username: buildRegistry.username, - serveraddress: buildRegistry.registryUrl, + password: r.password, + username: r.username, + serveraddress: r.registryUrl, }; } diff --git a/packages/server/src/utils/cluster/upload.ts b/packages/server/src/utils/cluster/upload.ts index 6bf02547c..2207f392e 100644 --- a/packages/server/src/utils/cluster/upload.ts +++ b/packages/server/src/utils/cluster/upload.ts @@ -1,5 +1,8 @@ import { findAllDeploymentsByApplicationId } from "@dokploy/server/services/deployment"; -import type { Registry } from "@dokploy/server/services/registry"; +import { + findRegistryByIdWithCredentials, + type Registry, +} from "@dokploy/server/services/registry"; import { createRollback } from "@dokploy/server/services/rollbacks"; import type { ApplicationNested } from "../builders"; @@ -22,19 +25,19 @@ export const uploadImageRemoteCommand = async ( const commands: string[] = []; if (registry) { - const registryTag = getRegistryTag(registry, imageName); + const r = await findRegistryByIdWithCredentials(registry.registryId); + const registryTag = getRegistryTag(r, imageName); if (registryTag) { commands.push(`echo "📦 [Enabled Registry Swarm]"`); - commands.push(getRegistryCommands(registry, imageName, registryTag)); + commands.push(getRegistryCommands(r, imageName, registryTag)); } } if (buildRegistry) { - const buildRegistryTag = getRegistryTag(buildRegistry, imageName); + const r = await findRegistryByIdWithCredentials(buildRegistry.registryId); + const buildRegistryTag = getRegistryTag(r, imageName); if (buildRegistryTag) { commands.push(`echo "🔑 [Enabled Build Registry]"`); - commands.push( - getRegistryCommands(buildRegistry, imageName, buildRegistryTag), - ); + commands.push(getRegistryCommands(r, imageName, buildRegistryTag)); commands.push( `echo "⚠️ INFO: After the build is finished, you need to wait a few seconds for the server to download the image and run the container."`, ); @@ -57,15 +60,13 @@ export const uploadImageRemoteCommand = async ( deploymentId: deploymentId, }); - const rollbackRegistryTag = getRegistryTag( - rollbackRegistry, - rollback?.image || "", + const r = await findRegistryByIdWithCredentials( + rollbackRegistry.registryId, ); + const rollbackRegistryTag = getRegistryTag(r, rollback?.image || ""); if (rollbackRegistryTag) { commands.push(`echo "🔄 [Enabled Rollback Registry]"`); - commands.push( - getRegistryCommands(rollbackRegistry, imageName, rollbackRegistryTag), - ); + commands.push(getRegistryCommands(r, imageName, rollbackRegistryTag)); } } try { @@ -74,6 +75,7 @@ export const uploadImageRemoteCommand = async ( throw error; } }; + /** * Extract the repository name from imageName by taking the last part after '/' * Examples: @@ -117,17 +119,17 @@ const getRegistryCommands = ( ): string => { return ` echo "📦 [Enabled Registry] Uploading image to '${registry.registryType}' | '${registryTag}'" ; -echo "${registry.password}" | docker login ${registry.registryUrl} -u '${registry.username}' --password-stdin || { +echo "${registry.password}" | docker login ${registry.registryUrl} -u '${registry.username}' --password-stdin || { echo "❌ DockerHub Failed" ; exit 1; } echo "✅ Registry Login Success" ; -docker tag ${imageName} ${registryTag} || { +docker tag ${imageName} ${registryTag} || { echo "❌ Error tagging image" ; exit 1; } echo "✅ Image Tagged" ; -docker push ${registryTag} || { +docker push ${registryTag} || { echo "❌ Error pushing image" ; exit 1; } diff --git a/packages/server/src/utils/volume-backups/backup.ts b/packages/server/src/utils/volume-backups/backup.ts index 1d795a14a..a9240f2dd 100644 --- a/packages/server/src/utils/volume-backups/backup.ts +++ b/packages/server/src/utils/volume-backups/backup.ts @@ -1,6 +1,7 @@ import path from "node:path"; import { paths } from "@dokploy/server/constants"; import { findComposeById } from "@dokploy/server/services/compose"; +import { findDestinationById } from "@dokploy/server/services/destination"; import type { findVolumeBackupById } from "@dokploy/server/services/volume-backups"; import { getBackupTimestamp, @@ -31,14 +32,14 @@ export const backupVolume = async ( volumeBackup: Awaited>, ) => { const { serviceType, volumeName, turnOff, prefix } = volumeBackup; + const destination = await findDestinationById(volumeBackup.destinationId); const serverId = volumeBackup.application?.serverId || volumeBackup.compose?.serverId; const { VOLUME_BACKUPS_PATH, VOLUME_BACKUP_LOCK_PATH } = paths(!!serverId); - const destination = volumeBackup.destination; const s3AppName = getVolumeServiceAppName(volumeBackup); const backupFileName = `${volumeName}-${getBackupTimestamp()}.tar`; const bucketDestination = `${s3AppName}/${normalizeS3Path(prefix || "")}${backupFileName}`; - const rcloneFlags = getS3Credentials(volumeBackup.destination); + const rcloneFlags = getS3Credentials(destination); const rcloneDestination = `:s3:${destination.bucket}/${bucketDestination}`; const volumeBackupPath = path.join(VOLUME_BACKUPS_PATH, volumeBackup.appName); diff --git a/packages/server/src/utils/volume-backups/utils.ts b/packages/server/src/utils/volume-backups/utils.ts index a1eb0a8f1..8edca6cf6 100644 --- a/packages/server/src/utils/volume-backups/utils.ts +++ b/packages/server/src/utils/volume-backups/utils.ts @@ -4,6 +4,7 @@ import { createDeploymentVolumeBackup, updateDeploymentStatus, } from "@dokploy/server/services/deployment"; +import { findDestinationById } from "@dokploy/server/services/destination"; import { findVolumeBackupById } from "@dokploy/server/services/volume-backups"; import { execAsync, @@ -77,7 +78,8 @@ const cleanupOldVolumeBackups = async ( volumeBackup: Awaited>, serverId?: string | null, ) => { - const { keepLatestCount, destination, prefix, volumeName } = volumeBackup; + const { keepLatestCount, prefix, volumeName } = volumeBackup; + const destination = await findDestinationById(volumeBackup.destinationId); if (!keepLatestCount) return;