Hi. I have a domain on DuckDNS and I have to create certs using DNS-01 method by updating the TXT field on my domain. It is the only way in my situation.
In order to automate DNS challenge requests (via TXT records), you will need to use an ACME client that supports it and a DNS service provider that also supports DNS TXT record updates (via API).
DuckDNS should be one such DNS service provider.
And Win-Acme should be one such ACME client.
So, I think you have all (the tools) that you needs to get this done.
DuckDNS has the added complication that there can only ever be a single TXT record associated with all domains on your account. So whatever client you're using that supports modifying DuckDNS records also needs to support validating challenges serially rather than in parallel.
Coincidentally, Posh-ACME could work if you're okay dealing with PowerShell. Here's a link to the plugin guide specifically for DuckDNS.
As win-acme supports DNS scripting via batch files you can also (technically) use the Posh-ACME script for DuckDNS to perform the Duck DNS updates via win-acme.
Incidentally Ryan, it would be really great if you had an official script/strategy to setup calling any of the Posh-ACME dns plugins outside of the Posh-ACME workflow itself (given an existing copy of Posh-ACME). As you know Certify The Web does this already but it looks like win-acme could benefit from the same strategy and it would remove the likelihood of script forks appearing like this : Create EasyDNS.ps1 by Legacy777 · Pull Request #1832 · win-acme/win-acme · GitHub
The DNS providers in Posh-ACME are a real gem, so with a wrapper script any other things like certbot on linux could also use them.
The script that Certify The Web generates to call Posh-ACME plugins could be better (I'm no powershell whizz) but it looks a bit like this:
$PoshACMERoot = "C:\Somewhere\PoshACME"
$Public = @( Get-ChildItem -Path $PoshACMERoot\Public\*.ps1 -ErrorAction Ignore )
$Private = @( Get-ChildItem -Path $PoshACMERoot\Private\*.ps1 -ErrorAction Ignore )
# Add-Type -Path "$($PoshACMERoot)\..\..\..\BouncyCastle.Crypto.dll"
# Dot source the files (in the same manner as Posh-ACME would)
Foreach($import in @($Public + $Private))
{
Try { . $import.fullname }
Catch
{
Write-Error -Message "Failed to import function $($import.fullname): $_"
}
}
# Replace Posh-ACME specific methods which don't apply when we're using them
function Export-PluginVar {
[CmdletBinding()]
param(
[Parameter(Mandatory,Position=0)]
[string]$VarName,
[Parameter(Mandatory,Position=1)]
[object]$VarValue
)
}
$script:UseBasic = @{}
if ('UseBasicParsing' -in (Get-Command Invoke-WebRequest).Parameters.Keys) { $script:UseBasic.UseBasicParsing = $true }
. $PoshACMERoot + "\Plugins\EasyDNS.ps1"
$PluginArgs= @{EDToken='test'; EDKey='test'; EDUseSandbox=$false}
Add-DnsTxt -RecordName '_acme-challenge.domain.com' -TxtValue '350QEvKeIHNz0MBtfi2ZBXoaDX3lQHzmVZwWaEOb4pA' @PluginArgs
To be fair, I've generally tried to make the plugins as dependency free as possible. I spent a ton of time on Route53 and Azure in particular implementing the raw REST calls necessary to make the associated vendor modules unnecessary. But yeah, I haven't spent much time thinking about or documenting how to use the plugins outside the context of the module since I'd (rightfully? selfishly?) rather folks just use the module.
In any case, now that I am thinking about it...most of the beginning of your script dot sourcing the module files and importing BouncyCastle shouldn't actually be necessary. But if you want the module-specific functions available, it might be easier to just Import-Module -Name path\to\Posh-ACME.psd1.
The fake Export-PluginVar definition is only currently needed for 3 (AcmeDns, Azure, and GCloud) of the ~50 plugins and you should also define Import-PluginVar to go with it. But both could probably be simplified to this:
function Export-PluginVar { param([Parameter(ValueFromRemainingArguments)]$DumpArgs) }
function Import-PluginVar { param([Parameter(ValueFromRemainingArguments)]$DumpArgs) }
For the rest of the plugins, the only prereqs that should be needed are the $script:UseBasic hashtable and dot sourcing the specific plugin file. I've got a rant for another time about why $script:UseBasic is even necessary.
Thanks Ryan, much appreciated. My script is derived from much hack and bash and the BouncyCastle bit is to avoid bundling the same DLL twice in the installer.
I do appreciate that working to let other people integrate your tech feels like you're pointing users elsewhere. Hopefully Certify is blatant enough about where the providers come from that Posh-ACME gets the due credit. Likewise when other projects use Posh-ACME I hope they'll make it clear that Posh-ACME is enabling that feature (and be sponsors as well if they can). I'd estimate win-acme to be about 3x more commonly used than Certify (possibly more) and certbot on linux is probably at least 100x more commonly used, so these would be a good targets for a simple wrapper they can call (e.g. one line to do the setup and one to call the required DNS API).
We're getting a bit off topic, but man I wish I could get rid of that BouncyCastle dependency. Sadly, I probably won't be able to until I can drop support for PowerShell 5.1...which won't likely happen until after Microsoft stops shipping it with Windows...which doesn't seem likely anytime soon. But again, the plugins themselves shouldn't need it at all.
Oh yeah, we're totally cool there. I love Certify!
I don't blame anyone for trying certbot first because it's as close to an "official" client as there is. And it's likely a safer long-term bet for supportability unless you actually develop your own client. But given the number of folks who have lambasted the decision to move to snap for distribution, suggesting they install PowerShell on their Linux box just to use my plugins is probably a stretch. That said, I'd probably help in a heartbeat if anyone ever asked for it.
It's because C:\Certbot if where the config files are kept and C:\Program Files (x86)\Certbot is where the binary program files are. On windows (and most other operating systems) you don't/can't store your config where your binary program files are, otherwise you'd need to run as (elevated to) administrator all the time.
Not true, because it already asks me to run as admin when loading certbot. The renewal task in Task Scheduler even has a tickbox to run on admin level.
But thanks for that link to that issue, reading it now.
Interesting, certbot definitely doesn't require UAC elevation for admin rights on my machine but maybe if you use self hosting it would (because on windows you have to be elevated to bind to port 80 unless you add a specific binding ACL).
The renewal task does have 'Run with highest privileges' checked but that necessary for a process that has to potentially modify other users files and possibly bind to port 80 (it's effectively UAC for administrator)
I am self hosting. But even just typing "certbot" in a command prompt requires UAC.
I also did a test where I installed Certbot in C:/Certbot instead of in Program Files(x86). It seems to have made no difference in operation. But it's nicer to just have 1 folder for the program instead of both in C:/ and in C:/Program Files(x86).
Do you think there would be any conflicts if I installed Certbot in the same location where Certbot wants to keep all the certs and configuration files? It defaults to C:/Program Files(x86) but I changed it.
During installation it presents you with "Install in: C:/Program Files(x86)", and it will install in "C:/Program Files(x86)/Certbot" and if you erase the "Program Files(x86)" so it just shows "C:/" then it blocks the install. But if you type "C:/Certbot" then it will install straight to C:/Certbot and not C:/Certbot/Certbot.