From 3113af8ce8e06a54d14cbdc50e1b05760188b616 Mon Sep 17 00:00:00 2001 From: Nico <47644445+nicotsx@users.noreply.github.com> Date: Thu, 26 Feb 2026 19:46:25 +0100 Subject: [PATCH] fix(repo): add a custom key after creation with the configured hostname (#583) Closes #456 --- AGENTS.md | 1 + app/server/utils/restic.ts | 48 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+) diff --git a/AGENTS.md b/AGENTS.md index 4b4cc050..c1891294 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -6,6 +6,7 @@ - If you realize an automated migration is incorrect, make sure to remove all the associated entries from the `_journal.json` and the newly created files located in `app/drizzle/` before re-generating the migration - The dev server is running at http://localhost:3000. Username is `admin` and password is `password` - The repo is https://github.com/nicotsx/zerobyte +- If you need to run a specific restic command on a repository, you can open and use the dev panel with `Meta+Shift+D` ## Project Overview diff --git a/app/server/utils/restic.ts b/app/server/utils/restic.ts index 951ec125..be8d3cf2 100644 --- a/app/server/utils/restic.ts +++ b/app/server/utils/restic.ts @@ -235,6 +235,41 @@ export const buildEnv = async (config: RepositoryConfig, organizationId: string) return env; }; +const keyAdd = async ( + config: RepositoryConfig, + organizationId: string, + options: { host: string; timeoutMs?: number }, +) => { + const repoUrl = buildRepoUrl(config); + + logger.info(`Adding restic key with host "${options.host}" for repository at ${repoUrl}...`); + + const env = await buildEnv(config, organizationId); + + const args = [ + "key", + "add", + "--repo", + repoUrl, + "--host", + options.host, + "--new-password-file", + env.RESTIC_PASSWORD_FILE, + ]; + addCommonArgs(args, env, config); + + const res = await safeExec({ command: "restic", args, env, timeout: options.timeoutMs ?? 60000 }); + await cleanupTemporaryKeys(env); + + if (res.exitCode !== 0) { + logger.error(`Restic key add failed: ${res.stderr}`); + return { success: false, error: res.stderr }; + } + + logger.info(`Restic key added with host "${options.host}" for repository: ${repoUrl}`); + return { success: true, error: null }; +}; + const init = async (config: RepositoryConfig, organizationId: string, options?: { timeoutMs?: number }) => { const repoUrl = buildRepoUrl(config); @@ -254,6 +289,18 @@ const init = async (config: RepositoryConfig, organizationId: string, options?: } logger.info(`Restic repository initialized: ${repoUrl}`); + + if (appConfig.resticHostname) { + const keyResult = await keyAdd(config, organizationId, { + host: appConfig.resticHostname, + timeoutMs: options?.timeoutMs, + }); + + if (!keyResult.success) { + logger.warn(`Repository initialized but failed to add key with hostname: ${keyResult.error}`); + } + } + return { success: true, error: null }; }; @@ -1248,6 +1295,7 @@ export const addCommonArgs = ( export const restic = { init, + keyAdd, backup, restore, dump,