A toolkit for automating SSL certificate management on Windows Servers (2012+) using Let's Encrypt via win-acme.
- IIS - Automatic HTTPS binding for websites
- RD Gateway - Remote Desktop Gateway SSL certificates
- LDAPS - Domain Controller LDAP over SSL
Download the latest signed release from GitHub Releases:
- Download
wincertmanager-x.x.x.zipandwincertmanager-x.x.x.zip.sha256 - Verify the SHA256 checksum
- Extract to
C:\Tools\wincertmanager(or your preferred location) - (Optional) To trust the toolkit's code-signing certificate for signature validation:
Note: Using
Import-Certificate -FilePath C:\Tools\wincertmanager\certs\rwts-codesign.cer -CertStoreLocation Cert:\LocalMachine\Root
LocalMachine\Rootensures full trust for signature validation. TheLocalMachinestore ensures the SYSTEM account (used for scheduled renewals) also trusts the certificate.
# Run prerequisites check and installation
.\scripts\Prerequisites\Install-Prerequisites.ps1This will:
- Check Windows version and requirements
- Enable TLS 1.2 if needed
- Verify .NET Framework version
- Download and install win-acme to
C:\Tools\win-acme - Create renewal scheduled task
Custom install path:
.\scripts\Prerequisites\Install-Prerequisites.ps1 -InstallPath "$env:ProgramFiles\win-acme"# Register domain with acme-dns
.\scripts\AcmeDns\Register-AcmeDns.ps1 -Domain "server.example.com"
# Add the CNAME record shown in the output to your DNS provider
# _acme-challenge.server.example.com -> <subdomain>.auth.acme-dns.ioExample for LDAPS on a Domain Controller:
C:\Tools\win-acme\wacs.exe `
--source manual --host dc01.example.com `
--validation script `
--dnscreatescript "C:\Tools\wincertmanager\scripts\AcmeDns\Update-AcmeDnsTxt.ps1" `
--dnscreatescriptarguments "create {Identifier} {RecordName} {Token}" `
--store certificatestore --certificatestore My `
--installation script `
--script "C:\Tools\wincertmanager\scripts\PostRenewal\Update-LDAPS.ps1" `
--scriptparameters "-Thumbprint {CertThumbprint} -TestConnection" `
--accepttos --emailaddress admin@example.comSee Service-Specific Notes for IIS and RD Gateway examples.
wincertmanager/
├── scripts/
│ ├── Prerequisites/ # Server preparation and win-acme installation
│ │ ├── Install-Prerequisites.ps1
│ │ └── Test-ServerReadiness.ps1
│ ├── AcmeDns/ # acme-dns registration and credential management
│ │ ├── Register-AcmeDns.ps1
│ │ ├── Get-AcmeDnsCredential.ps1
│ │ └── Update-AcmeDnsTxt.ps1 # DNS validation script for win-acme
│ ├── PostRenewal/ # Service-specific certificate binding scripts
│ │ ├── Update-RDGateway.ps1
│ │ └── Update-LDAPS.ps1
│ ├── Logging/ # Central logging functionality
│ │ └── Send-CertificateEvent.ps1
│ └── Helpers/ # Shared functions
│ └── Common.ps1
├── config/ # Configuration templates
│ ├── logging-config.example.json
│ ├── acme-dns/
│ └── cloudflare/
├── docs/ # Setup guides
│ ├── customer-onboarding.md
│ ├── iis-setup.md
│ ├── rdgateway-setup.md
│ ├── ldaps-setup.md
│ └── troubleshooting.md
└── examples/ # win-acme configuration examples
├── win-acme-iis.txt
├── win-acme-rdgateway.txt
└── win-acme-ldaps.txt
| Requirement | Minimum | Recommended |
|---|---|---|
| Windows Server | 2012 | 2016+ |
| .NET Framework | 4.6.2 | 4.7.2+ |
| PowerShell | 5.0 | 5.1 |
acme-dns delegates only the ACME challenge subdomain, providing:
- No full DNS provider access needed
- Works with any DNS provider supporting CNAME
- Simple one-time CNAME setup
- Works reliably on Domain Controllers and internal servers
Public acme-dns server: https://auth.acme-dns.io
You can also run your own acme-dns server or use a third-party hosted one.
-
Register with acme-dns:
# Using the public acme-dns server (default) .\scripts\AcmeDns\Register-AcmeDns.ps1 -Domain "server.example.com" # Or specify a custom acme-dns server with API authentication .\scripts\AcmeDns\Register-AcmeDns.ps1 -Domain "server.example.com" ` -AcmeDnsServer "https://acme-dns.example.com" ` -ApiKey "your-api-key" -ApiKeyId "your-key-id"
-
Add the CNAME record shown in the output to your DNS:
_acme-challenge.server.example.com. CNAME <subdomain>.auth.acme-dns.io. -
Request certificate using the script validation method (see examples below)
This toolkit uses script-based DNS validation with win-acme rather than win-acme's built-in acme-dns plugin. This approach:
- Works reliably in unattended/automated scenarios
- Uses WinCertManager's secure DPAPI-encrypted credential storage
- Avoids issues with win-acme's preliminary DNS validation on Domain Controllers
The Update-AcmeDnsTxt.ps1 script reads the acme-dns server URL from the stored credentials, so it works with any acme-dns server you registered with.
Direct CloudFlare API integration:
- Requires CloudFlare-managed DNS
- Create API token with Zone > DNS > Edit permission
- Automatic record creation/cleanup
win-acme has native IIS support. No post-renewal script needed - win-acme handles binding updates automatically.
wacs.exe --source iis --siteid 1 `
--validation script `
--dnscreatescript "C:\Tools\wincertmanager\scripts\AcmeDns\Update-AcmeDnsTxt.ps1" `
--dnscreatescriptarguments "create {Identifier} {RecordName} {Token}" `
--installation iisRequires post-renewal script to update SSL binding:
wacs.exe --source manual --host gateway.example.com `
--validation script `
--dnscreatescript "C:\Tools\wincertmanager\scripts\AcmeDns\Update-AcmeDnsTxt.ps1" `
--dnscreatescriptarguments "create {Identifier} {RecordName} {Token}" `
--store certificatestore --certificatestore My `
--installation script `
--script "C:\Tools\wincertmanager\scripts\PostRenewal\Update-RDGateway.ps1" `
--scriptparameters "-Thumbprint {CertThumbprint} -RestartService"Active Directory automatically detects certificates with Server Authentication EKU. The post-renewal script verifies configuration:
wacs.exe --source manual --host dc01.example.com `
--validation script `
--dnscreatescript "C:\Tools\wincertmanager\scripts\AcmeDns\Update-AcmeDnsTxt.ps1" `
--dnscreatescriptarguments "create {Identifier} {RecordName} {Token}" `
--store certificatestore --certificatestore My `
--installation script `
--script "C:\Tools\wincertmanager\scripts\PostRenewal\Update-LDAPS.ps1" `
--scriptparameters "-Thumbprint {CertThumbprint} -TestConnection"Note: Internal-only domains (.local) cannot use Let's Encrypt. Use a publicly resolvable domain (e.g., dc01.internal.example.com where example.com is a real domain you control).
All certificate events are logged to Windows Event Log:
- Source:
WinCertManager - Log: Application
Configure config/logging-config.json for:
- Webhook notifications (HTTP POST)
- Syslog forwarding (UDP/TCP)
Run the readiness check:
.\scripts\Prerequisites\Test-ServerReadiness.ps1 -DetailedWhen running on a Domain Controller or server using internal DNS, win-acme's preliminary DNS validation may fail because the internal DNS cannot resolve external acme-dns subdomains.
Symptom: Win-acme shows "Preliminary validation failed" even though the TXT record was created successfully.
Solution: Configure win-acme to use public DNS servers for validation. Edit C:\Tools\win-acme\settings.json:
"Validation": {
"DnsServers": [ "8.8.8.8", "1.1.1.1" ],
...
}This tells win-acme to use Google/Cloudflare DNS for checking TXT records instead of the system's DNS.
See docs/troubleshooting.md for more common issues.
| Guide | Description |
|---|---|
| Customer Onboarding | Setup guide and decision tree |
| IIS Setup | IIS certificate automation |
| RD Gateway Setup | Remote Desktop Gateway certificates |
| LDAPS Setup | Domain Controller LDAPS certificates |
| Troubleshooting | Common issues and solutions |
| Component | Default Location | Configurable |
|---|---|---|
| win-acme | C:\Tools\win-acme |
Yes (-InstallPath) |
| win-acme Config | %ProgramData%\win-acme |
Via win-acme settings |
| WinCertManager Toolkit | C:\Tools\wincertmanager |
Manual (copy anywhere) |
| WinCertManager Config | %ProgramData%\WinCertManager\Config |
No |
| WinCertManager Logs | %ProgramData%\WinCertManager\Logs |
No |
Certificates are renewed automatically:
- Scheduled task runs daily at 9:00 AM
- Renewal triggered when < 30 days remain
- Let's Encrypt certificates valid for 90 days
Check scheduled task status:
Get-ScheduledTask -TaskName "win-acme renew" | Get-ScheduledTaskInfo- DNS Validation: Preferred over HTTP-01 for internal servers
- Credential Storage: DPAPI encryption for acme-dns credentials
- API Tokens: Use minimal permissions (zone-specific, DNS Edit only)
- Private Keys: Stored in Windows certificate store with appropriate ACLs
This toolkit is maintained by Real World Technology Solutions.
This project is licensed under CC BY-NC 4.0 (Creative Commons Attribution-NonCommercial 4.0).
- Free for non-commercial use with attribution
- Commercial use requires permission from Real World Technology Solutions