mirror of
https://github.com/Dokploy/dokploy.git
synced 2026-07-11 00:45:26 +02:00
feat: optionally include encryption key in web server backups
This commit is contained in:
5
apps/dokploy/__test__/env/encryption.test.ts
vendored
5
apps/dokploy/__test__/env/encryption.test.ts
vendored
@@ -1,6 +1,7 @@
|
||||
import {
|
||||
decryptValue,
|
||||
encryptValue,
|
||||
exportEncryptionKey,
|
||||
isEncrypted,
|
||||
} from "@dokploy/server/lib/encryption";
|
||||
import { afterEach, describe, expect, it, vi } from "vitest";
|
||||
@@ -42,6 +43,10 @@ describe("encryptValue / decryptValue", () => {
|
||||
const tampered = `${encrypted.slice(0, -4)}AAAA`;
|
||||
expect(() => decryptValue(tampered)).toThrow(/BETTER_AUTH_SECRET/);
|
||||
});
|
||||
|
||||
it("exports the primary key as 32-byte hex for backups", () => {
|
||||
expect(exportEncryptionKey()).toMatch(/^[0-9a-f]{64}$/);
|
||||
});
|
||||
});
|
||||
|
||||
describe("dedicated ENCRYPTION_KEY", () => {
|
||||
|
||||
@@ -79,6 +79,7 @@ const Schema = z
|
||||
schedule: z.string().min(1, "Schedule (Cron) required"),
|
||||
prefix: z.string().min(1, "Prefix required"),
|
||||
enabled: z.boolean(),
|
||||
includeEncryptionKey: z.boolean(),
|
||||
database: z.string().min(1, "Database required"),
|
||||
keepLatestCount: z.coerce.number().optional(),
|
||||
serviceName: z.string().nullable(),
|
||||
@@ -223,6 +224,7 @@ export const HandleBackup = ({
|
||||
: "",
|
||||
destinationId: "",
|
||||
enabled: true,
|
||||
includeEncryptionKey: true,
|
||||
prefix: "/",
|
||||
schedule: "",
|
||||
keepLatestCount: undefined,
|
||||
@@ -262,6 +264,7 @@ export const HandleBackup = ({
|
||||
: "",
|
||||
destinationId: backup?.destinationId ?? "",
|
||||
enabled: backup?.enabled ?? true,
|
||||
includeEncryptionKey: backup?.includeEncryptionKey ?? true,
|
||||
prefix: backup?.prefix ?? "/",
|
||||
schedule: backup?.schedule ?? "",
|
||||
keepLatestCount: backup?.keepLatestCount ?? undefined,
|
||||
@@ -309,6 +312,7 @@ export const HandleBackup = ({
|
||||
prefix: data.prefix,
|
||||
schedule: data.schedule,
|
||||
enabled: data.enabled,
|
||||
includeEncryptionKey: data.includeEncryptionKey,
|
||||
database: data.database,
|
||||
keepLatestCount: data.keepLatestCount ?? null,
|
||||
databaseType: data.databaseType || databaseType,
|
||||
@@ -665,6 +669,31 @@ export const HandleBackup = ({
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
{databaseType === "web-server" && (
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="includeEncryptionKey"
|
||||
render={({ field }) => (
|
||||
<FormItem className="flex flex-row items-center justify-between rounded-lg border p-3 ">
|
||||
<div className="space-y-0.5">
|
||||
<FormLabel>Include encryption key</FormLabel>
|
||||
<FormDescription>
|
||||
Stores the encryption key inside the backup so
|
||||
environment variables can be restored on a new server.
|
||||
Anyone with access to the backup file can decrypt
|
||||
them.
|
||||
</FormDescription>
|
||||
</div>
|
||||
<FormControl>
|
||||
<Switch
|
||||
checked={field.value}
|
||||
onCheckedChange={field.onChange}
|
||||
/>
|
||||
</FormControl>
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
)}
|
||||
{backupType === "compose" && (
|
||||
<>
|
||||
{form.watch("databaseType") === "postgres" && (
|
||||
|
||||
1
apps/dokploy/drizzle/0174_great_naoko.sql
Normal file
1
apps/dokploy/drizzle/0174_great_naoko.sql
Normal file
@@ -0,0 +1 @@
|
||||
ALTER TABLE "backup" ADD COLUMN "includeEncryptionKey" boolean DEFAULT true NOT NULL;
|
||||
8551
apps/dokploy/drizzle/meta/0174_snapshot.json
Normal file
8551
apps/dokploy/drizzle/meta/0174_snapshot.json
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1219,6 +1219,13 @@
|
||||
"when": 1783494977500,
|
||||
"tag": "0173_aspiring_annihilus",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 174,
|
||||
"version": "7",
|
||||
"when": 1783674181297,
|
||||
"tag": "0174_great_naoko",
|
||||
"breakpoints": true
|
||||
}
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user