Skip to content

certgen: std::fs::rename fails with EXDEV on WSL/container cross-device mounts #2173

Description

@rsandbach

Agent Diagnostic

Can't use an agent if I can't setup a gateway. :-D (I had GitHub copilot start drafting this issue, after working out why the cross device failure was happening)

When generating cert files, crates/openshell-server/src/certgen.rs uses std::fs::rename(...) to move the newly generated certificates to the specified output directory. In some cases, the source and destination can land on different mounts/devices. In that case, rename(2) returns EXDEV (Rust: std::io::ErrorKind::CrossesDevices), which causes cert generation to fail.

Due to the location the temporary files are created, ${output_dir}.certgen.tmp, they are actually being created on the container's tempfs, not the attached volume. This can lead to the cross devices error.

Workaround (set --output-dir to a new folder within the mounted volume)

PS C:\> container run --rm -it -u 0:0 -v ogc:/extvol ghcr.io/nvidia/openshell/gateway:latest generate-certs --output-dir "/extvol/z"
2026-07-08T03:31:06.530744Z  INFO openshell_server::certgen: PKI files created. dir=/extvol/z

Expected

Cert generation should succeed regardless of whether source/destination are on the same device.
The temp certs probably should get created IN the --output-dir, not next to it.

Actual

Move step fails with cross-device rename error (EXDEV / CrossesDevices).

Proposed fix

Use a cross-device-safe move:

  1. Attempt std::fs::rename(src, dst) first.
  2. On ErrorKind::CrossesDevices, fallback to:
    • std::fs::copy(src, dst)
    • preserve permissions if needed
    • std::fs::remove_file(src)
  3. Propagate all other errors unchanged.

OR

Generate the temporary certificates within a folder of the output dir (/extvol/certgen.tmp/ca.crt), not in it.

Why this change

This preserves same-device fast path/behavior while handling common WSL/container mount layouts where cross-device moves are expected.

Description

generate-certs fails with --output-dir args.
generate-certs to be successful.

Reproduction Steps

Environment

  • Windows host + WSLC
PS C:\> container run --rm -it -u 0:0 -v ogc:/extvol ghcr.io/nvidia/openshell/gateway:latest generate-certs --output-dir "/extvol"
Error:   x failed to move /extvol.certgen.tmp/ca.crt -> /extvol/ca.crt
  `-> Invalid cross-device link (os error 18)

Environment

Windows 11 25H2
wslc 2.9.3.0

Logs

Error:   x failed to move /extvol.certgen.tmp/ca.crt -> /extvol/ca.crt
  `-> Invalid cross-device link (os error 18)

Agent-First Checklist

  • I pointed my agent at the repo and had it investigate this issue
  • I loaded relevant skills (e.g., debug-openshell-cluster, debug-inference, openshell-cli)
  • My agent could not resolve this — the diagnostic above explains why

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:gatewayGateway server and control-plane worktopic:compatibilityCompatibility-related work

    Type

    Fields

    No fields configured for Bug.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions