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

Certificates::for() returns a CertificateBuilder — the handle for one domain. Every setter returns the builder, so you describe the certificate and finish with a terminal call:

use RoundlyConsulting\Certificates\Facades\Certificates;

$certificate = Certificates::for('shop.example.com')
    ->alsoFor('www.shop.example.com')
    ->using('acme')
    ->validForDays(90)
    ->meta(['tenant' => '7'])
    ->owner($tenant)        // attaches via the HasCertificates morph
    ->issue();

Setters

MethodEffect
alsoFor(string ...$domains)Append SAN domains to one multi-domain certificate.
using(string $driver)Driver for this issuance; also scopes find(), issueIfMissing() and statusReport().
validForDays(int $days)Fallback expiry when the driver reports none (default 90).
meta(array $meta)Stored in the registry’s meta JSON column.
owner(Model $owner)Associates the certifiable owner.
fresh(bool $fresh = true)Bypass the status cache for statusReport().

The issuer and namespace are driver configuration, not per-certificate options: the kubernetes driver always uses drivers.kubernetes.issuer, issuer_kind and namespace. For a second issuer or namespace, register another driver with Certificates::extend() and pick it with using().

Terminal methods

$builder = Certificates::for('shop.example.com')->using('acme');

$builder->issue();                 // Certificate — always provisions
$builder->issueIfMissing();        // Certificate — the active record, or a new issuance
$builder->exists();                // bool
$builder->status();                // ?CertificateStatus
$builder->find();                  // ?Certificate
$builder->fresh()->statusReport(); // ?CertificateStatusReport — cache bypassed

// Lifecycle verbs on the domain's registry row — the acme row only, because of using().
$builder->renew();                 // Certificate — renewed now
$builder->renewLater();            // Certificate — RenewCertificateJob queued
$builder->revoke('key compromise'); // Certificate — Revoked + CertificateRevoked
$builder->expire();                // Certificate — Expired + CertificateExpired
MethodReturnsBehaviour
issue()CertificateAlways provisions and records.
issueIfMissing()CertificateReturns the latest active record for the driver, otherwise issues.
exists()boolAsks the default provider about the primary domain.
status()?CertificateStatusRegistry status of the latest record.
find()?CertificateLatest registry record, filtered by using().
statusReport()?CertificateStatusReportLive report from the using() driver (or the default), cache-aware.
renew()CertificateRenew the domain’s registry row now.
renewLater()CertificateQueue RenewCertificateJob for that row.
revoke(?string $reason = null)CertificateRecord a revocation of that row.
expire()CertificateMark that row expired.

The lifecycle verbs resolve the domain’s most recent registry row — on the using() driver when set — and call the matching manager method, so Certificates::fake() records them. No row throws CertificateException; the handle never falls back to another domain’s row, or to the same domain’s row under another driver.

for() also accepts a list of domains — the first is the primary, the rest become SANs (see Multi-domain & wildcards). Build the handle with Certificates::for() — its constructor is internal. Like the manager, the builder is macroable.

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.