Implementation Details
August 29, 2025 · View on GitHub
Implementation Details
The webserver exposes the following routes/directories:
/.well-known/acme-challenge- directory/.well-known/public/whoami- URL prints host/.well-known/peter_sslers- admin tool IMPORTANT - THIS EXPOSES PRIVATE KEYS ON PURPOSE
The server will respond to requests with the following header to identify it:
X-Peter-SSLers: production
Configuration and Storage
For each environment, a dedicated Data Directory should be created.
At a minimum, the Data Directory should contain a config.ini file;
example configuraiton files are located in the example_configs directory.
The following items will be created in the data directory::
{DataDirectory}/ssl_minnow.sqlite- the core database{DataDirectory}/_ACME_SERVER_BUNDLE/- if ACME Servers require a Trusted Root that is not in the default trust store, on-disk bundle files will be created and stored here as needed.{DataDirectory}/acme-dns.db- the testing system is configured to use this location for it's storage.
Additionally, it is recommended to specify the nginx_ca_bundle.pem as a file in the data directory::
{DataDirectory}/nginx_ca_bundle.pem- if the nginx servers pool require a Trusted Root that is not in the default trust store, an on-disk bundle files will be looked for in this location.
Just a friendly reminder:
THE ADMIN TOOL SHOULD NEVER BE PUBLICLY ACCESSIBLE. YOU SHOULD ONLY RUN IT ON A PRIVATE NETWORK
By default, the example_configs/production.ini file won't even run the admin tools.
That is how serious we are about telling you to be careful!
manage custom trust
To specify the CA Certificate bundles:
import peter_sslers.lib.cas
peter_sslers.lib.cas.CA_ACME = [bool, str]
# use ca_bundle_pem in configuration
# peter_sslers.lib.cas.CA_NGINX = [bool, str]
why/how?
Again, the purpose of this package is to enable Certificate Management in systems where one or more of the following apply:
- you have a lot of Domains
- you have a lot of machines
- your Domains resolve to more than one IP address
Imagine you want to issue a Certificate for 100 Domains, which could be served from any one of 5 machines (load balancers or round-robin dns) and the Certificates need to be deployable to all 5 machines.
To solve this you can:
- proxy external
/.well-known/acme-challenge/to one or more machines running this tool (they just need to share a common datastore) - make
/.well-known/peter_sslersonly usable within your LAN or NEVER USABLE - on a machine within your LAN, you can query for the latest certs for Domain(s)
using simple
curlcommands
In a more advanced implementation (such as what this was originally designed to
manage) the Certificates need to be loaded into a Redis server for use by an
OpenResty/Nginx webserver/gateway that will dynamically handle SSL Certificates.
In a simple example, OpenResty/Nginx will query
/.well-known/peter_sslers/domain/example.com/config.json to pull the active Certificate
information for a Domain. In advanced versions, that Certificate information will
be cached into multiple levels of OpenResty/Nginx and Redis using different
optimization strategies.
This package does all the annoying openssl work in terms of building chains and converting formats You just tell it what Domains you need Certificates for and in which format AND THERE YOU GO.
Deployment Concepts

PeterSSlers can run as a standalone service OR proxied behind Nginx/Apache/etc
The SSLMinnow datastore is entirely separate and standalone. It is portable.

In order to make network configuration more simple, the package includes a "fake server" that includes routes for the major public and admin endpoints. This should support most integration test needs.

In an advanced setting, multiple servers proxy to multiple peter-sslers "public" instances.
The instances share a single SSLMinnow data store.
The "Admin" tool runs on the private intranet.
Notes
Certificate/Key Translations
Certificates and Keys are stored in the PEM format, but can be downloaded in the DER format if needed.
There are several ways to download each file. Different file suffix will change the format and headers.
Peter shows you buttons for available formats on each page.
X509Certificate
The Certificate Itself:
cert.pem PEM application/x-pem-file
cert.pem.txt PEM text/plain
cert.cer DER application/pkix-cert
cert.crt DER application/x-x509-server-cert
cert.der DER application/x-x509-server-cert
The Certificate Chain:
chain.pem PEM application/x-pem-file
chain.pem.txt PEM text/plain
The Certificate Fullchain
fullchain.pem PEM application/x-pem-file
fullchain.pem.txt PEM text/plain
X509CertificateTrusted
The CertificateAuthority's Certificate:
cert.pem PEM application/x-pem-file
cert.pem.txt PEM text/plain
cert.cer DER application/pkix-cert
cert.crt DER application/x-x509-ca-cert
cert.der DER application/x-x509-ca-cert
X509CertificateTrustChain
One or more CertificateAuthority Certificates
chain.pem PEM application/x-pem-file
chain.pem.txt PEM text/plain
X509CertificateRequest
csr.pem PEM application/x-pem-file
csr.pem.txt PEM text/plain
csr.csr PEM application/pkcs10
Account/Domain Keys
key.pem PEM application/x-pem-file
key.pem.txt PEM text/plain
key.key DER application/pkcs8
Account/Domain Keys
key.pem PEM application/x-pem-file
key.pem.txt PEM text/plain
key.key DER application/pkcs8
Workflow Concepts
Object Attributes
Domain
is_active
If a Domain is "active", then it is actively managed and should be included in
ACME Order renewals or generating Nginx configuration.
X509Certificate
is_active
If a Certificate is "active" (True by default) then it is actively managed and
should be included in generating Nginx configuration.
is_deactivated and is_revoked
If a certificate is not "active", only one of these will be True. If an inactive
certificate was deactivated, then it can be activated and this flag will reverse.
If the certificate was revoked, it is permanent and should not be re-activated.
Oddities
-
When an
AcmeAuthorizationis "deactivated", the "ACME Server" will disassociate the related "ACME Challenges" on the upstream server itself. Invoking bothacme-server/deactivateandacme-server/syncfrom anAcmeAuthorizationobject will sync the PeterSSLers object to the "ACME Authorization" object on the server. This will transition the status of theAcmeChallengeobject to*410*, an internal code which means "ThisAcmeChallengehas disappeared". The "ACME Challenge" objects will still remain on the "ACME Server" in a "pending" state, which will be reflected if anacme-server/syncis invoked from theAcmeChallengeobject.Illustration:
1. Create AcmeOrder AcmeAuthorization.status = "*discovered*" 2. Load AcmeAuthorization AcmeAuthorization.status = "pending" AcmeChallenge.status = "pending" 3. Deactivate AcmeAuthorization AcmeAuthorization.status = "deactivated" AcmeChallenge.status = "*410*" 3. Sync AcmeChallenge AcmeChallenge.status = "pending"No known ACME Servers recycle pending Challenges across Authorizations. Adding an "Authorization2Challenge" table to track the "active" status of the relationship would unnecessarily complicate this application, however it will be done if necessary in the future.