Configure NextPDF Gotenberg
At a glance
Section titled “At a glance”Configuration has two parts: the immutable GotenbergConfig value
object, which describes the service and its limits, and the
GotenbergBridge constructor, which receives the PHP Standard
Recommendation (PSR) collaborators for Hypertext Transfer Protocol
(HTTP). You provide both through explicit constructor injection. The
package has no global state, reads no environment variables, and defines
no hidden default endpoint.
The configuration object
Section titled “The configuration object”GotenbergConfig is a final readonly value object. Create it
directly with named arguments, or build it from an associative array
with GotenbergConfig::fromArray().
Fields
Section titled “Fields”| Field | Type | Default | Effect |
|---|---|---|---|
apiUrl | string | '' | Base Uniform Resource Locator (URL) for the Gotenberg service. Required: an empty value makes the config invalid and every conversion fails fast. Must use Hypertext Transfer Protocol Secure (HTTPS). |
timeout | int | 30 | Hard transfer timeout in seconds. The cURL-pinned transport applies it when selected. |
maxFileSize | int | 52_428_800 | Maximum input size in bytes (50 MiB). Inputs larger than this are rejected before any request. |
apiKey | string | '' | Bearer token. When non-empty it is sent as an Authorization: Bearer <token> header. Marked #[\SensitiveParameter] so it is redacted in stack traces. |
pinnedPublicKeys | list<string> | [] | Primary Transport Layer Security (TLS) SubjectPublicKeyInfo (SPKI) pins in sha256/<base64> form. Empty disables pinning. |
backupPublicKeys | list<string> | [] | Backup TLS SPKI pins, kept separate so rotation can be validated independently. |
Constructing directly
Section titled “Constructing directly”<?php
declare(strict_types=1);
use NextPDF\Gotenberg\GotenbergConfig;
$config = new GotenbergConfig( apiUrl: 'https://gotenberg.example.com', timeout: 60, maxFileSize: 20 * 1024 * 1024, apiKey: $secretFromYourSecretStore,);Constructing from an array
Section titled “Constructing from an array”fromArray() accepts snake_case keys and ignores malformed values
instead of throwing. Non-string api_url becomes ''. Non-int
timeout falls back to 30. Non-int max_file_size falls back to the
50 MiB default. Non-array pin lists become []. Non-string entries
inside the pin arrays are dropped.
<?php
declare(strict_types=1);
use NextPDF\Gotenberg\GotenbergConfig;
$config = GotenbergConfig::fromArray([ 'api_url' => 'https://gotenberg.example.com', 'timeout' => 45, 'max_file_size' => 20_000_000, 'api_key' => $secretFromYourSecretStore, 'pinned_public_keys' => ['sha256/YLh1dUR9y6Kja30RrAn7JKnbQG/uEtLMkBgFF2Fuihg='], 'backup_public_keys' => ['sha256/Vjs8r4z+80wjNcr1YKepWQboSIRi63WsWXhIMN+eWys='],]);This forgiving parsing is deliberate. You can pass a framework configuration array directly, without a pre-validation layer, and still get a well-typed object. It does not verify that the URL is reachable or that the pins are correct. The bridge performs those checks at conversion time.
Validity
Section titled “Validity”isValid() returns true only when apiUrl is a non-empty string. It
performs no network or scheme checks. The security policy handles HTTPS
and private-address screening at conversion time. If the config is
invalid, convertFile() and convertString() throw a
GotenbergConvertException with the message Invalid Gotenberg configuration: apiUrl is empty.
An invalid config also makes isAvailable() return false without any
network call.
The bridge constructor
Section titled “The bridge constructor”GotenbergBridge receives the configuration plus the PSR collaborators:
| Argument | Type | Required | Effect |
|---|---|---|---|
config | GotenbergConfig | yes | The service descriptor and limits described above. |
httpClient | Psr\Http\Client\ClientInterface | yes | The PSR-18 client used for the health probe and fallback transport. |
requestFactory | Psr\Http\Message\RequestFactoryInterface | yes | Builds the PSR-7 request. |
streamFactory | Psr\Http\Message\StreamFactoryInterface | yes | Builds the request body stream. |
logger | Psr\Log\LoggerInterface|null | no (default null) | When supplied, logs one debug-level entry per conversion request. |
htmlSecurityPolicy | HtmlSecurityPolicyInterface|null | no | Defaults to the core Hypertext Markup Language (HTML) security policy. Applies at the parse layer and complements the transport-layer policy. |
responseFactory | Psr\Http\Message\ResponseFactoryInterface|null | no (default null) | Required to activate the cURL-pinned transport. Without it the bridge always uses the injected PSR-18 client. |
<?php
declare(strict_types=1);
use NextPDF\Gotenberg\GotenbergBridge;
$bridge = new GotenbergBridge( config: $config, httpClient: $psrHttpClient, requestFactory: $psrRequestFactory, streamFactory: $psrStreamFactory, logger: $psrLogger, responseFactory: $psrResponseFactory,);Transport selection
Section titled “Transport selection”The bridge supports two transports and selects one for each conversion request:
- cURL-pinned transport — used when a
responseFactorywas injected and there is something to pin (the URL resolved to one or more Internet Protocol (IP) addresses, or SPKI pins are configured). This transport binds the resolved address set withCURLOPT_RESOLVE. It enforces SPKI pinning withCURLOPT_PINNEDPUBLICKEYwhen pins are present. It verifies the peer and host (CURLOPT_SSL_VERIFYPEER,CURLOPT_SSL_VERIFYHOST = 2). It applies the configured timeout and disables redirect following (CURLOPT_FOLLOWLOCATION = false,CURLOPT_MAXREDIRS = 0). - Injected PSR-18 client — used in every other case, including when
the application programming interface (API) URL is a bare public IP
literal (no Domain Name System (DNS) to pin) and no SPKI pins are
configured, or when no
responseFactorywas supplied.
For DNS-rebinding-resistant connections and TLS pinning, inject a
responseFactory and configure pins. The health probe always uses the
injected PSR-18 client, regardless of transport selection.
TLS public-key pinning
Section titled “TLS public-key pinning”Pinning uses the Secure Hash Algorithm 256-bit (SHA-256) SPKI
fingerprint model. Each pin is a string of the form
sha256/<base64-encoded-spki-hash>. The transport also accepts the
cURL-native sha256//<base64> form and converts the single-slash form to
it. Any other prefix raises an InvalidSpkiPinException.
allPublicKeyPins() returns the de-duplicated union of
pinnedPublicKeys and backupPublicKeys. The TLS layer accepts a
certificate whose SPKI hash matches any member of that combined set.
For operations, configure at least one backup pin so that a planned
certificate or key rotation does not lock the bridge out of the service
while the new key propagates. Keeping the backup list separate from the
primary list lets you validate and rotate the backup pin independently
of the active one. See /integrations/gotenberg/security-and-operations/ for the
rotation procedure.
Per-request conversion options
Section titled “Per-request conversion options”The multipart payload type (GotenbergConvertPayload) carries the file
plus two optional Gotenberg conversion options:
landscape(bool, defaultfalse) — sent as thelandscapeform field with"true"or"false".nativePageRanges(string, default'') — sent as anativePageRangesform field only when non-empty; accepts Gotenberg’s range syntax, such as1-3or1,3,5-9.
The public convertFile() and convertString() entry points build the
payload with the defaults for both fields. The fields are part of the
payload contract, and the test suite exercises them. Expose them from
your integration layer if you need landscape output or page selection.
See also
Section titled “See also”- /integrations/gotenberg/install/ — installation and the Gotenberg baseline.
- /integrations/gotenberg/quickstart/ — a runnable end-to-end example.
- /integrations/gotenberg/production-usage/ — config sourcing, secrets, timeouts, retries.
- /integrations/gotenberg/security-and-operations/ — the full security model and pin rotation.
- /integrations/gotenberg/troubleshooting/ — configuration-related exception meanings.