Loosely Decoupled
GuideSSHPowerShell

Configure SSH Key Authentication for an Administrator on Windows Server with PowerShell

Windows OpenSSH ignores an administrator’s authorized_keys. Put the key in administrators_authorized_keys with the right ACL, scripted for a fresh server.

A patent-style drawing of a cheerful tin robot holding a key to the wrong one of two doors, while the correct, more heavily guarded door stands beside it. The key is cyan.
On this page

TL;DR

For any account in the local Administrators group, the public key goes in one shared file, and that file must be accessible only by Administrators and SYSTEM. In an elevated PowerShell session on the server, with your public key in $publicKey:

PowerShell
$authorizedKeys = "$env:ProgramData\ssh\administrators_authorized_keys"

Add-Content -Path $authorizedKeys -Value $publicKey -Encoding ascii
icacls.exe $authorizedKeys /inheritance:r /grant 'Administrators:F' /grant 'SYSTEM:F'

Then from the client:

Command
$ ssh -i ~/.ssh/id_ed25519 Administrator@server-address

No password prompt means it worked. A non-administrator account uses ~\.ssh\authorized_keys as on any other OpenSSH server and needs none of this.

The OpenSSH port for Windows makes one deliberate departure from the sshd_config defaults you know. Its stock configuration ends with:

Text
Match Group administrators
       AuthorizedKeysFile __PROGRAMDATA__/ssh/administrators_authorized_keys

So for an administrator, the per-user authorized_keys is never consulted, and ssh-copy-id — which doesn’t exist on Windows anyway — would put the key in a file sshd never reads. The key goes in the shared file, and sshd ignores that file without saying why if an ordinary user can write to it.

Generate a key pair on the client

If you do not already have one:

Command
$ ssh-keygen -t ed25519

Take the defaults. Key formats, ssh-keygen and the rest of the client side are unmodified OpenSSH, so a key you already use elsewhere works here too. The public half is ~/.ssh/id_ed25519.pub, one line beginning ssh-ed25519. That line is what the server needs; the private half never leaves the client.

Get the public key onto the server

Pick whichever route reaches the server. In a password-authenticated SSH session, or an RDP session, paste the one line into a variable on the server:

PowerShell
# Paste the whole public key line between the quotes.
$publicKey = 'ssh-ed25519 AAAA... you@laptop'

Or, from the client, copy the line in one step, which avoids pasting a long line through a terminal:

Command
$ scp ~/.ssh/id_ed25519.pub Administrator@server-address:id_ed25519.pub

and on the server:

PowerShell
$publicKey = Get-Content "$env:USERPROFILE\id_ed25519.pub"

Write the key and fix the permissions

PowerShell
$sshDir        = "$env:ProgramData\ssh"
$authorizedKeys = "$sshDir\administrators_authorized_keys"

if (-not (Test-Path $sshDir)) {
    New-Item -ItemType Directory -Path $sshDir | Out-Null
}

Add-Content -Path $authorizedKeys -Value $publicKey -Encoding ascii

icacls.exe $authorizedKeys /inheritance:r /grant 'Administrators:F' /grant 'SYSTEM:F'

Add-Content creates the file if it is missing and appends if it is not, so the same lines add a second administrator’s key later. -Encoding ascii is not decoration: see the first common failure.

/inheritance:r strips the inherited entries. The two /grant entries put back the only two principals Microsoft’s documentation allows on this file. sshd’s own permission check is looser, and rejects the file only when another account has write access. Confirm:

PowerShell
icacls.exe $authorizedKeys

The output should list exactly BUILTIN\Administrators:(F) and NT AUTHORITY\SYSTEM:(F).

Test from the client

sshd reads the keys file at every sign-in, so no restart is needed. From the client:

Command
$ ssh -i ~/.ssh/id_ed25519 Administrator@server-address

Expected result

You’re signed in without a password prompt. Once that holds for every account that needs access, turn password authentication off in C:\ProgramData\ssh\sshd_config:

Text
PasswordAuthentication no

and restart the service, which reads sshd_config only when it starts. Leave password authentication on until the key login is confirmed, or you’ll lock yourself out of the server you’re configuring.

Common failures

Login still asks for a password

The key is in the file and the ACL is right, but the file isn’t plain ASCII. In Windows PowerShell 5.1, > and Out-File write UTF-16 with a byte-order mark, and sshd can’t parse a key that starts with one. Delete the file and write it again with Add-Content -Encoding ascii or Set-Content -Encoding ascii. Inspect a suspect file: a good file starts 73 73 68 (ssh), a bad one starts FF FE.

PowerShell
Format-Hex -Path $authorizedKeys | Select-Object -First 1

ACL shows extra principals after icacls

Inheritance wasn’t removed before granting. Run the /inheritance:r form earlier, which does both steps in one call, and check again.

icacls reports no mapping for an account name

Error

No mapping between account names and security IDs was done.

The Windows installation isn’t in English, and the Administrators group has a localized name. Grant it by SID instead, with /grant '*S-1-5-32-544:F' in place of /grant 'Administrators:F'.

Works for one account and not another

The second account isn’t an administrator. For it, the key belongs in that user’s own C:\Users\<name>\.ssh\authorized_keys, and the shared file is irrelevant.

Client output doesn’t explain the refusal

Ask the server. When the ACL is the cause, Server 2025 logs it under Applications and Services Logs > OpenSSH > Operational, naming the file and the account that can write to it. Server 2022’s OpenSSH 8.1 logs only “Authentication refused” there; the line naming the file goes to the OpenSSH > Debug channel, which is off by default. An encoding fault logs nothing there, so check the bytes as described earlier. ssh -v on the client shows only that the key was offered and declined.

Tested with

OS
Windows Server 2025 Datacenter (26100.33438) and Windows Server 2022 Datacenter (20348.5622)
OpenSSH
9.5p2 on 2025, 8.1p1 on 2022
Client
OpenSSH on macOS 27
Date
October 2026

New articles, by email.

A short note when something new is published.