Skip to content

Commit 24f4c30

Browse files
passcodclaude
andcommitted
fix(canopy): set KOPIA_PASSWORD env so snapshot restore can reopen the repo
The canopy restore path ran 'kopia repository connect' and 'kopia snapshot restore' as two separate processes, passing the repo password only to connect via --password. The restore process must reopen the repository and needs the password again; headless containers have no keyring for kopia to retrieve the persisted credential, so it fell back to an interactive prompt and died with 'inappropriate ioctl for device'. Mirror the legacy restore path by setting KOPIA_PASSWORD on the kopia container env, which kopia reads on every invocation. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1 parent c538b87 commit 24f4c30

1 file changed

Lines changed: 27 additions & 5 deletions

File tree

src/controllers/canopy/builders.rs

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -205,11 +205,25 @@ pub fn build_canopy_restore_job(cfg: &CanopyRestoreJobConfig<'_>) -> Job {
205205
args: Some(vec![script]),
206206
env: Some(
207207
[
208-
vec![EnvVar {
209-
name: "SNAPSHOT_ID".into(),
210-
value: Some(cfg.snapshot_id.into()),
211-
..Default::default()
212-
}],
208+
vec![
209+
EnvVar {
210+
name: "SNAPSHOT_ID".into(),
211+
value: Some(cfg.snapshot_id.into()),
212+
..Default::default()
213+
},
214+
// `snapshot restore` runs as a separate kopia process from
215+
// `repository connect`, so it must re-open the repository and
216+
// needs the password. Headless containers have no keyring for
217+
// kopia to retrieve the persisted credential from, so without
218+
// this env var it falls back to an interactive prompt and dies
219+
// with "inappropriate ioctl for device". kopia reads
220+
// KOPIA_PASSWORD on every invocation.
221+
EnvVar {
222+
name: "KOPIA_PASSWORD".into(),
223+
value: Some(cfg.repo_password.into()),
224+
..Default::default()
225+
},
226+
],
213227
kopia_writable_env(),
214228
]
215229
.concat(),
@@ -637,6 +651,14 @@ mod tests {
637651
.iter()
638652
.any(|e| e.name == "SNAPSHOT_ID" && e.value.as_deref() == Some("abc123"))
639653
);
654+
// KOPIA_PASSWORD must be on the container env so `snapshot restore`
655+
// (a separate process from `repository connect`) can re-open the
656+
// repository without an interactive password prompt.
657+
assert!(
658+
kopia_env
659+
.iter()
660+
.any(|e| e.name == "KOPIA_PASSWORD" && e.value.as_deref() == Some("supersecret"))
661+
);
640662
let kopia_mounts = pod_spec.containers[0].volume_mounts.as_ref().unwrap();
641663
assert!(
642664
kopia_mounts

0 commit comments

Comments
 (0)