Configuration
alpinCertificateClient reads a single JSON configuration file — typically
named config.json — that tells it where the alpinCertificateTool platform
lives and how to authenticate against it:
{
"baseURL": "https://d3signapp.alpin.it/alpinCertificateToolREST/api/",
"apiKey": "YOUR_API_KEY"
}
baseURL— the alpinCertificateTool REST API endpoint. Use the value above unless you've been told otherwise.apiKey— your personal API key. You can view (and, if needed, regenerate) it from the alpin-cert-tool d.3one app in your d.3one Configuration Dashboard (see Architectural Details).
Every invocation of the client points at this file via -c / --config.
Keep it out of version control, since it carries your API key.
Installing the client
alpinCertificateClient ships as a single, self-contained jar file,
alpinCertificateClient-1.0.0-complete.jar. Copy it to any directory on
the target machine — Windows or Linux — there's nothing else to install,
beyond having a Java 21 (or later) runtime available on that machine.
java -jar alpinCertificateClient-1.0.0-complete.jar -c C:\cert\config.json <command> ...
Sample scripts
We provide ready-made Bash and PowerShell sample scripts that show typical
usage end to end, from requesting a certificate to installing it on your
target system. The rest of this page walks through one of them,
windows1.ps1, in detail — the same concepts apply to the Bash samples.
Howto for the powershell update script (windows1.ps1)
# Alpin Certificate Client Demo for Windows
#
# Command args:
# Usage: alpinCertificateClient order-auto [-hV] [--cert-file=CERT_PATH]
# [--certificate-instance=CERTIFICATE_INSTANCE]
# [--certificate-inventory=CERTIFICATE_INVENTORY] [--challenge-type=TYPE]
# [--dnsprovider=DNSPROVIDER] [--key-file=KEY_FILE] [-p=PASSWORD]
# [--pem-file=PEM_FILE] [--pfx-file=PFX_FILE] [--ttl=TTL]
# [--dns-option=KEY=VALUE]... DOMAIN CA_ID SECRET [RENEW_DAYS]
# Order a certificate for a domain, automatically fulfilling the dns-01 challenge
# via a DNS provider
# DOMAIN Domain name (e.g. example.com or *.example.com for
# wildcard)
# CA_ID Certificate authority identifier (lowercase
# alphanumeric, underscores, and hyphens)
# SECRET 32-character secret used to decrypt the user and
# domain key pairs
# [RENEW_DAYS] If set, only proceed when no certificate exists yet
# for this domain, or the existing one is already
# expired or expires within this many days;
# otherwise do nothing
# --cert-file=CERT_PATH File to which the domain's certificate should be
# exported
# --certificate-instance=CERTIFICATE_INSTANCE
# The certificate's key inside the certificate
# inventory
# --certificate-inventory=CERTIFICATE_INVENTORY
# Path to a .json file that consists of key-value
# pairs, where the key is the certificate instance
# and they value is that certificate's expiration
# date
# --challenge-type=TYPE ACME challenge type to fulfill: DNS01 (default),
# DNSPERSIST01, or DNSHOSTED01
# --dns-option=KEY=VALUE
# Provider-specific option (zoneId=.../apiToken=...
# for cloudflare; hostedZoneId=.../accessKeyId=...
# /secretAccessKey=... for route53); may be
# repeated; ignored for --challenge-type DNSHOSTED01
# --dnsprovider=DNSPROVIDER
# DNS provider to use for automated challenge
# fulfillment (must be listed in the dnsProviders
# config); required unless --challenge-type is
# DNSHOSTED01, which ignores it
# -h, --help Show this help message and exit.
# --key-file=KEY_FILE File to which the domain's key pair should be
# exported
# -p, --password=PASSWORD The password that should be used to protect the
# certificate. Only used if the --pfx-file or
# --pem-file options are specificed
# --pem-file=PEM_FILE File to which the domain's certificate should be
# exported (in pem format)
# --pfx-file=PFX_FILE File to which the domain's certificate should be
# exported (in pfx format)
# --ttl=TTL TTL in seconds for the DNS record; if omitted, the
# DNS provider applies its own default
# -V, --version Print version information and exit.
# Check and adapt the powershell execution policy if needed, for example:
# RemoteSigned allows locally created scripts to run, while scripts downloaded from the internet generally need to be signed (or explicitly unblocked).
# Get-ExecutionPolicy -List
# Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy RemoteSigned
# Example to setup domain
# java -jar alpinCertificateClient-1.0.0-complete.jar -c C:\cert\config.json setup sub.alpin.zone letsencrypt_stage ABCDEFGHIJKLMNOPQRSTUVWXYZabcdef
# Set NO_COLOR if you want to skip ansi colors (as in elevated powershells)
#$env:NO_COLOR = 1
$env:NO_COLOR = $null
# Example to auto order certificate
java -jar alpinCertificateClient-1.0.0-complete.jar `
-c C:\cert\config.json `
order-auto sub.alpin.zone letsencrypt_stage ABCDEFGHIJKLMNOPQRSTUVWXYZabcdef 5 `
--challenge-type=DNSHOSTED01 `
--pfx-file=C:\cert\domain.pfx `
--pem-file=C:\cert\domain.pem `
--password=password `
--certificate-inventory=C:\cert\inventory.json `
--certificate-instance=windows-server
# Store the client's exit code
$exitCode = $LASTEXITCODE
# Example for powershell postprocessing
# Note that you need to run this in an elevated powershell, if scheduling through task scheduler:
# Create a new task (not a basic task)
# General - Run whether user is loggoed on or not - Run with highest privileges
# Actions - Program/script powershell.exe
# - Add arguments -NoProfile -ExecutionPolicy Bypass -File "C:\path\to\dir\renewalscript.ps1""
# - Start in C:\path\to\dir
# Example to load certificates in windows certificate store, restart services, kill processes
if ($exitCode -eq 0) {
# CertStoreLocation: this machine "Cert:\LocalMachine\My" or current user "Cert:\CurrentUser\My"
#Import-PfxCertificate -FilePath "C:\cert\domain.pfx" -CertStoreLocation "Cert:\LocalMachine\My" -Password (ConvertTo-SecureString "password" -AsPlainText -Force)
# Restart Windows service if needed
#Restart-Service -Name "AdobeARMservice" -Force
# Terminate a specific process if needed
#Stop-Process -Name "crash_reporter" -Force
}
exit $exitCode
The comment block at the top is the client's own --help output for the
order-auto command — it's the authoritative reference for every option, and
we'll return to it in the full parameter reference
below. If the script itself refuses to run, see
Allowing the script to run below.
Allowing the script to run
If PowerShell refuses to run windows1.ps1 at all — typically with an error
about the file "not being digitally signed" — it's almost always because the
script was downloaded from the internet (a browser or file share tags
downloaded files this way) rather than created locally. Windows' default
execution policy is intentionally stricter about downloaded scripts than
about ones you wrote yourself. The script's own header comments cover the
fix:
# Check and adapt the powershell execution policy if needed, for example:
# RemoteSigned allows locally created scripts to run, while scripts downloaded from the internet generally need to be signed (or explicitly unblocked).
# Get-ExecutionPolicy -List
# Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy RemoteSigned
Get-ExecutionPolicy -Listshows the current policy for each scope (MachinePolicy,UserPolicy,Process,CurrentUser,LocalMachine), so you can see what's actually blocking the script.Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy RemoteSignedrelaxes the policy for your own user account only: locally created scripts (like your own copy ofwindows1.ps1, once you've saved and edited it) are allowed to run unsigned, while scripts that still carry the "downloaded from the internet" mark are not — unless you explicitly clear that mark first, e.g. withUnblock-File -Path .\windows1.ps1.
First-time setup for a domain
java -jar alpinCertificateClient-1.0.0-complete.jar -c C:\cert\config.json setup sub.alpin.zone letsencrypt_stage ABCDEFGHIJKLMNOPQRSTUVWXYZabcdef
Run setup once per domain, the first time you want a certificate for it. It
takes care of the one-time bootstrapping a domain needs before it can be
issued a certificate: registering (or reusing) your account with the given
Certificate Authority — here letsencrypt_stage, Let's Encrypt's sandbox
environment — and generating the domain's key pair, both encrypted under your
SECRET. Once this has run, the domain is ready for order-auto to issue
and renew certificates against.
Checking, ordering, and renewing the certificate
java -jar alpinCertificateClient-1.0.0-complete.jar `
-c C:\cert\config.json `
order-auto sub.alpin.zone letsencrypt_stage ABCDEFGHIJKLMNOPQRSTUVWXYZabcdef 5 `
--challenge-type=DNSHOSTED01 `
--pfx-file=C:\cert\domain.pfx `
--pem-file=C:\cert\domain.pem `
--password=password `
--certificate-inventory=C:\cert\inventory.json `
--certificate-instance=windows-server
This is the command you actually schedule to run every day. A few things worth calling out:
--challenge-type=DNSHOSTED01selects the DNS-HOSTED-01 challenge — the proprietary, zero-touch-DNS approach described on the Architectural Details page. It's the right choice unless your DNS is already hosted with an API-driven provider we integrate with.order-autois the command that does the actual work: it checks whether the current certificate forsub.alpin.zonestill has enough validity left, and if not, requests a new one and completes the challenge automatically. The trailing5isRENEW_DAYS— renew only if the certificate expires within 5 days (or doesn't exist yet); otherwise the command does nothing and exits cleanly.--pfx-file/--pem-filewrite the freshly issued (or renewed) certificate and its private key to disk, in PKCS#12 and PEM form respectively, both protected by--password. This password is independent fromSECRET—SECRETonly unlocks your stored account and domain key pairs, while--passwordprotects these exported files.--certificate-inventory/--certificate-instancemaintain a small local JSON file (inventory.json) that records, per certificate "instance" name (herewindows-server), when that certificate was last installed on this machine — so your script can tell whether the file it just wrote is actually new.- At the end, the script stores
$LASTEXITCODE. A non-zero exit code means a certificate was actually fetched (issued or renewed) and now needs to be installed; a zero exit code means the existing certificate was still valid and nothing changed, so the rest of the script can skip installation entirely. - The commented-out block under the exit-code check shows typical
installation steps you can enable: importing the
.pfxinto the Windows Certificate Store withImport-PfxCertificate, restarting a Windows service that needs to pick up the new certificate, or killing a process that will restart with it on its own.
Scheduling the script to run daily
The whole point of order-auto is that it's safe to run every day and only
does something on the days a renewal is actually due, so schedule it once
and forget about it. On Windows, the built-in Task Scheduler is the
usual way to do that. The script's own comments spell out the settings that
matter:
# Note that you need to run this in an elevated powershell, if scheduling through task scheduler:
# Create a new task (not a basic task)
# General - Run whether user is loggoed on or not - Run with highest privileges
# Actions - Program/script powershell.exe
# - Add arguments -NoProfile -ExecutionPolicy Bypass -File "C:\path\to\dir\renewalscript.ps1""
# - Start in C:\path\to\dir
- Use Create Task… (not Create Basic Task…) — only the full dialog exposes the "Run with highest privileges" option.
- On the General tab, set "Run whether user is logged on or not" and
check "Run with highest privileges". Certificate installation steps
like
Import-PfxCertificateinto the Local Machine store, or restarting a Windows service, need an elevated (administrator) PowerShell session — this is what gets you that, non-interactively, on a daily schedule. - On the Actions tab, the program to run is
powershell.exe, with arguments-NoProfile -ExecutionPolicy Bypass -File "C:\path\to\dir\renewalscript.ps1"and "Start in" set to that same directory — so relative paths inside the script (and any files it writes) resolve where you expect.-ExecutionPolicy Bypasshere sidesteps the execution-policy issue from the previous section specifically for this scheduled run, without changing your machine's general policy.
One side effect of running elevated, non-interactively via Task Scheduler:
alpinCertificateClient normally prints colored ANSI output, and that
elevated PowerShell host may not render it correctly, showing raw escape
codes instead of colored text. If you see that, disable coloring with the
NO_COLOR environment variable the script already sets up for this purpose:
# Set NO_COLOR if you want to skip ansi colors (as in elevated powershells)
#$env:NO_COLOR = 1
$env:NO_COLOR = $null
Uncomment $env:NO_COLOR = 1 (and remove or comment out the
$env:NO_COLOR = $null line below it) to make the client skip ANSI
coloring entirely — useful whenever output is going somewhere that doesn't
render color well, such as a Task Scheduler history log.
DNS-HOSTED-01
Using --challenge-type=DNSHOSTED01 is the most practical approach if your
current DNS provider isn't one that offers an API to programmatically
create, update, and delete DNS records.
Potentially in Q3/2026 or Q4/2026, there will be a DNS-PERSIST-01 challenge available. With that challenge type, you'll be able to set up a DNS TXT record once, and that same record will be sufficient for any subsequent certificate renewal. Since DNS-PERSIST-01 isn't officially available yet, we've implemented a similar approach as part of the alpinCertificateTool platform, which we call DNS-HOSTED-01.
With the DNS-HOSTED-01 challenge:
- You only need to create a DNS record of type CNAME once, pointing your certificate's name at a specific target namespace on the alpinCertificateTool infrastructure. As long as this DNS record is present, you'll be able to issue or renew that certificate.
- Behind the scenes, the alpinCertificateTool platform takes care of dynamically creating, updating, and deleting the real DNS records in our target namespace that are needed for the standard DNS-01 challenge — you never have to touch your own DNS again after that first CNAME.
This use case is totally simple. If, for example, you plan to create a certificate for the domain name
subdomain.yourdomain.tld
all you need to do is create a CNAME entry in your DNS:
_acme-challenge.subdomain.yourdomain.tld CNAME _acme-challenge.subdomain-yourdomain-tld.certificatemanager.alpin.it 60
Explained in detail:
_acme-challenge.subdomain.yourdomain.tld—_acme-challenge.followed by the certificate name you want.CNAME— the type of DNS record._acme-challenge.subdomain-yourdomain-tld.certificatemanager.alpin.it— the target record you're pointing to. It starts with_acme-challenge., followed by your certificate name with every period replaced by a dash, and ending with.certificatemanager.alpin.it.60— the TTL (time to live) of the record. Keep it short, such as 60 seconds.
Two real-world examples:
_acme-challenge.sub.alpin.zone CNAME _acme-challenge.sub-alpin-zone.certificatemanager.alpin.it 60
_acme-challenge.test.alpin.zone CNAME _acme-challenge.test-alpin-zone.certificatemanager.alpin.it 60
DNS-01 with an API-driven DNS provider
The example above uses DNS-HOSTED-01, which needs no DNS provider credentials at all. If your domain's DNS is already hosted with Cloudflare or AWS Route 53, you can instead use the standard DNS-01 challenge and let alpinCertificateClient manage the TXT record for you directly against your own DNS provider.
Example: Cloudflare
java -jar alpinCertificateClient-1.0.0-complete.jar `
-c C:\cert\config.json `
order-auto d3.alpin.it letsencrypt_stage ABCDEFGHIJKLMNOPQRSTUVWXYZabcdef 5 `
--challenge-type=DNS01 `
--dnsprovider=cloudflare `
--dns-option=zoneId="YOUR_CLOUDFLARE_ZONE_ID" `
--dns-option=apiToken="YOUR_CLOUDFLARE_API_TOKEN" `
--pfx-file=C:\cert\domain2.pfx `
--pem-file=C:\cert\domain2.pem `
--password=password `
--certificate-inventory=C:\cert\inventory.json `
--certificate-instance=windows-server2
Aside from the domain and file names, the only differences from the
DNS-HOSTED-01 example are --challenge-type=DNS01, --dnsprovider=cloudflare,
and the two --dns-option values — your Cloudflare zone ID and an API token
scoped to manage DNS records in that zone.
Example: AWS Route 53
java -jar alpinCertificateClient-1.0.0-complete.jar `
-c C:\cert\config.json `
order-auto test.alpin.zone letsencrypt_stage ABCDEFGHIJKLMNOPQRSTUVWXYZabcdef 1000 `
--challenge-type=DNS01 `
--dnsprovider=route53 `
--dns-option=hostedZoneId="YOUR_ROUTE53_HOSTED_ZONE_ID" `
--dns-option=accessKeyId="YOUR_AWS_ACCESS_KEY_ID" `
--dns-option=secretAccessKey="YOUR_AWS_SECRET_ACCESS_KEY" `
--ttl=60 `
--pfx-file=C:\cert\domain3.pfx `
--pem-file=C:\cert\domain3.pem `
--password=password `
--certificate-inventory=C:\cert\inventory.json `
--certificate-instance=windows-server3
Here --dnsprovider=route53 takes three --dns-option values instead of
two — a hosted zone ID and an AWS access key pair with permission to modify
records in that zone — plus --ttl=60, which shortens the TXT record's TTL
so the CA doesn't have to wait as long for it to propagate before validating
the challenge. Note also RENEW_DAYS is 1000 here rather than 5: since
no real certificate has 1000 days of validity left, this effectively forces
a renewal on every run — handy while testing, but not what you'd want in a
real nightly schedule.
Full parameter reference
Positional arguments, in order:
| Argument | Description |
|---|---|
DOMAIN |
Domain name, e.g. example.com, or *.example.com for a wildcard certificate |
CA_ID |
Certificate Authority identifier (lowercase alphanumeric, underscores, and hyphens) |
SECRET |
32-character secret used to decrypt your user and domain key pairs |
RENEW_DAYS (optional, order-auto only) |
Only proceed if no certificate exists yet, or the existing one is expired or expires within this many days; otherwise do nothing |
Options:
| Option | Description |
|---|---|
--cert-file=CERT_PATH |
File to export the domain's certificate to |
--certificate-instance=CERTIFICATE_INSTANCE |
The certificate's key inside the certificate inventory file |
--certificate-inventory=CERTIFICATE_INVENTORY |
Path to a .json file mapping certificate instance names to that certificate's expiration date |
--challenge-type=TYPE |
ACME challenge type to fulfill: DNS01 (default), DNSPERSIST01, or DNSHOSTED01 |
--dns-option=KEY=VALUE |
Provider-specific option — zoneId=... / apiToken=... for Cloudflare, hostedZoneId=... / accessKeyId=... / secretAccessKey=... for Route 53; may be repeated; ignored when --challenge-type=DNSHOSTED01 |
--dnsprovider=DNSPROVIDER |
DNS provider to use for automated challenge fulfillment; required unless --challenge-type=DNSHOSTED01 |
-h, --help |
Show the help message and exit |
--key-file=KEY_FILE |
File to export the domain's key pair to |
-p, --password=PASSWORD |
Password protecting the exported certificate; only used together with --pfx-file or --pem-file |
--pem-file=PEM_FILE |
File to export the domain's certificate to, in PEM format |
--pfx-file=PFX_FILE |
File to export the domain's certificate to, in PFX format |
--ttl=TTL |
TTL in seconds for the DNS record; if omitted, the DNS provider's own default applies |
-V, --version |
Print version information and exit |