This is a guide that shows you how to get a publicly trusted wildcard certificate at no cost from Let’s Encrypt using PowerShell.
Requirements:
- Windows PowerShell 5.1
- .NET Framework 4.7.2 (link to check)
- Possibility to add CNAME in DNS
Step by step
Start PowerShell as admin (see information below for non-admin steps)
Verify that PowerShell’s ExecutionPolicy allows running scripts (i.e. RemoteSigned or less)
Otherwise: Set-ExecutionPolicy RemoteSigned
Run:
Install-Module -Name Posh-ACME
Accept warnings about untrusted repositories (that is, if you accept PSGallery, a common module repository):
Run:
New-PACertificate *.tomdemo.se -AcceptTOS -Contact <your-email> -DnsPlugin AcmeDns -PluginArgs @{ACMEServer='auth.acme-dns.io'} -Install
Explanation of the options used:
*.tomdemo.se | The name you want in the certificate. You can add additional comma-separated names |
AcceptTOS | Indicates that you accept the Let’s Encrypt Terms of Service (see https://letsencrypt.org/documents/LE-SA-v1.2-November-15-2017.pdf) |
Contact | Email for expiration notification (optional) |
DnsPlugin | Which DNS plugin should be used for automatic domain ownership validation. Since my DNS provider Loopia isn’t natively supported by Posh-ACME, I used the ACMEDns option, which requires you to manually add a CNAME record in your DNS provider once, and that can be reused when updating the certificate. Here is a list of DNS providers supported by Posh-ACME: https://github.com/rmbolger/Posh-ACME/wiki/List-of-Supported-DNS-Providers |
PluginArgs | Options that depends on chosen DNSPlugin |
Install | This option will install the certificate in the computer’s Certificate Store (requires admin permission, see Getting certificate without admin permission below) |
Do not close the PowerShell window!
Add the CNAME record shown in the output of the command you just ran in the DNS registrar for the domain.
Here is an example from Swedish DNS registrar Loopia, but your DNS registrar interface may look different:
Go back to the PowerShell window and press enter to continue.
The script will wait 2 minutes for DNS to propagate:
After that, you should get the certificate:
To see more information about the certificate, you can use the following command:
Get-PACertificate | Format-List
Here you can see basic information about the certificate and that all the relevant files are stored in %LOCALAPPDATA%\Posh-ACME folder, and that it includes a PFX-file if you want to install the certificate on another machine. The default PFX-password is “poshacme”. You can specify your own with the option -PfxPass when running the New-PACertificate command.
Go to the Local Computer certificate store (run certlm.msc) and verify that the certificate has been installed correctly:
Depending on what service you are using the certificate for, you may need to make extra configuration steps in the service to start using the certificate.
You can manually renew the certificate by running the following command:
Submit-Renewal
As you can see, it will not renew certificates that are not about to expire yet (I believe it uses 30 days or less validity time). You can override this by running:
Submit-Renewal -Force
To automate the renewal, you can create a scheduled task that runs this command daily:
Create a file called C:\Cert\AutoRenewal.ps1, containing the command “Submit-Renewal” (not the -Fore option, since you don’t want to renew at every check).
Run the following commands, but first change <password> to your own password
Note: The scheduled task must run in the context of the user requesting the certificate since validation information is stored in that user’s profile.
$Trigger = New-ScheduledTaskTrigger -At 10:00am -Daily $Action= New-ScheduledTaskAction -Execute "PowerShell.exe" -Argument "C:\Cert\AutoRenewal.ps1" Register-ScheduledTask -TaskName "Certificate AutoRenewal" -Trigger $Trigger -User "$env:USERDOMAIN\$env:USERNAME" -Password '<password>' -Action $Action -RunLevel Highest –Force
Test certificates
For testing, you can switch the Let’s Encrypt server you send your requests to. The test server does not create a publicly trusted certificate but has no rate limiting.
Read more about rate limiting here: https://letsencrypt.org/docs/rate-limits/
To use test server:
Set-PAServer LE_STAGE
To use production server:
Set-PAServer LE_PROD
It will keep using the specified server until you change it again.
Getting certificate without admin permission
Most steps above work without admin permission, with the exception of installing the certificate in the Computer certificate store.
You might need to restrict the scoop of these commands as well:
Set-ExecutionPolicy RemoteSigned -Scope CurrentUser Install-Module -Name Posh-ACME -Scope CurrentUser
Then exclude the -Install option in the New-PACertificate command example above.
You will still get a valid publicly trusted certificate, and you can move the created pfx-file to a computer where you want to install it (where you are admin).
Custom Acme-DNS instance
In my example above, I use the public ACME-Dns service. The advantage of that is that your DNS provider does not have to support API access for the Domain Verification part. Instead, you manually create a CNAME record in your DNS provider once that redirects the DNS validation to ACME-Dns.
To increase security, you should use your own instance of Acme-DNS, see here: https://github.com/joohoi/acme-dns