---
title: "Configuration — Media Library for Laravel | Roundly"
description: "Every config key and its default — disks, image driver, remote fetches, dedup, placeholders, responsive and CDN."
url: https://roundly-consulting.com/open-source/docs/media-library-for-laravel/configuration
language: en
---

[All packages](https://roundly-consulting.com/open-source.md)

[Media Library for Laravel](https://roundly-consulting.com/open-source/docs/media-library-for-laravel.md)

# Configuration

The package works with zero host configuration — every key has a default, and the common ones are env-backed. The published config/media.php in full:

```php
return [
    'disk' => env('MEDIA_DISK', 'public'),
    'variants_disk' => env('MEDIA_VARIANTS_DISK'),

    'media_model' => RoundlyConsulting\MediaLibrary\Models\Media::class,
    'table_name' => 'media',

    'queue_variants_by_default' => false,
    'queue_connection' => env('MEDIA_QUEUE_CONNECTION'),
    'queue_name' => env('MEDIA_QUEUE'),

    'image_driver' => env('MEDIA_IMAGE_DRIVER', 'imagick'),
    'max_image_pixels' => 50_000_000,
    'variant' => [
        'quality' => 75,
        'background' => '#ffffff',
    ],

    'url_fallback_to_original' => false,
    'temporary_url_default_lifetime' => 5,

    'stream' => [
        'enabled' => env('MEDIA_STREAM_ENABLED', true),
        'route_prefix' => 'media',
        'middleware' => ['web'],
    ],

    'path_generator' => RoundlyConsulting\MediaLibrary\Support\DefaultPathGenerator::class,
    'file_namer' => RoundlyConsulting\MediaLibrary\Support\DefaultFileNamer::class,

    'default_visibility' => 'public',
    'max_file_size' => 1024 * 1024 * 256,

    'remote' => [
        'headers' => [],
        'timeout' => 30,
        'fetch_max_bytes' => 5_000_000,
        'max_redirects' => 5,
        'allowed_ports' => null,
        'forward_headers_on_redirect' => false,
        'block_private_networks' => true,
        'allowed_private_hosts' => [],
    ],

    'deduplicate' => true,
    'checksum_algorithm' => 'sha256',          // sha256|sha384|sha512|sha512/256|sha3-256|sha3-384|sha3-512
    'verify_checksum_on_read' => false,

    'placeholders' => [
        'thumbhash' => true,
        'blurhash' => true,
    ],

    'responsive' => [
        'widths' => [320, 640, 960, 1280, 1920],
    ],

    'drafts' => [
        'ttl' => 1440,
    ],

    'url_generator' => RoundlyConsulting\MediaLibrary\Support\DefaultUrlGenerator::class,
    'cdn' => [
        'enabled' => false,
        'base_url' => env('MEDIA_CDN_URL'),
        'cache_bust' => true,
        'disks' => [],
    ],
];
```

## Every key

| Key | Default | Purpose |
| --- | --- | --- |
| `disk` | public | Default disk for originals (MEDIA\_DISK). A blank value is not set, so public applies; a non-string value throws. |
| `variants_disk` | null | Default disk for variants (MEDIA\_VARIANTS\_DISK); null or blank (not set) = the original's disk. A non-string value throws. |
| `media_model` | Media::class | Eloquent model that persists media. Must be the packaged Media model or a subclass of it; anything else throws InvalidConfigurationException. |
| `table_name` | media | Database table the media model uses. A blank value is not set, so media applies; a non-string value throws. |
| `queue_variants_by_default` | false | Queue all variant generation by default. |
| `queue_connection` | null | Queue connection for GenerateVariantsJob (MEDIA\_QUEUE\_CONNECTION); null = the default connection. |
| `queue_name` | null | Queue name for GenerateVariantsJob (MEDIA\_QUEUE); null = the default queue. |
| `image_driver` | imagick | imagick or gd (MEDIA\_IMAGE\_DRIVER); anything else throws. With imagick configured but the extension missing, gd is used. |
| `max_image_pixels` | 50,000,000 | The largest image (width × height, read from the header) decoded for variants and placeholders; a bigger one is stored without either. null or blank (not set) = no cap, otherwise at least 1. |
| `variant.quality` | 75 | Default JPEG/WebP quality (1–100). |
| `variant.background` | #ffffff | Flatten colour when a transparent image is converted to JPEG. |
| `url_fallback_to_original` | false | When getUrl() is asked for an un-generated variant: throw (false) or return the original’s URL (true). |
| `temporary_url_default_lifetime` | 5 | Default minutes (at least 1) for signed/temporary URLs when no expiry is passed. |
| `stream.enabled` | true | Register the signed streaming route (MEDIA\_STREAM\_ENABLED, read as a boolean; anything else throws). |
| `stream.route_prefix` | media | URI prefix for the streaming route. |
| `stream.middleware` | \['web'\] | Middleware stack for the streaming route; Laravel’s signed is always appended. |
| `path_generator` | DefaultPathGenerator::class | Directory layout for a media’s files. A class that is not a PathGenerator throws when resolved. |
| `file_namer` | DefaultFileNamer::class | Original and variant file naming. A class that is not a FileNamer throws when resolved. |
| `default_visibility` | public | public or private for new media when a bucket or add doesn’t set it. Anything else throws — a typo is never stored (it would read as public). |
| `max_file_size` | 256 MB | Package-level size cap, enforced on every add (and remote download) and emitted by the derived rules; a bucket’s maxFileSize() overrides it. null or blank (not set) = no limit, otherwise at least 1 byte. |
| `remote.headers` | \[\] | Extra HTTP headers (name ⇒ value) for remote fetches — addFromUrl() and MediaLibrary::remote()->fetch(). Sent to the URL’s own origin (scheme, host, port) only, unless forward\_headers\_on\_redirect is on. A Host header throws: the host is the URL’s own. |
| `remote.timeout` | 30 | Time budget in seconds (at least 1) for one remote fetch, every redirect hop included. |
| `remote.fetch_max_bytes` | 5,000,000 | Byte cap of MediaLibrary::remote()->fetch() (at least 1), counted after decoding. addFromUrl() is capped by max\_file\_size instead. |
| `remote.max_redirects` | 5 | Redirects (301, 302, 303, 307, 308) a remote fetch follows, each vetted like the first hop; 0 follows none. |
| `remote.allowed_ports` | null | null = any port 1–65535; otherwise a non-empty list of the ports a remote URL may use (default ports count, so \[443\] refuses plain http://). An empty list or a port outside 1–65535 throws. |
| `remote.forward_headers_on_redirect` | false | Send remote.headers to another origin a redirect points at as well. |
| `remote.block_private_networks` | true | SSRF guard for remote fetches: canonicalise every hop, refuse a host that is, resolves to or redirects to a private, loopback, link-local, carrier-grade NAT, cloud-metadata or other reserved address or is localhost by name, pin every vetted address and bypass the environment’s proxy. false turns it off for fetches — only for URLs you trust completely; vet() and SafeRemoteUrl judge either way. |
| `remote.allowed_private_hosts` | \[\] | Exempt from the guard: exact host names (case-insensitive), addresses and address/prefix ranges, e.g. \['minio.internal', '10.0.5.0/24', 'fd00::/8'\]. A host name listed here is fetched without resolution, address check or pin. A blank entry or a malformed range throws. |
| `deduplicate` | true | Reuse storage for identical bytes. |
| `checksum_algorithm` | sha256 | Content checksum (dedup key + integrity): sha256, sha384, sha512, sha512/256, sha3-256, sha3-384 or sha3-512 — anything else throws InvalidConfigurationException. Changing it is safe: verification tries every accepted algorithm with the stored digest length, though new uploads no longer deduplicate against rows hashed the old way. |
| `verify_checksum_on_read` | false | Re-hash on read; throws on drift. |
| `placeholders.thumbhash` | true | Compute a ThumbHash LQIP on add. |
| `placeholders.blurhash` | true | Compute a Blurhash LQIP on add. |
| `responsive.widths` | \[320…1920\] | Default responsive srcset ladder (positive integers), overridable per bucket. |
| `drafts.ttl` | 1440 | Minutes (at least 1) before an unbound draft is prunable. |
| `url_generator` | DefaultUrlGenerator::class | URL building strategy. Takes precedence over the CDN generator; a class that is not a UrlGenerator throws when resolved. |
| `cdn.enabled` | false | Rewrite public URLs onto a CDN host. |
| `cdn.base_url` | null | CDN base URL (MEDIA\_CDN\_URL), e.g. https://cdn.example.com. |
| `cdn.cache_bust` | true | Append ?v={updated\_at} to public URLs. |
| `cdn.disks` | \[\] | Limit CDN rewriting to these disks; \[\] = all public disks. |

Every bool switch is parsed as a boolean wherever it is read: true/1/on/yes turn it on and false/0/off/no turn it off, so a switch you feed from .env in your published config behaves as written. A blank value (MEDIA\_STREAM\_ENABLED=) is not set, so the default applies. Anything else (say MEDIA\_STREAM\_ENABLED=disabled) throws InvalidConfigurationException instead of quietly reading as the default.

Every other setting is read just as strictly. A setting that is not set — absent, null, or blank like a host’s MEDIA\_VARIANTS\_DISK= — takes its default, and an optional one (variants\_disk, the queue connection and name, max\_file\_size, max\_image\_pixels, cdn.base\_url) stays unset; a blank path\_generator, file\_namer or url\_generator binds the packaged class. Integers accept an int or a plain integer string (every env value is a string), so thirty or 5.5 throws rather than becoming 0 — which for remote.timeout would have meant no timeout at all. A non-string disk, queue, table name, route prefix, background or CDN base URL throws, and so does a default\_visibility, image\_driver or checksum\_algorithm typo, or a junk entry in a width, middleware, header or CDN-disk list. php artisan about renders a broken setting as INVALID.

The presigned-s3 disk driver reads its own keys (presign\_endpoint, presign\_use\_path\_style\_endpoint) from the disk’s entry in config/filesystems.php, not from config/media.php — see URLs, streaming & downloads.

## Environment

The common knobs are env-driven, so you rarely publish the config at all:

```bash
MEDIA_DISK=public
MEDIA_VARIANTS_DISK=s3
MEDIA_IMAGE_DRIVER=imagick
MEDIA_STREAM_ENABLED=true
MEDIA_CDN_URL=https://cdn.example.com
```

## 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](https://roundly-consulting.com/support-us.md)

By donating, you agree to our [donation terms](https://roundly-consulting.com/donation-terms.md).

[Support our open source work (opens in a new tab)](https://donate.stripe.com/dRmeVe8FX5PF1Qd9pXcEw00) [Join us on Patreon (opens in a new tab)](https://www.patreon.com/cw/roundly)

## 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.

[Get a quote in 48 hours](https://roundly-consulting.com/contact.md) [Browse all packages](https://roundly-consulting.com/open-source/docs/media-library-for-laravel.md)
