Security

Install a trusted TLS certificate for Remote Desktop

Replace the self-signed Remote Desktop certificate with a CA-issued one, bind it to the RDP listener with PowerShell, connect by hostname on port 3389 and plan renewals.

AdvancedWindows server5 min read

Windows protects Remote Desktop with a self-signed certificate, which is why every new client shows an identity warning. If you install a certificate from a trusted authority and connect by its hostname, the warning disappears and clients can verify the server properly. This guide covers the requirements, importing the certificate, binding it to the RDP listener with PowerShell, and keeping it renewed.

Before you start

  • A Windows VPS running Windows Server 2019, 2022 or 2025, with an Administrator account.
  • A hostname, such as rdp.example.com, with a DNS A record pointing to your server IP. You connect as rdp.example.com:3389.
  • A certificate for that exact hostname, issued by a public certificate authority. It can be a commercial certificate or a free one from an ACME client such as win-acme.
  • The certificate as a .pfx file with its private key, or already in the server's Local Computer → Personal store.
  • The browser console from your VPS provider's control panel as a fallback in case Remote Desktop stops accepting connections.

Warning: A wrong binding, or a certificate whose private key Remote Desktop cannot read, can stop RDP from accepting new connections. Keep your current session open while you work and know how to open the browser console.

Check the certificate meets the requirements

Remote Desktop accepts a certificate only if:

  • The subject or a Subject Alternative Name matches the hostname clients use, for example rdp.example.com.
  • It includes the Server Authentication enhanced key usage.
  • It has a private key on the server.
  • It sits in the Local Computer certificate store, not the user store.
  • It is within its validity dates.

Import the certificate

If you have a .pfx file, copy it to the server (for example to C:\certs\rdp.pfx) and import it in an elevated PowerShell window:

PowerShell
$pw = Read-Host -AsSecureString -Prompt 'PFX password'
Import-PfxCertificate -FilePath C:\certs\rdp.pfx -CertStoreLocation Cert:\LocalMachine\My -Password $pw

The output shows the new certificate's Thumbprint. You can list certificates for your hostname at any time:

PowerShell
Get-ChildItem Cert:\LocalMachine\My |
  Where-Object Subject -like '*rdp.example.com*' |
  Format-List Subject, Thumbprint, NotAfter, HasPrivateKey

Confirm HasPrivateKey: True. Delete the .pfx file from the server once it is imported.

Give Remote Desktop access to the private key

The Remote Desktop service runs as NETWORK SERVICE and must be able to read the private key.

  1. Press Win + R, type certlm.msc and press Enter.
  2. Open Personal → Certificates and find your certificate.
  3. Right-click it and choose All Tasks → Manage Private Keys.
  4. Click Add, type NETWORK SERVICE, click Check Names, then OK.
  5. Give it Read permission only and click OK.

Bind the certificate to the RDP listener

Copy the thumbprint without spaces. Then set it on the RDP listener:

PowerShell
$thumb = 'PASTE_THUMBPRINT_HERE'
$ts = Get-CimInstance -Namespace root\cimv2\TerminalServices -ClassName Win32_TSGeneralSetting -Filter "TerminalName='RDP-Tcp'"
Set-CimInstance -InputObject $ts -Property @{ SSLCertificateSHA1Hash = $thumb }

Read it back to confirm:

PowerShell
Get-CimInstance -Namespace root\cimv2\TerminalServices -ClassName Win32_TSGeneralSetting -Filter "TerminalName='RDP-Tcp'" |
  Select-Object SSLCertificateSHA1Hash

The value should match your thumbprint. New connections use the new certificate. Your current session stays connected.

Note: This changes only the certificate. Port 3389 and its firewall rule stay exactly as they were.

Connect by hostname

From your PC, connect to the name on the certificate, not the IP:

PowerShell
mstsc /v:rdp.example.com:3389

If you connect by IP, the name will not match and the warning returns. Update saved .rdp files and connection managers to use the hostname.

Plan renewals

Certificates expire, and Remote Desktop does not swap in a renewed certificate on its own. The renewed certificate has a new thumbprint, so you must bind it again.

  • Commercial certificates: set a calendar reminder well before the expiry date. Import the new certificate, grant key access and run the binding commands again.
  • ACME certificates (win-acme and similar): these are short-lived and renew automatically. Configure the client to run a post-renewal script that grants key access and rebinds the new thumbprint. Check your ACME client's documentation for its script options.
  • Check expiry dates from time to time:
PowerShell
  Get-ChildItem 'Cert:\LocalMachine\My' | Where-Object Subject -like '*rdp.example.com*' | Select-Object NotAfter, Thumbprint

If the bound certificate is deleted or expires, clients see errors or warnings again, so remove old certificates only after the new one is bound.

Check it works

  1. Connect from a PC that has never connected before, using rdp.example.com:3389.
  2. You should go straight to the credentials prompt with no identity warning.
  3. In the session, run the read-back command above and confirm the thumbprint.

Troubleshooting

  • New connections fail right after binding: Remote Desktop cannot read the private key. Repeat the key access step for NETWORK SERVICE, using the browser console if needed.
  • Warning still says the name does not match: you are connecting by IP or by a different name. Use the exact hostname on the certificate.
  • Set-CimInstance reports invalid parameter: the thumbprint has spaces or hidden characters. Retype it, or copy it from Get-ChildItem output.
  • Warning returned after a few months: the certificate was renewed but not rebound. Bind the new thumbprint.

Next steps

Was this guide helpful?

Still stuck?

Ask MdmHost AI for a quick answer, or open a ticket and our team will take a look. We are here 24/7.