Posh-ACME is a free PowerShell tool that helps you automatically get, renew, and manage SSL/TLS certificates for your websites and servers. Think of an SSL certificate as the digital ID that makes your website secure (the little padlock icon in browsers). Normally, getting and renewing these certificates is a manual, time-consuming process. Posh-ACME does it all for you automatically.
This guide will walk you through every step needed to install and set up Posh-ACME on your computer, whether you're using Windows, Linux, or macOS. No prior experience is required — just follow the steps in order.
|
?? What You Will Achieve By the end of this guide, you will have Posh-ACME installed, connected to your DNS provider (Cloudflare), and registered with the SSL certificate authority (ACME server) — ready to issue real SSL certificates. |
Here is a summary of what this guide covers:
| Topic | Details |
|---|---|
| Supported Operating Systems | Windows 10/11, Windows Server 2016+, Linux (Ubuntu, CentOS, RHEL), macOS |
| Required PowerShell Version | Windows: PowerShell 5.1 or newer | Linux/macOS: PowerShell Core 7 or newer |
| DNS Provider Used in This Guide | Cloudflare (Posh-ACME also supports 50+ other DNS providers) |
| Certificate Authority | Custom ACME server with EAB (External Account Binding) authentication |
| Validation Method | DNS-01 — Automatically creates DNS records to prove domain ownership |
Before starting the installation, make sure you have the following ready. Think of this as your checklist before cooking — gather all ingredients first!
You will need to collect the following items before starting. Ask your IT admin or DNS provider if you don't have them:
|
?? Don't have EAB credentials? Contact your ACME server administrator. They will provide you with the EAB Key ID, HMAC Key, and server URL. Without these, you cannot register for certificates. |
PowerShell is the tool that runs Posh-ACME. Windows users likely already have it. Linux and macOS users will need to install PowerShell Core 7. Follow only the section that applies to your operating system.
Open PowerShell (on Windows, search for 'PowerShell' in the Start menu) and type the following command, then press Enter:
$PSVersionTable.PSVersion
You should see output like this:
Major Minor Patch PreReleaseLabel BuildLabel
----- ----- ----- --------------- ----------
7 4 0
If the Major version number shows 7 or higher (for Linux/macOS) or 5.1 or higher (for Windows), you're good to go! Skip to Part 2. If not, follow the installation steps below for your operating system.
Open your Linux terminal and run the following commands one by one. Copy each line exactly as shown and press Enter after each one:
| Step | Description & Command |
|---|---|
| Step 1 |
Update your system's package listsudo apt-get update |
| Step 2 |
Install required helper toolssudo apt-get install -y wget apt-transport-https software-properties-common |
| Step 3 |
Download Microsoft's repository signing keywget -q "https://packages.microsoft.com/config/ubuntu/$(lsb_release -rs)/packages-microsoft-prod.deb" |
| Step 4 |
Register the Microsoft repositorysudo dpkg -i packages-microsoft-prod.deb |
| Step 5 |
Delete the downloaded key file (no longer needed)rm packages-microsoft-prod.deb |
| Step 6 |
Update the package list againsudo apt-get update |
| Step 7 |
Install PowerShellsudo apt-get install -y powershell |
| Step 8 |
Start PowerShellpwsh |
Open your terminal and run these commands:
| Step | Description & Command |
|---|---|
| Step 1 |
Register the Microsoft repositorycurl https://packages.microsoft.com/config/rhel/8/prod.repo | sudo tee /etc/yum.repos.d/microsoft.repo |
| Step 2 |
Install PowerShellsudo yum install -y powershell |
| Step 3 |
Start PowerShellpwsh |
You'll need Homebrew installed. If you don't have it, visit https://brew.sh to install it first. Then run:
| Step | Description & Command |
|---|---|
| Step 1 |
Install PowerShell using Homebrewbrew install --cask powershell |
| Step 2 |
Start PowerShellpwsh |
After installation on any platform, confirm it's working by checking the version:
pwsh --version
Expected result:
PowerShell 7.4.0
| ? PowerShell installed and verified successfully! |
Now that PowerShell is ready, we'll install the Posh-ACME module. A 'module' is like a plugin — it adds new features to PowerShell.
There are two ways to install it. Choose the option that matches your situation:
Install-Module -Name Posh-ACME -Scope CurrentUser -Force
On Windows (run PowerShell as Administrator):
Install-Module -Name Posh-ACME -Scope AllUsers -Force
On Linux or macOS (use sudo):
sudo pwsh -Command "Install-Module -Name Posh-ACME -Scope AllUsers -Force"
|
?? Trusted Repository Warning If PowerShell asks: 'Are you sure you want to install from an untrusted repository?' — this is normal. Type A and press Enter to accept and continue. This just means the repository hasn't been manually marked as trusted on your machine. |
Run these commands to confirm Posh-ACME is installed correctly:
# Check that the module is listed
Get-Module -Name Posh-ACME -ListAvailable
# Load the module into this session
Import-Module Posh-ACME
# See all available commands
Get-Command -Module Posh-ACME
# Check the version number
(Get-Module Posh-ACME).Version
You should see output similar to this:
ModuleType Version Name ExportedCommands
---------- ------- ---- ----------------
Script 4.23.0 Posh-ACME {Add-DnsTxt, Complete-PAOrder, Export-PAAccountKey ...}
You'll need this file path in the next step. Run this command to find it:
$modulePath = (Get-Module Posh-ACME -ListAvailable).ModuleBase
Write-Host "Posh-ACME installed at: $modulePath"
The path will look something like these depending on your operating system:
| ? Posh-ACME module installed and verified! |
|
?? Do Not Skip This Step! By default, Posh-ACME will wait only 2 minutes for the certificate authority to respond. Some ACME servers take longer than that. If you skip this step, your certificate requests may fail with a timeout error even though everything is set up correctly. |
We need to edit one file inside Posh-ACME to increase the waiting time from 2 minutes to 10 minutes. Don't worry — this is a simple text change.
Run this command in PowerShell. It will show you the full path to the file:
$modulePath = (Get-Module Posh-ACME -ListAvailable).ModuleBase
$finalizeScript = Join-Path $modulePath "Public\Submit-OrderFinalize.ps1"
Write-Host "Script location: $finalizeScript"
Make note of the path it shows — you'll need it in the next step.
Before changing anything, always make a backup. This command copies the file and adds '.backup' to the copy's name:
Copy-Item $finalizeScript "$finalizeScript.backup" -Force
Write-Host "Backup created!"
Choose the command that matches your operating system:
On Windows:
notepad $finalizeScript
# Or if you have VS Code installed:
code $finalizeScript
On Linux:
nano $finalizeScript
# Or:
vim $finalizeScript
On macOS:
nano $finalizeScript
# Or:
code $finalizeScript
Inside the file, scroll down to around line 200–250 and look for these two lines.
What you will see (the original/default settings):
$maxRetries = 12 # Default: 12 attempts
$retrySleep = 10 # Default: 10 seconds between attempts
# Total timeout: 12 x 10 = 120 seconds (just 2 minutes)
Change $maxRetries from 12 to 60 so it looks like this:
$maxRetries = 60 # Changed: 60 attempts
$retrySleep = 10 # Keep this the same: 10 seconds between attempts
# Total timeout: 60 x 10 = 600 seconds (10 minutes)
|
?? Important Only change the number after '$maxRetries ='. Change 12 to 60. Do not change any other part of the file. |
Alternative option — 15-minute timeout with more frequent checks (advanced users):
$maxRetries = 180 # 180 attempts
$retrySleep = 5 # 5 seconds between attempts
# Total: 180 x 5 = 900 seconds (15 minutes)
Save the file and close the editor.
Run this command to double-check that your changes are in the file:
Select-String -Path $finalizeScript -Pattern "maxRetries|retrySleep" -Context 1,1
You should see:
> $maxRetries = 60
> $retrySleep = 10
| ? Timeout increased to 10 minutes — Posh-ACME will now wait longer for responses! |
Posh-ACME needs permission to automatically add and remove DNS records in your Cloudflare account. It does this using an API Token — a special password that gives it exactly the permissions it needs, nothing more.
Follow these steps in the Cloudflare website:
Now set the token permissions. Make sure these are selected:
Under Zone Resources:
|
?? Save Your Token Now! The token is a 40-character code that looks like: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX. Copy it to a safe place right now. Once you leave this page, Cloudflare will never show it again. |
Let's make sure the token can actually talk to Cloudflare. Open PowerShell and run this code (replace the X's with your actual token):
# Paste your actual Cloudflare API token here
$cfToken = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
# Build the request headers
$headers = @{
'Authorization' = "Bearer $cfToken"
'Content-Type' = 'application/json'
}
# Send a test request
try {
$response = Invoke-RestMethod -Method Get `
-Uri "https://api.cloudflare.com/client/v4/zones" `
-Headers $headers
if ($response.success) {
Write-Host "Token is valid! Your accessible zones:"
$response.result | ForEach-Object { Write-Host " - $($_.name)" }
}
} catch {
Write-Host "Token test failed: $($_.Exception.Message)"
}
If successful, you'll see your domain names listed. If it fails, double-check the token was copied correctly.
| ? Cloudflare API token created and tested! |
Now we'll connect Posh-ACME to the certificate authority (the ACME server) that will issue your SSL certificates. You'll use the EAB credentials your administrator provided.
Tell Posh-ACME which certificate server to use. Replace the URL with the one your ACME admin gave you:
# Replace with your actual ACME server URL
Set-PAServer -DirectoryUrl "https://acme.https.in/acme/directory"
# Check the connection was successful
Get-PAServer | Format-List
If connected successfully, you'll see details about the server:
location : https://acme.https.in/acme/directory
status : Valid
nonce : https://acme.https.in/acme/new-nonce
newAccount : https://acme.https.in/acme/new-account
newOrder : https://acme.https.in/acme/new-order
Now register your account. Replace all the placeholder values (the X's) with your actual EAB credentials from your administrator:
# Your EAB Key ID (40 characters) --- from your ACME admin
$eabKeyId = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
# Your HMAC Key (64 characters) --- from your ACME admin
$eabHmacKey = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
# Your email address
$email = "yourname@example.com"
# Register your account
New-PAAccount -Contact $email -ExtAcctKID $eabKeyId -ExtAcctHMACKey $eabHmacKey -AcceptTOS
# Verify account was created
Get-PAAccount | Format-List
A successful registration will show:
id : https://acme.https.in/acme/acct/ACCOUNT_TOKEN
status : valid
contact : {mailto:yourname@example.com}
| ? ACME account registered and active! |
Instead of typing your credentials every time you open PowerShell, we'll create a configuration file that stores everything and loads it automatically.
Run this script to save all your settings to a file. Replace each placeholder value with your actual credentials:
# Where to save the configuration
$configPath = "$HOME\.poshacme-config.ps1"
# Create the file with your credentials
@"
# Posh-ACME Configuration File
`$acmeServer = "https://acme.https.in/acme/directory"
`$eabKeyId = "YOUR_EAB_KEY_ID_HERE"
`$eabHmacKey = "YOUR_HMAC_KEY_HERE"
`$email = "yourname@example.com"
`$cfToken = "YOUR_CLOUDFLARE_TOKEN_HERE"
# Connect to ACME server
Set-PAServer -DirectoryUrl `$acmeServer
# Set up Cloudflare plugin credentials
`$pArgs = @{
CFToken = (`$cfToken | ConvertTo-SecureString -AsPlainText -Force)
}
Write-Host "Configuration loaded!"
"@ | Out-File -FilePath $configPath -Encoding UTF8
Write-Host "Configuration saved to: $configPath"
Every time you open a new PowerShell session, load your settings with this single command:
. "$HOME\.poshacme-config.ps1"
If you want PowerShell to automatically load your settings every time it opens:
Step 3a: Open your PowerShell profile file
notepad $PROFILE
Step 3b: Add this line to the file
. "$HOME\.poshacme-config.ps1"
Step 3c: Save and close
Save the file and close Notepad. From now on, your Posh-ACME settings will load automatically every time you start PowerShell.
| ? Configuration saved and ready to use! |
This guide uses Cloudflare, but Posh-ACME supports more than 50 DNS providers. Here are the setup snippets for other popular providers. Use the one that matches your DNS host.
# First, install the AWS PowerShell module
Install-Module -Name AWS.Tools.Route53 -Scope CurrentUser -Force
# Then set up your credentials
$pArgs = @{
R53AccessKey = "YOUR_AWS_ACCESS_KEY"
R53SecretKey = "YOUR_AWS_SECRET_KEY" | ConvertTo-SecureString -AsPlainText -Force
}
# Install the Azure DNS module
Install-Module -Name Az.Dns -Scope CurrentUser -Force
# Log in to Azure
Connect-AzAccount
# Set up credentials
$pArgs = @{
AZSubscriptionId = "YOUR_SUBSCRIPTION_ID"
AZResourceGroup = "your-resource-group-name"
}
# Install Google Cloud module
Install-Module -Name GoogleCloud -Scope CurrentUser -Force
$pArgs = @{
GCloudKeyFile = "C:\path\to\your\service-account-key.json"
}
$pArgs = @{
GDKey = "YOUR_GODADDY_API_KEY"
GDSecret = "YOUR_GODADDY_SECRET" | ConvertTo-SecureString -AsPlainText -Force
}$pArgs = @{
DOToken = "YOUR_DIGITALOCEAN_TOKEN" | ConvertTo-SecureString -AsPlainText -Force
}|
?? Full list of supported DNS providers Visit https://poshac.me/docs/v4/Plugins/ to see all 50+ supported DNS providers with setup instructions. |
Let's run a quick check to make sure all pieces are connected and working together before you start issuing certificates.
# Load your configuration
. "$HOME\.poshacme-config.ps1"
# Check ACME server connection
Get-PAServer | Select-Object location, status
# Check your ACME account
Get-PAAccount | Select-Object id, status, contact
# Test server connectivity
Test-PAServer -Verbose
If something doesn't work, check the table below for your error and its solution.
| Problem / Error | Solution |
|---|---|
| PowerShell command 'pwsh' not found | PowerShell is not installed or not in the system PATH. Reinstall PowerShell using the steps in Part 1. |
| Module installation fails with permission error | Run PowerShell as Administrator (Windows) or use sudo (Linux/macOS). See Step 1 of Part 2. |
| 'Cannot load module' or execution policy error | Run: Set-ExecutionPolicy RemoteSigned -Scope CurrentUser -Force — then try importing the module again. |
| Cloudflare API token test returns 'failed' | The token may have been copied incorrectly or has the wrong permissions. Recreate it in Cloudflare with Zone ? DNS ? Edit and Zone ? Zone ? Read permissions. |
| EAB registration fails: 'Invalid account binding signature' | Check that your EAB Key ID is exactly 40 characters and HMAC Key is exactly 64 characters. Make sure there are no spaces before or after. Also verify the ACME server URL is correct. |
| Certificate request times out after 2 minutes | You likely skipped Part 3. Go back and change $maxRetries from 12 to 60 in Submit-OrderFinalize.ps1. |
Use this checklist to confirm you've completed every step before moving on to issuing certificates:
| ? | PowerShell version checked or installed (v5.1+ on Windows, v7+ on Linux/macOS) |
| ? | Posh-ACME module installed and verified (version shown when listed) |
| ? | Timeout increased in Submit-OrderFinalize.ps1 ($maxRetries changed to 60) |
| ? | Cloudflare API token created with correct DNS edit permissions |
| ? | Cloudflare API token tested successfully (zones listed in output) |
| ? | ACME server URL set using Set-PAServer |
| ? | ACME account registered with EAB credentials (status shows 'valid') |
| ? | Configuration file created and tested |
Congratulations — you have completed the Posh-ACME installation! Your system is now fully set up to issue and renew SSL certificates automatically.
|
?? Continue to the Deployment Guide See the Deployment Guide (DEPLOYMENT_GUIDE.md) to learn how to actually request your first SSL certificate, set up automatic renewal, and manage multiple domains. |