typo3-fal-s3 — TYPO3 files in S3, without a network drive and without new addresses.
TYPO3 keeps images and downloads in the fileadmin folder. When that folder lives in object storage such as Amazon S3, it is usually mounted as a network drive. That is slow, needs special privileges and breaks at the wrong moment. typo3-fal-s3 is a storage driver for TYPO3 that talks to S3 directly. The switch happens in place: files, references and addresses on the website stay as they are.
- What it is: a driver for TYPO3's file abstraction layer (FAL) that connects Amazon S3 and S3-compatible storage
- Who it is for: operators of TYPO3 websites who keep their media in S3, for example in Kubernetes without a shared disk
- Tech: TYPO3 extension · TYPO3 14.3+ · PHP 8.5+ · async-aws · MIT licence · source on GitHub
TL;DR — Does this fit my setup?
Use it if …
- your TYPO3 website keeps its media in an S3 bucket and mounts it as a network drive (FUSE mount) today
- several servers or pods should see the same files without a shared disk
- no access keys should sit in TYPO3; the driver uses the identity of the server or pod
Don't use it if …
- you still run TYPO3 13 or older; the driver requires TYPO3 14.3
- files in the bucket sit in archive storage classes such as Glacier; they can only be read after a restore
- nothing delivers the files; the driver manages them, delivery is the job of the web server or a CDN
Effort
One Composer package, one command to switch the storage and the name of the bucket. The way back is the same command with the old driver.
Why no network drive, and what the driver does differently
The problem
A mounted bucket pretends S3 is a disk. Every check whether a file exists becomes a request over the network. The server needs extended privileges for it, and when the drive hangs, the whole website hangs. In Kubernetes there is an extra service on every node that only provides the drive.
The solution
typo3-fal-s3 talks to S3 directly, as a driver in TYPO3's file abstraction layer. It keeps the folder structure of the bucket. That is why an existing storage can be switched without TYPO3 having to re-index a single file.
| What | How the driver handles it |
|---|---|
| File addresses | stay the same, /fileadmin/… by default |
| Access to S3 | through the identity of the server or pod, no key in TYPO3 |
| Repeated lookups | answers from S3 land in a shared cache; a folder costs one request, not one per file |
| Two servers write the same image variant | both succeed, neither overwrites the other |
| Image variants | live in the bucket and carry a long cache lifetime |
| Other data in the same bucket | is hidden and read-only |
In production
Since October 2026 the driver runs on four TYPO3 websites in Kubernetes. Before, every pod had a network drive with the bucket attached. The switch went website by website, with the drive as a fallback, until everything ran clean.
- The pods no longer have a fileadmin drive and need no special privileges for it.
- Each website reads and writes with its own role that only sees its bucket.
- No file had to be re-indexed, no address changed.
The files are delivered by the website's web server. To make that fast, caddy-fs-s3cache keeps a local copy.
fileadmin still mounted as a network drive? I help with the switch, the permissions and the delivery. Get in touch →
Installation and configuration
For operators of a TYPO3 14 website. Three steps.
1. Install the package
composer require koh/typo3-fal-s3
2. Name the bucket
Every setting can come from an environment variable, so the record in TYPO3 stays the same for all environments.
KOH_FAL_S3_BUCKET=my-media-bucket
KOH_FAL_S3_REGION=eu-north-1
3. Switch the storage
vendor/bin/typo3 koh_fal_s3:storage --uid 1 --driver KohS3
vendor/bin/typo3 cache:flush
The command remembers the old setting. --driver Local restores it.
The main options
| Option | Default | Meaning |
|---|---|---|
bucket | required | Name of the S3 bucket |
region, endpoint, pathStyle | from the AWS configuration | AWS region; own endpoint and path-style addressing for S3-compatible storage such as MinIO or RustFS |
keyPrefix | empty | Only a subfolder of the bucket becomes the storage |
publicBaseUri | /fileadmin/ | The address under which the web server delivers the files |
excludedPrefixes | a few known folders | Parts of the bucket TYPO3 neither sees nor writes |
malwareGate | off | Refuses files that the AWS malware scan has marked as dangerous |
fallbackProcessingFolder | off | Puts the image variants from extensions into the bucket as well instead of the local disk |
Permissions
The driver needs the right to list the bucket (s3:ListBucket). Without it, S3 answers “forbidden” instead of “not found” for a missing file. On the files it needs read, write and delete. Credentials are not stored in TYPO3. Like with every AWS tool, they come from the environment or, in Kubernetes, from the identity of the pod.
Common pitfalls
- The driver does not deliver files. It produces addresses such as
/fileadmin/image.jpg. Under that address the web server has to fetch the file from the bucket, for example with caddy-fs-s3cache or through a CDN. Without that part, images stay empty. - The shared cache belongs in Redis or Valkey. By default it sits in the database, which is enough to start. A cache in memory only makes every page request ask S3 again.
- Archive storage classes lock files. A file in Glacier or an archive tier of Intelligent-Tiering can only be read after a restore. For a website, keep these tiers switched off.
- Changes made outside TYPO3 show up later. What another system writes directly into the bucket, TYPO3 notices when the cache expires, after one day by default. The period is configurable.
fileadmin in S3 without a network drive?
If your TYPO3 website fetches its media from S3 through a mounted drive, typo3-fal-s3 helps. I support the switch, the permissions in AWS and the delivery through the web server.
Or email me directly: mail@ole-hartwig.eu