SPORK ACME Server Guide
v0.4.0-beta.4 | 2,401 tests | 0 warnings | 0 audit vulnerabilities | 12/12 CI jobs green | FIPS 140-3 default
SPORK ACME Server is a standalone, RFC 8555-compliant certificate authority that works with certbot, acme.sh, and any ACME client out of the box. It includes a built-in micro-CA, interactive setup wizard, admin dashboard, and FIPS 140-3 mode.
Download
Download the standalone binary and run the setup wizard:
# Download
curl -fSL -o spork-acme \
https://rayketcham.com/CRLs/sp0rk/static/spork-acme-0.4.0-beta.4-linux-x86_64
# Make executable
chmod +x spork-acme
# Run the interactive setup wizard (requires root)
sudo ./spork-acme
System Requirements
| Requirement | Details |
|---|---|
| Architecture | x86_64 (amd64) |
| Operating System | Linux (any distribution with kernel 4.x+) |
| RAM | 256 MB minimum, 512 MB recommended |
| Disk | 100 MB for binary + 1 GB for CA data |
| Network | Port 6446 (ACME/HTTPS, configurable) |
| Dependencies | None — statically linked against musl libc |
Setup Wizard
The setup wizard runs automatically on first launch. It generates a complete CA hierarchy, TLS certificates, systemd service, and starts the ACME server.
sudo ./spork-acme
Deployment Types
| Option | Description | Recommended |
|---|---|---|
| 2-tier | Root CA + Issuing CA (root stays offline) | Yes, for testing |
| 3-tier | Root + Policy CA + Issuing CA | Enterprise production |
| Subordinate | Subordinate to Windows CA (CSR export/import) | AD-integrated environments |
| WinRM Bridge | Direct subordination via WinRM to Windows CA | Automated AD environments |
| Import PFX | Import existing CA from PFX/PKCS#12 file | Migration from existing CA |
Algorithm Selection
| Algorithm | Type | Notes |
|---|---|---|
| ECDSA P-256 | Classical | Default. Fastest, broadest compatibility. FIPS-approved. |
| ECDSA P-384 | Classical | Higher security margin. FIPS-approved. |
| RSA 3072 / 4096 | Classical | Legacy compatibility. FIPS-approved (≥3072). |
| ML-DSA-65 | Post-Quantum | NIST FIPS 204. Requires PQC-aware clients. |
| ML-DSA-65 + ECDSA P-256 | Hybrid | Composite signature. Best of both worlds. |
| ML-DSA-87 + ECDSA P-384 | Hybrid | Maximum security for both classical and PQC. |
| SLH-DSA-SHA2-128s | Post-Quantum | Hash-based, conservative security assumptions. |
--no-default-features --features ceremony.
DN Builder
The setup wizard includes an interactive Distinguished Name builder for configuring your CA subject. It supports multi-level attributes with editing and reordering.
| Attribute | Description | Example |
|---|---|---|
| CN (Common Name) | CA display name | My Org Issuing CA |
| O (Organization) | Organization name (removable) | My Organization Inc |
| OU (Org Unit) | Multi-level OU support | IT Security, PKI Operations |
| C (Country) | 2-letter ISO code | US |
| ST (State) | State or province | California |
| L (Locality) | City | San Francisco |
| DC (Domain Component) | Auto-parsed from domain | DC=example,DC=com |
The builder provides a review screen showing the full DN preview:
Subject DN: CN=My Org Issuing CA, OU=PKI Operations, O=My Organization Inc, C=US
[1] Edit attributes
[2] Reorder attributes
[3] Remove an attribute
[4] Accept and continue
Bind Address & Ports
| Setting | Default | Description |
|---|---|---|
| Bind address | 0.0.0.0 | IP to listen on (127.0.0.1 for localhost-only) |
| ACME port | 6446 | HTTPS port for ACME protocol and admin UI |
| External URL | Auto-detected | Public URL clients use to reach this server |
The wizard also prompts for:
- Lockbox passphrase — encrypts all CA private keys (AES-256-GCM + Argon2id)
- Systemd service — install and enable
spork-acme.service - System trust store — optionally add CA cert to OS trust store
FIPS Mode
The official SPORK ACME binary ships with FIPS 140-3 enabled by default. All cryptographic operations use aws-lc-rs (NIST Certificate #4816) as the backend. No special build steps, flags, or separate downloads are needed — one binary, FIPS by default.
Setup Wizard Toggle
During setup, the wizard asks you to choose FIPS mode:
FIPS 140-3 MODE
═══════════════
This binary uses aws-lc-rs (NIST Certificate #4816)
for all cryptographic operations.
> FIPS On - FIPS-approved algorithms only (Recommended)
FIPS Off - All algorithms available (Ed25519, RSA-2048, PQC)
- FIPS On (default): Only FIPS-approved algorithms shown in algorithm selection (ECDSA P-256/P-384, RSA ≥3072)
- FIPS Off: All algorithms available including Ed25519, RSA-2048, and PQC. The crypto backend is still aws-lc-rs (FIPS-certified) — only the algorithm policy is relaxed.
FIPS Algorithm Matrix
| Algorithm | FIPS Status | Notes |
|---|---|---|
| ECDSA P-256 | Approved | Recommended default |
| ECDSA P-384 | Approved | Higher security margin |
| RSA ≥3072 | Approved | RSA-2048 rejected |
| RSA-PSS ≥3072 | Approved | |
| Ed25519 | Not approved | Available with FIPS Off |
| RSA-2048 | Not approved | Available with FIPS Off |
| ML-DSA-* | Approved (FIPS 204) | Requires PQC feature flag |
| SLH-DSA-* | Approved (FIPS 205) | Requires PQC feature flag |
Verifying FIPS Mode
# Check if binary was built with FIPS
./spork-acme --version
# Output includes "fips" in feature list
# Server logs show FIPS status at startup
sudo journalctl -u spork-acme | grep -i fips
Domain Policy
SPORK ACME Server uses a deny-by-default domain policy. All certificate
requests are rejected unless the requested domain matches an --allow-domain pattern.
Configuration
# Allow all domains (universal wildcard)
sudo spork-acme -s /opt/spork-acme --allow-domain "**"
# Allow a specific domain and all subdomains
sudo spork-acme -s /opt/spork-acme --allow-domain "**.example.com"
# Allow only single-level subdomains
sudo spork-acme -s /opt/spork-acme --allow-domain "*.example.com"
# Allow an exact domain
sudo spork-acme -s /opt/spork-acme --allow-domain "server1.example.com"
# Multiple patterns (repeat the flag)
sudo spork-acme -s /opt/spork-acme \
--allow-domain "**.internal.corp" \
--allow-domain "*.lab.local"
Wildcard Patterns
| Pattern | Matches | Does Not Match |
|---|---|---|
** | Everything | — |
**.example.com | a.example.com, b.c.example.com | example.com |
*.example.com | a.example.com | b.c.example.com |
server1.example.com | server1.example.com | server2.example.com |
--allow-domain, the server
will reject all certificate requests. During the setup wizard, you are prompted to configure
allowed domains. Use --allow-domain "**" for testing environments.
Service Management
The setup wizard installs two systemd units:
| Unit | Purpose |
|---|---|
spork-acme.service | Main ACME server process |
spork-acme-crl.timer | Periodic CRL regeneration (every 12 hours) |
Common Commands
# Check server status
sudo systemctl status spork-acme
# Start / stop / restart
sudo systemctl start spork-acme
sudo systemctl stop spork-acme
sudo systemctl restart spork-acme
# Enable at boot
sudo systemctl enable spork-acme
# View live logs
sudo journalctl -u spork-acme -f
# View CRL timer status
sudo systemctl list-timers spork-acme-crl.timer
Management Menu
Running spork-acme with an existing installation presents a management menu:
sudo spork-acme
SPORK ACME Server v0.4.0-beta.4
Existing installation detected at /opt/spork-acme/
1) Configure - Web UI, TLS certificates, proxy settings
2) Backup - Create/restore encrypted backups, scheduling
3) Security - Audit, hardening, permissions, user management
4) Upgrade - Upgrade binary with full backup
5) Status - Service health and configuration review
6) Uninstall - Clean removal with optional backup
Select an option [1-6]:
Server Mode (No Systemd)
Run the server directly in the foreground for debugging:
sudo SPORK_LOCKBOX_PASSPHRASE="your-passphrase" \
spork-acme -s /opt/spork-acme
Admin Dashboard
The admin portal is served at https://hostname:6446/admin and provides
certificate inventory, revocation status, CA health, and audit logs.
Authentication Methods
| Method | Setup | Security Level |
|---|---|---|
| HTTP Basic Auth | --admin-user / --admin-password | Standard |
| mTLS (Client Cert) | Import SuperAdmin PFX into browser | High |
| Bearer Token | Set via Configure > Web UI | Standard |
mTLS Setup
- During setup, the wizard generates a SuperAdmin PFX at
/opt/spork-acme/admin/superadmin.pfx - Copy the PFX to your workstation
- Import into your browser:
- Firefox: Settings → Privacy & Security → Certificates → View Certificates → Import
- Chrome: Settings → Privacy and Security → Security → Manage certificates → Import
- Navigate to
https://hostname:6446/adminand select the client certificate when prompted
Admin Certificate Hierarchy
| Level | Capabilities |
|---|---|
| SuperAdmin | Full control, issue admin certs, factory reset |
| Admin | Revoke certs, manage CRLs, issue certs |
| Operator | Issue certs, view logs |
| Viewer | View-only access |
Dashboard Features
- Certificate browser — search, filter, inspect issued certificates
- CA status — view CA hierarchy, validity, key status
- Revocation management — CRL status, OCSP responder health
- ACME dashboard — accounts, orders, challenge status
- Audit log — full trail of all operations with export (CSV/JSON)
Test with Certbot
Verify the ACME server works with a certbot dry-run:
# Dry-run test (does not save a certificate)
certbot certonly --standalone \
--server https://localhost:6446/acme/directory \
--no-verify-ssl \
--agree-tos \
-d test.example.com \
--dry-run
Expected output:
Simulating a certificate request for test.example.com
The dry run was successful.
Issue a real certificate:
certbot certonly --standalone \
--server https://localhost:6446/acme/directory \
--no-verify-ssl \
--agree-tos \
-d myhost.internal.example.com
Rocky Linux / RHEL / CentOS Setup
Install Certbot
sudo dnf install -y epel-release
sudo dnf install -y certbot
Open the Firewall
sudo firewall-cmd --add-port=6446/tcp --permanent
sudo firewall-cmd --reload
SELinux Configuration
# Allow proxy connections (if using reverse proxy)
sudo setsebool -P httpd_can_network_connect 1
# Set file context for spork-acme binary
sudo semanage fcontext -a -t bin_t '/opt/spork-acme/bin/spork-acme'
sudo restorecon -v /opt/spork-acme/bin/spork-acme
# If denials persist, generate a targeted policy module
sudo ausearch -m avc -ts recent | audit2allow -M spork-acme
sudo semodule -i spork-acme.pp
audit2allow to create targeted policy
modules rather than switching to permissive mode.
Trust the CA Certificate
sudo cp /opt/spork-acme/ca/ca.crt /etc/pki/ca-trust/source/anchors/spork-ca.crt
sudo update-ca-trust
# Verify
openssl verify -CAfile /etc/pki/tls/certs/ca-bundle.crt /opt/spork-acme/ca/ca.crt
Keystore Passphrase for Service Mode
sudo mkdir -p /etc/spork-acme
sudo tee /etc/spork-acme/env > /dev/null <<'EOF'
SPORK_LOCKBOX_PASSPHRASE=your-passphrase-here
EOF
sudo chmod 600 /etc/spork-acme/env
sudo chown root:root /etc/spork-acme/env
Ubuntu / Debian Setup
Install Certbot
sudo apt update
sudo apt install -y certbot
Trust the CA Certificate
sudo cp /opt/spork-acme/ca/ca.crt /usr/local/share/ca-certificates/spork-ca.crt
sudo update-ca-certificates
Firewall (if UFW is enabled)
sudo ufw allow 6446/tcp
sudo ufw reload
Ubuntu and Debian do not run SELinux by default, so no additional security context configuration is needed. The keystore passphrase setup is the same as Rocky Linux (see above).
ACME Client Quick Start
The spork CLI includes a built-in ACME client that handles the full certificate
lifecycle. It works with any RFC 8555-compliant ACME server.
# 1. Download and install the spork client
curl -fSL -o spork-client-installer \
https://rayketcham.com/CRLs/sp0rk/static/spork-client-0.3.0-beta.9-linux-x86_64-installer
chmod +x spork-client-installer
sudo ./spork-client-installer
# 2. Request a certificate
spork acme certonly \
-d myhost.example.com \
--server https://acme.internal:6446/acme/directory \
--webroot /var/www/html \
--agree-tos
# 3. Check the issued certificate
spork acme status --domain myhost.example.com
# 4. (Optional) Deploy to Apache with automatic backup
sudo spork acme install \
-d myhost.example.com \
--server https://acme.internal:6446/acme/directory \
--apache \
--agree-tos
# 5. Set up automated renewal (cron)
echo "0 3 * * * spork acme renew -d myhost.example.com -s https://acme.internal:6446/acme/directory" \
| sudo crontab -
certonly saves
certificates to ~/.spork/certs/<domain>/. Each domain directory contains
fullchain.pem (certificate + chain) and privkey.pem (private key).
certonly — Request a Certificate
Performs the full ACME flow in one command: register account, create order, complete challenge, generate key + CSR, finalize, and download.
spork acme certonly [OPTIONS] -d <DOMAIN> -s <SERVER>
| Flag | Description |
|---|---|
-d, --domain <DOMAIN> | Domain name(s). Repeat for SANs: -d a.com -d b.com |
-s, --server <URL> | ACME server directory URL |
--webroot <DIR> | Web root for HTTP-01 challenge |
--standalone | Built-in HTTP server on port 80 for challenge |
--dns | DNS-01 challenge (manual TXT record, required for wildcards) |
-o, --output-dir <DIR> | Custom output directory |
--agree-tos | Agree to terms of service |
Examples
# Webroot challenge
spork acme certonly \
-d myhost.example.com \
--server https://acme.internal:6446/acme/directory \
--webroot /var/www/html --agree-tos
# Multiple SANs
spork acme certonly \
-d example.com -d www.example.com -d mail.example.com \
--server https://acme.internal:6446/acme/directory \
--webroot /var/www/html --agree-tos
# DNS-01 challenge (for wildcards)
spork acme certonly \
-d example.com \
--server https://acme.internal:6446/acme/directory \
--dns --agree-tos
install — Request and Deploy
install command modifies your web server
configuration. A backup is automatically created. Use spork acme rollback to restore.
Performs the full certonly flow, then detects your web server, backs up its config,
deploys the certificate, tests, and reloads. Automatic rollback on failure.
spork acme install [OPTIONS] -d <DOMAIN> -s <SERVER>
| Flag | Description |
|---|---|
--apache | Deploy to Apache (Linux) |
--nginx | Deploy to Nginx (Linux) |
--iis | Deploy to IIS (Windows) |
--backup-dir <DIR> | Custom backup directory |
renew — Renew a Certificate
Checks if a previously issued certificate is near expiry (within 30 days) and re-requests it.
# Check if renewal is needed
spork acme renew --domain myhost.example.com \
--server https://acme.internal:6446/acme/directory --dry-run
# Renew if within 30 days of expiry
spork acme renew --domain myhost.example.com \
--server https://acme.internal:6446/acme/directory
# Force renewal regardless
spork acme renew --domain myhost.example.com \
--server https://acme.internal:6446/acme/directory --force
Automated Renewal
# Cron: renew daily at 3 AM
0 3 * * * spork acme renew -d myhost.example.com -s https://acme.internal:6446/acme/directory
status — Show Certificate Status
spork acme status --domain myhost.example.com
Certificate Status
Subject: myhost.example.com
SANs: myhost.example.com, www.myhost.example.com
Valid From: 2026-02-11 00:00:00 UTC
Valid Until: 2026-05-12 00:00:00 UTC
Days Left: 90
OK
rollback — Restore Web Server Config
# Rollback to most recent backup
sudo spork acme rollback
# Rollback to a specific backup
sudo spork acme rollback --backup-id 2026-02-11-120000
# List available backups
spork acme backups
Apache Integration
The install command locates the virtual host for your domain, updates
SSLCertificateFile and SSLCertificateKeyFile directives, runs
apachectl configtest, and reloads.
sudo spork acme install \
-d myhost.example.com \
--server https://acme.internal:6446/acme/directory \
--apache --agree-tos
Manual deployment:
# After certonly, update your vhost config:
SSLCertificateFile /home/user/.spork/certs/myhost.example.com/fullchain.pem
SSLCertificateKeyFile /home/user/.spork/certs/myhost.example.com/privkey.pem
# Test and reload
sudo apachectl configtest
sudo systemctl reload apache2 # or httpd on RHEL
Nginx Integration
The deployer locates the server block for your domain, updates
ssl_certificate and ssl_certificate_key directives, runs
nginx -t, and reloads.
sudo spork acme install \
-d myhost.example.com \
--server https://acme.internal:6446/acme/directory \
--nginx --agree-tos
Manual deployment:
# After certonly, update your server block:
ssl_certificate /home/user/.spork/certs/myhost.example.com/fullchain.pem;
ssl_certificate_key /home/user/.spork/certs/myhost.example.com/privkey.pem;
# Test and reload
sudo nginx -t
sudo systemctl reload nginx
IIS Integration (Windows)
On Windows, the deployer imports the certificate into the Windows certificate store, binds it to the IIS site, and restarts the site.
spork acme install ^
-d myhost.example.com ^
--server https://acme.internal:6446/acme/directory ^
--iis --agree-tos
--apache and --nginx are
Linux only. --iis is Windows only. Use certonly and deploy manually
if your web server is not supported.
Backup & Restore
Interactive Backup
sudo spork-acme
# Navigate: Backup > Create Backup
# Choose encryption option
# Select backup directory
What Gets Backed Up
- CA private keys (from encrypted keystore)
- CA certificates and chain files
- Configuration files
- Issued certificate database
- Admin certificates
- TLS server certificates
- ACME account data
Restore from Backup
sudo spork-acme
# Navigate: Backup > Restore
# Select backup file
# Enter encryption passphrase if encrypted
Manual Restore
# Stop service
sudo systemctl stop spork-acme
# Extract backup
sudo tar -xzf /var/backups/spork/spork-backup-full-*.tar.gz -C /opt/spork-acme
# Start service
sudo systemctl start spork-acme
Scheduled Backups
sudo spork-acme
# Navigate: Backup > Schedule
# Select frequency: Daily, Weekly, or Monthly
# Enable encryption
CRL Management
The CRL timer runs every 12 hours by default (7-day validity with overlap).
# Check CRL timer
sudo systemctl status spork-acme-crl.timer
# Manual CRL update
sudo spork-acme --update-crl -s /opt/spork-acme
# View last CRL update
sudo journalctl -u spork-acme-crl.service --since today
CRL distribution:
- Local path:
/opt/spork-acme/ca/crl.pem - HTTP endpoint:
https://your-server:6446/crl
TLS Certificate Renewal
Renew the server's own TLS certificate (used for HTTPS on port 6446):
# Check expiration
openssl s_client -connect localhost:6446 </dev/null 2>/dev/null | \
openssl x509 -noout -dates
# Manual renewal
sudo spork-acme --renew-tls -s /opt/spork-acme
# Automatic renewal timer
sudo systemctl enable --now spork-acme-renew.timer
Log Management
# Real-time logs
sudo journalctl -u spork-acme -f
# Today's errors only
sudo journalctl -u spork-acme --since today -p err
# Export logs
sudo journalctl -u spork-acme --since "2026-01-01" > spork-logs.txt
Log Levels
| Level | Use Case |
|---|---|
error | Production (minimal) |
info | Normal operations (default) |
debug | Troubleshooting |
trace | Development only |
# Set via command line
spork-acme -s /opt/spork-acme --log-level debug
# Set via environment
export RUST_LOG=spork_acme=debug
Security Hardening
Automated Hardening
sudo spork-acme
# Navigate: Security > Harden
This creates a dedicated spork user/group, sets restrictive file permissions, and configures ownership on the state directory.
Manual Hardening
# Create dedicated user
sudo useradd -r -s /bin/false -d /opt/spork-acme spork
# Set ownership and permissions
sudo chown -R spork:spork /opt/spork-acme
sudo chmod 750 /opt/spork-acme
sudo chmod 600 /opt/spork-acme/keystore.db
sudo chmod 700 /opt/spork-acme/ca
sudo chmod 700 /opt/spork-acme/admin
sudo chmod 600 /opt/spork-acme/admin/*.pfx
Systemd Hardening
The default service file includes security restrictions. Add these for high-security deployments:
[Service]
NoNewPrivileges=true
ProtectSystem=strict
ProtectHome=true
ReadWritePaths=/opt/spork-acme
PrivateTmp=true
CapabilityBoundingSet=CAP_NET_BIND_SERVICE
AmbientCapabilities=CAP_NET_BIND_SERVICE
# Additional hardening
ProtectKernelTunables=true
ProtectKernelModules=true
ProtectKernelLogs=true
ProtectControlGroups=true
PrivateDevices=true
RestrictSUIDSGID=true
MemoryDenyWriteExecute=true
Network Hardening
# Bind to localhost only (behind reverse proxy)
spork-acme -s /opt/spork-acme --bind 127.0.0.1
Rate Limiting
| Limit | Default |
|---|---|
| Requests per account | 10/minute |
| Requests per IP | 30/minute |
| New orders per account | 20/day |
| Failed validations | 5/hour per domain |
Security Audit
sudo spork-acme
# Navigate: Security > Audit
Security Checklist
- Run security hardening wizard
- Create dedicated spork user
- Verify file permissions (keystore 0600, state dir 0750)
- Configure firewall (allow only port 6446)
- Bind to specific interface (not 0.0.0.0 in production)
- Enable audit logging and forward to SIEM
- Schedule regular backups with encryption
- Rotate admin certificates annually
Windows CA Integration
SPORK can operate as a subordinate CA under your Windows Active Directory Certificate Services (AD CS) infrastructure. The Windows CA signs SPORK's CA certificate, then SPORK issues end-entity certificates via ACME.
Windows AD CS Root CA (RSA/ECDSA)
|
+--- signs subordinate ---> SPORK Issuing CA
|
+----------+----------+
v v v
ECDSA Hybrid ML-DSA
Step 1: Configure Windows CA Template
- Open Certificate Templates console (
certtmpl.msc) - Duplicate "Subordinate Certification Authority" template
- Set: name=
SPORKSubCA, validity=5-10y, pathLenConstraint=0, CA:TRUE - Publish:
certutil -setcatemplates +SPORKSubCA
Step 2: Generate CSR on SPORK
sudo spork-acme
# Select: Subordinate to Windows CA
# Choose algorithm (ECDSA P-256 recommended for Windows compat)
# CSR saved to: /opt/spork-acme/spork-acme.csr
Step 3: Submit CSR to Windows CA
REM On Windows CA server:
certreq -submit -attrib "CertificateTemplate:SPORKSubCA" spork-acme.csr spork-ca.cer
REM If pending approval:
certutil -resubmit <RequestID>
Step 4: Export Root CA Certificate
certutil -ca.cert windows-root.cer
certutil -encode windows-root.cer windows-root.pem
Step 5: Import to SPORK
spork-acme --import-cert /opt/spork-acme/ca/spork-ca.cer \
--import-chain /opt/spork-acme/ca/windows-root.pem \
-s /opt/spork-acme
Step 6: Verify
# Test ACME directory
curl -s https://acme.yourcompany.com:6446/directory | jq
# Issue a certificate
certbot certonly --standalone \
--server https://acme.yourcompany.com:6446/directory \
--agree-tos -d myserver.yourcompany.com
# Verify chain: TLS cert -> SPORK Issuing CA -> Windows Root CA
openssl s_client -connect acme.yourcompany.com:6446 -showcerts
Troubleshooting
Port 6446 already in use
sudo ss -tlnp | grep 6446
# Kill the conflicting process or change the ACME bind port
Permission denied on startup
sudo chmod +x /opt/spork-acme/bin/spork-acme
sudo chown -R root:root /opt/spork-acme
sudo chmod 700 /opt/spork-acme
SELinux denials (Rocky / RHEL)
sudo ausearch -m avc -ts recent
sudo ausearch -m avc -ts recent | audit2allow -M spork-acme-local
sudo semodule -i spork-acme-local.pp
Firewall blocking connections
# Rocky / RHEL
sudo firewall-cmd --add-port=6446/tcp --permanent
sudo firewall-cmd --reload
# Ubuntu / Debian
sudo ufw allow 6446/tcp
Certbot fails with SSL errors
# Option 1: Use --no-verify-ssl
certbot certonly --standalone \
--server https://localhost:6446/acme/directory \
--no-verify-ssl --agree-tos -d test.example.com --dry-run
# Option 2: Set REQUESTS_CA_BUNDLE
export REQUESTS_CA_BUNDLE=/opt/spork-acme/ca/ca.crt
certbot certonly --standalone \
--server https://localhost:6446/acme/directory \
--agree-tos -d test.example.com --dry-run
Service fails to start (keystore error)
# Check logs
sudo journalctl -u spork-acme -n 50
# Verify environment file
ls -la /etc/spork-acme/env
sudo grep SPORK_LOCKBOX_PASSPHRASE /etc/spork-acme/env
CRL timer not running
sudo systemctl status spork-acme-crl.timer
sudo systemctl enable --now spork-acme-crl.timer
# Manual trigger
sudo systemctl start spork-acme-crl.service
Domain rejected by server
# Check that --allow-domain is configured
sudo journalctl -u spork-acme | grep -i "domain.*denied\|domain.*reject"
# Add allowed domains
# Edit the systemd ExecStart line or config to include:
# --allow-domain "**.yourdomain.com"
# Then restart:
sudo systemctl restart spork-acme
FIPS mode rejects algorithm
The official binary ships with FIPS enabled by default. Ed25519 and RSA-2048 are not available. Re-run setup and choose a FIPS-approved algorithm:
# Re-run setup with ECDSA P-256/P-384 or RSA ≥3072
sudo spork-acme
"No supported challenge type"
The ACME server did not offer HTTP-01 or DNS-01 challenges. Check that:
- The domain name is valid RFC 1035 format
- The ACME server is reachable at the specified URL
- Your account is registered (
spork acme register)
install fails to detect web server
# Specify explicitly
sudo spork acme install -d example.com -s URL --apache --agree-tos
# Or use certonly and deploy manually
spork acme certonly -d example.com -s URL --agree-tos
# Then configure web server with:
# ~/.spork/certs/example.com/fullchain.pem
# ~/.spork/certs/example.com/privkey.pem
Windows CA: "Key mismatch" during import
The certificate was signed from a different CSR. Verify you are importing the certificate that matches your CSR. If the CSR was regenerated, request a new certificate from Windows CA.
Windows CA: "Not a CA certificate"
The Windows CA used the wrong template. Verify the template has BasicConstraints CA:TRUE with pathLenConstraint=0, marked critical.