Configuration
Spork uses TOML for configuration. The spork.toml file controls CA behavior, certificate profiles, and operational settings.
File search order
Spork searches for configuration in this order:
--configcommand-line argument./spork.tomlin current directory$CA_DIR/spork.tomlin CA directory~/.config/spork/spork.tomluser config
Basic configuration
# spork.toml
[ca]
# CA directory (overridden by --ca flag)
path = "./pki/issuing"
# Default signature algorithm
algorithm = "ecdsa-p384" # see Algorithm selection below
# Key encryption
key_encryption = "aes-256-gcm"
require_passphrase = true
[database]
# Storage backend: sqlite (default) or postgresql (planned)
type = "sqlite"
path = "spork.db" # relative to CA directory
# PostgreSQL (planned — not yet available)
# type = "postgresql"
# url = "postgres://user:pass@localhost/spork"
[logging]
level = "info" # trace, debug, info, warn, error
format = "json" # json, text
file = "spork.log"
Algorithm selection
| Algorithm string | Description |
|---|---|
ecdsa-p384 |
ECDSA P-384 (192-bit classical security; no quantum resistance) |
rsa-2048 |
RSA 2048-bit (compatibility; not recommended for new PKI) |
rsa-3072 |
RSA 3072-bit |
rsa-4096 |
RSA 4096-bit |
mldsa44 |
ML-DSA-44 (FIPS 204 specification-conformant — NIST category 2, post-quantum) |
mldsa65 |
ML-DSA-65 (FIPS 204 specification-conformant — NIST category 3, post-quantum) |
mldsa87 |
ML-DSA-87 (FIPS 204 specification-conformant — NIST category 5, post-quantum) |
Composite signatures (a classical and a PQ algorithm paired in one certificate) are not supported. The format is specified in draft-ietf-lamps-pq-composite-sigs, which has cleared IETF review and is awaiting RFC publication; Spork implements none of it, so there is no composite algorithm string to configure. Use a single algorithm per CA, and run parallel classical and PQ hierarchies if you need both.
Certificate profiles
Profiles define templates for certificate issuance. Each profile specifies key usage, extended key usage, and validity constraints. The profile name is passed to spork issue --profile <name>.
# TLS server certificate profile
[profiles.tls-server]
key_usage = ["digitalSignature"]
extended_key_usage = ["serverAuth"]
validity_days = 365
# Require SAN; CN alone is not sufficient
require_san = true
allowed_san_types = ["dns", "ip"]
[profiles.tls-server.subject]
required = ["CN"]
allowed = ["O", "OU", "L", "ST", "C"]
forbidden = ["emailAddress"]
# TLS client certificate profile
[profiles.tls-client]
key_usage = ["digitalSignature"]
extended_key_usage = ["clientAuth"]
validity_days = 365
require_san = false
allowed_san_types = ["email", "uri"]
[profiles.tls-client.subject]
required = ["CN"]
allowed = ["O", "OU", "emailAddress"]
# Code signing certificate profile
[profiles.code-sign]
key_usage = ["digitalSignature"]
extended_key_usage = ["codeSigning"]
validity_days = 365
require_san = false
[profiles.code-sign.subject]
required = ["CN", "O"]
allowed = ["OU", "L", "ST", "C"]
Validity periods
[validity]
root_ca_years = 20
policy_ca_years = 10
issuing_ca_years = 7
end_entity_days = 365
# Maximum end-entity validity enforced by this CA
max_end_entity_days = 365
# CRL update schedule
crl_validity_days = 7
crl_overlap_days = 1 # generate new CRL before current one expires
Spork is intended for private CAs. Public-web Baseline Requirements (CA/Browser Forum ballot SC-081v3) cap TLS end-entity validity at 200 days as of March 2026; private CAs may choose longer periods appropriate to their policy. Set max_end_entity_days to whatever your policy requires.
Extension templates
Extensions configured here are embedded in every certificate issued by the CA. Replace placeholder URLs with your own infrastructure endpoints.
[extensions]
# Authority Information Access
[extensions.aia]
ocsp = "http://ocsp.example.com/"
ca_issuers = "http://aia.example.com/issuing-ca.crt"
# CRL Distribution Points
[extensions.cdp]
uris = [
"http://crl.example.com/issuing-ca.crl",
"ldap://ldap.example.com/cn=Issuing%20CA,ou=PKI,o=Example,c=US"
]
# Certificate Policies
[extensions.policies]
oids = ["2.23.140.1.2.2"] # Organization Validated (example)
cps_uri = "http://www.example.com/pki/cps"
# Name Constraints (for CA certificates)
[extensions.name_constraints]
permitted_dns = [".example.com", ".example.org"]
excluded_dns = [".forbidden.example.com"]
permitted_email = ["@example.com"]
Full example
Complete spork.toml for a private issuing CA:
[ca]
path = "/opt/pki/issuing"
algorithm = "mldsa65"
key_encryption = "aes-256-gcm"
require_passphrase = true
[database]
type = "sqlite"
path = "spork.db"
[logging]
level = "info"
format = "json"
file = "/var/log/spork/issuing.log"
[validity]
end_entity_days = 365
max_end_entity_days = 365
crl_validity_days = 7
[extensions.aia]
ocsp = "http://ocsp.example.com/"
ca_issuers = "http://aia.example.com/issuing-ca.crt"
[extensions.cdp]
uris = ["http://crl.example.com/issuing-ca.crl"]
[profiles.tls-server]
key_usage = ["digitalSignature"]
extended_key_usage = ["serverAuth"]
validity_days = 365
require_san = true
allowed_san_types = ["dns", "ip"]
[profiles.tls-server.subject]
required = ["CN"]
allowed = ["O", "OU", "L", "ST", "C"]