NewWe open-sourced 50+ Laravel packages
Custom AI apps, agents and automation — Roundly ConsultingRoundly
All packages
Certificates for Laravel

Filesystem driver

The filesystem driver manages PEM material on a Storage disk. It is not a CA: it reads material produced elsewhere — an external ACME run, a purchased certificate — and, with self_signed enabled, generates self-signed certificates for local development and tests. It never reports work it did not do:

config(['certificates.drivers.filesystem.self_signed' => true]);
Certificates::for('app.test')->using('filesystem')->issue();

Driver keys

KeyEnvDefaultPurpose
diskCERTIFICATES_FS_DISKlocalStorage disk holding the PEM material.
pathCERTIFICATES_FS_PATHcertificatesDirectory on that disk.
self_signedCERTIFICATES_FS_SELF_SIGNEDfalseMint fresh self-signed material on every issue and renewal — never over a CA-issued PEM. Off, a name with no stored PEM throws.
self_signed_daysCERTIFICATES_FS_SELF_SIGNED_DAYS90Validity of self-signed certificates, in days.

Layout

It uses the same layout as the ACME store — one directory per certificate name holding certificate.pem, private.key and an optional chain.pem. The defaults (local disk, certificates path) match drivers.acme.store, so the filesystem driver reads ACME-issued material out of the box:

certificates/                          path on the disk
└── generated-tls-app-example-com/     Certificates::certificateName($domain)
    ├── certificate.pem                leaf certificate
    ├── private.key                    private key
    └── chain.pem                      intermediate chain, when present

Importing existing certificates

Place certificate.pem and private.key (and chain.pem when you have one) under the directory named by Certificates::certificateName($domain). exists() checks for certificate.pem; get() lists every stored certificate by its common name; status() parses the leaf for expiry, issuer, serial, fingerprint and SANs, so imported material is registered with its real expiry. Without self_signed, issuing a name with no stored PEM throws CertificateException — import the material first — and renewing material nobody replaced fails as not renewed (same fingerprint). Pull stored certificates into the registry with:

php artisan certificates:sync --driver=filesystem

Self-signed certificates

With self_signed on, every issue and renewal mints fresh self-signed material covering every requested domain (subjectAltName included), valid for self_signed_days — so a renewal really moves the expiry. A PEM a real CA issued is never overwritten with a self-signed one.

CERTIFICATES_FS_DISK=local
CERTIFICATES_FS_PATH=certificates
CERTIFICATES_FS_SELF_SIGNED=true
CERTIFICATES_FS_SELF_SIGNED_DAYS=90

Show your open-source love

This package is free and MIT-licensed. If it saves you time, a one-off donation or a Patreon membership keeps it maintained, tested and documented.

More ways to support, including crypto

By donating, you agree to our donation terms.

Want this built into your product?

We integrate our packages into custom Laravel and AI builds. Tell us what you're working on and we'll reply within 48 hours.