Skip to content

Clarify that --signTemplate works when cross compiling - #69

Open
virzak wants to merge 1 commit into
velopack:masterfrom
virzak:docs/signing-on-linux
Open

Clarify that --signTemplate works when cross compiling#69
virzak wants to merge 1 commit into
velopack:masterfrom
virzak:docs/signing-on-linux

Conversation

@virzak

@virzak virzak commented Jul 28, 2026

Copy link
Copy Markdown

Two statements in the docs say a Windows package can only be signed on Windows. Both contradict the Cross Platform Signing section on the same page, which already documents JSign on Linux/macOS via --signTemplate.

cross-compiling.mdx — "The standard --signParams / --signTemplate path relies on signtool.exe, which only runs on Windows." --signTemplate doesn't; it runs whatever command it's given.

signing.mdx — "Signing relies on signtool.exe which is only supported on Windows. If you are using a different operating system, you will need to sign your binaries on a Windows machine before deploying them."

Why the corrected version is right

In WindowsPackCommand.cs, --signParams and --azureTrustedSignFile are registered inside if (VelopackRuntimeInfo.IsWindows), while --signTemplate is registered unconditionally — so on Linux the signtool-backed flags aren't even offered, and vpk [win] pack --help lists only --signTemplate.

In WindowsPackCommandRunner.cs the template runs before the platform guard:

if (!string.IsNullOrEmpty(signTemplate)) {
    helper.Sign(filePaths, signTemplate, signParallel, progress, true);
}
// signtool.exe does not work if we're not on windows.
if (!VelopackRuntimeInfo.IsWindows) return;

Confirmed empirically on Ubuntu — vpk [win] pack ... --signTemplate "..." reported "Code-signed 5/5 files" for the app payload and "Code-signed 1/1 files" for the setup bundle. MyApp-win-Setup.exe, Squirrel.exe, MyApp_ExecutionStub.exe, MyApp.exe and MyApp.dll all came out with a populated certificate table whose digest matches the file.

Changes

Both notes are scoped to the signtool-backed options and link to the existing Cross Platform Signing section. No new tools are recommended; the JSign section is unchanged.

Translated copies weren't touched.

Disclosure: I maintain a cross-platform signing tool that works via --signTemplate, which is how I ran into this. I've deliberately left it out of the changes — this is a correction, not a placement. Happy to add it next to JSign if you'd want a .NET-native option there, but that's your call and not part of this PR.

Two places state that signing a Windows package requires Windows, which
contradicts the Cross Platform Signing section documenting JSign via
--signTemplate:

- cross-compiling.mdx said the "--signParams / --signTemplate path relies
  on signtool.exe". --signTemplate does not; it runs an arbitrary command.
- signing.mdx said signing relies on signtool.exe and that other operating
  systems must sign on a Windows machine.

In WindowsPackCommand.cs, --signParams and --azureTrustedSignFile are
registered inside 'if (VelopackRuntimeInfo.IsWindows)' while --signTemplate
is registered unconditionally, and WindowsPackCommandRunner runs the
template before the 'if (!VelopackRuntimeInfo.IsWindows) return' guard.

Scope both notes to the signtool-backed options and point at the existing
Cross Platform Signing section.
@caesay

caesay commented Jul 28, 2026

Copy link
Copy Markdown
Member

presumably your mentioned sign tool is https://github.com/zompinc/sign-universal ? I would be genuinely interested in providing a native / integrated option for signing windows PE/MSI on nix. Given it's pure .NET it could in theory be shipped embedded with VPK. is that something you'd be open to?

@virzak

virzak commented Jul 28, 2026

Copy link
Copy Markdown
Author

Yeah, happily.

The draft is linked to this issue (velopack/velopack#1019). It makes --azureTrustedSignFile work on Linux and macOS by swapping the signtool Dlib for the managed Trusted Signing client — same metadata.json, key still never local. Windows keeps the Dlib, so nothing existing changes. Verified on Ubuntu against a live account: 6 payload files plus the setup bundle, real certificate, full chain, timestamped. This PR is a proof of concept, happy to rework if you have other ideas.

The engine is on nuget.org as SignUniversal (1.0.34, MIT license).

Azure SDK is now a transitive dependency through SignUniversal.Azure.

PS: also works with PFX.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants