Skip to content

Comments

openssh: Add helper scripts to fix service binPath and autostart#7666

Open
SwingURM wants to merge 2 commits intoScoopInstaller:masterfrom
SwingURM:openssh-fix-service-binpath
Open

openssh: Add helper scripts to fix service binPath and autostart#7666
SwingURM wants to merge 2 commits intoScoopInstaller:masterfrom
SwingURM:openssh-fix-service-binpath

Conversation

@SwingURM
Copy link

@SwingURM SwingURM commented Feb 21, 2026

Closes #7665

  • Use conventional PR title: <manifest-name[@version]|chore>: <general summary of the pull request>
  • I have read the Contributing Guide

Add post_install scripts that are generated on install:

  • fix.ps1 — Rewrites sshd and ssh-agent service binPath to the real absolute path.
  • autostart-sshd.ps1 — Sets both sshd and ssh-agent services to Automatic startup type.

Summary by CodeRabbit

  • New Features

    • Added automated post-install setup for SSH services to resolve paths, apply fixes, and enable automatic startup.
  • Chores

    • Updated installation notes with instructions for uninstalling, running the post-install fix, and enabling SSH autostart.

@github-actions
Copy link
Contributor

All changes look good.

Wait for review from human collaborators.

openssh

  • Lint
  • Description
  • License
  • Hashes
  • Checkver
  • Autoupdate

Check the full log for details.

@SwingURM
Copy link
Author

@coderabbitai review

@coderabbitai
Copy link

coderabbitai bot commented Feb 21, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai
Copy link

coderabbitai bot commented Feb 21, 2026

📝 Walkthrough

Walkthrough

Added post-install PowerShell commands to the OpenSSH manifest that resolve the real installation path (follow symlinks), create a fix script to rewrite service binPath to absolute targets, and create an autostart script to set sshd and ssh-agent to Automatic startup.

Changes

Cohort / File(s) Summary
OpenSSH Manifest
bucket/openssh.json
Added a post_install array with PowerShell commands to: resolve the real directory behind the current symlink, create fix.ps1 (rewrites sshd/ssh-agent service binPath to absolute paths), and create autostart-sshd.ps1 (sets services startup type to Automatic). Updated notes to include uninstall, fix, and autostart instructions.

Sequence Diagram(s)

sequenceDiagram
  participant Scoop as Installer (Scoop)
  participant Post as post_install script
  participant FS as Filesystem / Symlink
  participant FixPS as fix.ps1
  participant SCM as Service Control Manager / Registry
  participant AutostartPS as autostart-sshd.ps1

  Scoop->>Post: run post_install commands
  Post->>FS: resolve real directory for `current` symlink
  Post->>FixPS: create fix.ps1 with resolved absolute paths
  FixPS->>SCM: update `sshd` and `ssh-agent` service `binPath` to absolute targets
  Post->>AutostartPS: create autostart-sshd.ps1
  AutostartPS->>SCM: set `sshd` and `ssh-agent` StartupType = Automatic
Loading

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely describes the main change: adding helper scripts to fix service binPath and enable autostart for OpenSSH services.
Description check ✅ Passed The description includes the linked issue reference (#7665), marks both checklist items, and explains the purpose of the new post_install scripts (fix.ps1 and autostart-sshd.ps1).
Linked Issues check ✅ Passed The PR directly addresses the requirements from issue #7665 by implementing post_install scripts that rewrite service binPath to absolute paths and provide autostart functionality.
Out of Scope Changes check ✅ Passed All changes in bucket/openssh.json are directly related to implementing the solution for issue #7665; no out-of-scope modifications are present.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Tip

Issue Planner is now in beta. Read the docs and try it out! Share your feedback on Discord.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
bucket/openssh.json (1)

47-47: Note the re-run requirement after scoop update in the notes.

fix.ps1 embeds the resolved absolute versioned path at install time (e.g., ...\openssh\10.0.0.0p2\sshd.exe). Scoop runs post_install on updates as well, expanding $dir to the current junction path, so each update regenerates fix.ps1 with the new version's path — but the service registry entry is not automatically updated. Users must re-run sudo fix.ps1 after every scoop update openssh for the service to point to the new binary.

Consider expanding the note to reflect this:

📝 Proposed note update
-        "Run 'sudo $dir\\fix.ps1' to fix service binPath to absolute path.",
+        "Run 'sudo $dir\\fix.ps1' to fix service binPath to absolute path. Re-run after every 'scoop update openssh'.",

Also applies to: 54-54

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@bucket/openssh.json` at line 47, The post_install script writes fix.ps1
embedding the resolved versioned path (via Set-Content writing to
"$dir\\fix.ps1"), but Scoop re-runs post_install on updates using the current
junction path and does not update existing Windows service registry entries, so
users must re-run sudo fix.ps1 after every scoop update openssh to repoint
services to the new binary; update the notes referenced (and the duplicate at
the second occurrence) to explicitly state that after running scoop update
openssh the user must re-run sudo fix.ps1 (or re-create the sshd/ssh-agent
service entries) to update the service binPath to the new version.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@bucket/openssh.json`:
- Line 45: The post_install line using [IO.Directory]::ResolveLinkTarget($dir,
$true).FullName is a .NET 6+ API and will throw on Windows PowerShell 5.1;
replace that call with the PowerShell 5.0+ compatible approach using (Get-Item
$dir -Force).Target and keep the existing fallback logic (i.e., assign the
target to $real and if it's null/empty set $real = $dir) so junction targets are
resolved when present but the script continues when not a link; update the
expression that sets $real to use the (Get-Item ...).Target lookup and preserve
the subsequent if (!$real) { $real = $dir } behavior.

---

Nitpick comments:
In `@bucket/openssh.json`:
- Line 47: The post_install script writes fix.ps1 embedding the resolved
versioned path (via Set-Content writing to "$dir\\fix.ps1"), but Scoop re-runs
post_install on updates using the current junction path and does not update
existing Windows service registry entries, so users must re-run sudo fix.ps1
after every scoop update openssh to repoint services to the new binary; update
the notes referenced (and the duplicate at the second occurrence) to explicitly
state that after running scoop update openssh the user must re-run sudo fix.ps1
(or re-create the sshd/ssh-agent service entries) to update the service binPath
to the new version.

@SwingURM
Copy link
Author

@coderabbitai review

@coderabbitai
Copy link

coderabbitai bot commented Feb 21, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
bucket/openssh.json (1)

44-45: (Get-Item $dir -Force).Target addresses the previous PS 5.1 compatibility concern.

The .ResolveLinkTarget issue from the prior review is resolved. Two small notes:

  • .Target resolves only one level of indirection, unlike the earlier ResolveLinkTarget($dir, $true) (recursive). For Scoop's single-layer current junction this is sufficient.
  • Get-Item $dir treats the path as a glob pattern, so a Scoop root containing [, ], or * characters would silently fail to match. -LiteralPath avoids this:
🔧 Optional: use -LiteralPath
-        "$real = (Get-Item $dir -Force).Target; if (!$real) { $real = $dir }",
+        "$real = (Get-Item -LiteralPath $dir -Force).Target; if (!$real) { $real = $dir }",
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@bucket/openssh.json` around lines 44 - 45, The current post_install snippet
uses (Get-Item $dir -Force).Target which works but treats $dir as a glob; update
the Get-Item call to use -LiteralPath to avoid accidental glob expansion (i.e.,
replace Get-Item $dir -Force with Get-Item -LiteralPath $dir -Force) while
keeping the existing $real fallback logic (post_install, $real, and the !$real
check) intact; note that .Target is single-level resolution which is acceptable
for Scoop's single-layer junction usage.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@bucket/openssh.json`:
- Around line 46-47: The generated fix.ps1 currently uses a $q helper and writes
sc.exe config lines that lose their surrounding double-quotes when PowerShell
evaluates them; remove the "$q = [char]34" helper and change the two sc.exe
strings written by Set-Content (the sc.exe config sshd binPath= ... and sc.exe
config ssh-agent binPath= ... entries) to use a parenthesised single-quoted
expression that includes literal double-quote characters around the real path
(e.g. use ('"'+ <real path> + '"' ) style so the resulting ImagePath in the
registry includes the quote characters and preserves paths with spaces).

---

Nitpick comments:
In `@bucket/openssh.json`:
- Around line 44-45: The current post_install snippet uses (Get-Item $dir
-Force).Target which works but treats $dir as a glob; update the Get-Item call
to use -LiteralPath to avoid accidental glob expansion (i.e., replace Get-Item
$dir -Force with Get-Item -LiteralPath $dir -Force) while keeping the existing
$real fallback logic (post_install, $real, and the !$real check) intact; note
that .Target is single-level resolution which is acceptable for Scoop's
single-layer junction usage.

Comment on lines +46 to +47
"$q = [char]34",
"Set-Content \"$dir\\fix.ps1\" @(\"sc.exe config sshd binPath= ${q}${real}\\sshd.exe${q}\", \"sc.exe config ssh-agent binPath= ${q}${real}\\ssh-agent.exe${q}\") -Encoding UTF8",
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Generated fix.ps1 drops the binPath quotes, breaking paths with spaces.

The post-install command writes sc.exe config sshd binPath= "…\sshd.exe" into fix.ps1. When PowerShell 5.1 later executes that line it treats the outer "…" as a string literal, strips the delimiters, and hands sc.exe the bare path. For paths without spaces the stored registry ImagePath is correct; but for a Scoop root that contains spaces (e.g. C:\Users\My User\scoop\…), sc.exe stores an unquoted path and the SCM tokenises at the first space on service start — exactly the failure mode this PR is trying to fix.

The registry ImagePath must contain the path wrapped in double-quote characters for SCM to handle spaces correctly.

Replace the $q auxiliary line and both sc.exe strings with a parenthesised single-quoted expression — ('"…"') — which produces a PS string value that includes the literal double-quote chars and forwards them untouched to sc.exe:

🐛 Proposed fix for sc.exe binPath quoting
-        "$q = [char]34",
-        "Set-Content \"$dir\\fix.ps1\" @(\"sc.exe config sshd binPath= ${q}${real}\\sshd.exe${q}\", \"sc.exe config ssh-agent binPath= ${q}${real}\\ssh-agent.exe${q}\") -Encoding UTF8",
+        "Set-Content \"$dir\\fix.ps1\" @(\"sc.exe config sshd binPath= ('`\"${real}\\sshd.exe`\"')\", \"sc.exe config ssh-agent binPath= ('`\"${real}\\ssh-agent.exe`\"')\") -Encoding UTF8",

The generated fix.ps1 will then contain lines such as:

sc.exe config sshd binPath= ('"C:\actual\path\sshd.exe"')
sc.exe config ssh-agent binPath= ('"C:\actual\path\ssh-agent.exe"')

The single-quoted expression '"…"' evaluates to a string value that carries the double-quote characters, so sc.exe receives and stores "C:\actual\path\sshd.exe" (with quotes) in ImagePath. This is safe for both spaced and space-free paths.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@bucket/openssh.json` around lines 46 - 47, The generated fix.ps1 currently
uses a $q helper and writes sc.exe config lines that lose their surrounding
double-quotes when PowerShell evaluates them; remove the "$q = [char]34" helper
and change the two sc.exe strings written by Set-Content (the sc.exe config sshd
binPath= ... and sc.exe config ssh-agent binPath= ... entries) to use a
parenthesised single-quoted expression that includes literal double-quote
characters around the real path (e.g. use ('"'+ <real path> + '"' ) style so the
resulting ImagePath in the registry includes the quote characters and preserves
paths with spaces).

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: symlink in OpenSSH service binPath causes issues

1 participant