TYPO3 Site Handling: Minimal Architecture for a Single‑Domain Site
Learn the smallest viable site‑configuration, where trust boundaries lie, and how to verify and evolve the design as requirements grow.
21 Sept 2026, 03:58 UTC

Problem: Mapping hostnames to site roots without legacy sys_domain
When you install TYPO3, the old sys_domain table is no longer used for site resolution. Instead, site handling relies on YAML files under config/sites/. If you simply copy a multi‑site example, you may end up with unnecessary identifiers, duplicate language entries, or misrouted requests that produce 404s or redirect loops. The useful takeaway is that a single‑domain site needs only one site identifier, one base URL, and one language entry; everything else can be added later as the project evolves.
Requirements
TYPO3 Site Handling must:
- Map the request’s
Hostheader (and optional port or path prefix) to a site root defined inconfig/sites/<identifier>/config.yaml. - Resolve the language variant for the site, falling back to the default language when no prefix matches.
- Make the resolved site available to the frontend rendering pipeline and to backend link generation.
These requirements replace the legacy domain‑to‑page tree mapping and are satisfied by a single YAML file per site.
Smallest suitable design
For a site that answers to one hostname (e.g., www.example.com) and uses only the default language, the minimal configuration consists of:
- One site identifier (any string that is unique within the installation, used in backend URLs and cache tags).
- A
base:value of/(the site root is the web document root). - One language entry with
languageId: 0(the default language) and nolocaleorlanguagePrefixunless you want explicit prefixes.
Example YAML (config/sites/example/config.yaml):
# config/sites/example/config.yaml
rootPageId: 1
base: '/'
languages:
- title: 'Default'
enabled: true
languageId: 0
locale: ''
iso-639-1: ''
hreflang: ''
direction: ''
flag: ''
languageIdInMenu: 0
No routeEnhancers or custom slug configuration is required; TYPO3’s built‑in slug routing will generate URLs like /about-us automatically.
Trust and data boundaries
The web server (Apache, Nginx, IIS, etc.) must forward the request’s Host header unchanged to TYPO3’s entry point (index.php). If the server is configured to accept any host and pass it through, an attacker can supply a malicious Host header that TYPO3 will match against its site configurations. This creates a trust boundary:
- Before the boundary: The web server decides which
Hostvalues are allowed. - After the boundary: TYPO3 trusts the
Hostvalue it receives and uses it to select a site.
To keep the boundary safe, configure the web server to restrict the Host header to the expected hostname(s) (e.g., via server_name in Nginx or ServerName/ServerAlias in Apache).
Operational checks
After adding or modifying a site configuration, perform these checks:
- File validity: Ensure the YAML is parsable (
php -l config/sites/example/config.yamlor a YAML linter) and readable by the PHP-FPM/web‑server user. - Backend verification: Log into the TYPO3 backend, go to Site Management, and confirm that the identifier, base URL, and root page ID appear as expected.
- Cache flush: Run
./vendor/bin/typo3cms cache:flush(requires CLI access with the same filesystem permissions as the web process) to clear cached site‑resolution data. - Frontend test: Request the site with the production
Hostheader (e.g.,curl -I -H "Host: www.example.com" https://www.example.com/) and verify:- HTTP 200 (or a redirect to the canonical URL if you enforce trailing slashes).
- No redirect loops.
- The response contains a
<link rel="canonical" href="https://www.example.com/"/>tag that matches the configured base.
- Link inspection: View a rendered page source and check that generated links use the base URL and no unexpected language prefix (since we rely on the default language).
Failure modes
Common ways the minimal design can break:
- Misconfigured base URL: Setting
base: /sub/when the site is actually served from the document root causes TYPO3 to prepend/sub/to every URL, leading to 404s or redirect loops. - Duplicate or missing identifiers: Two site configurations with the same identifier cause cache‑tag collisions; a missing identifier results in a "Site not found" exception when the
Hostheader matches no configuration. - Unmatched Host header: If the web server forwards an arbitrary
Host(e.g., a default catch‑all vhost), TYPO3 may select the first site in the list or throw an exception, producing incorrect content or error pages. - Cache corruption after renaming: Changing the site identifier after content has been indexed leaves stale cache tags; links that still contain the old identifier may break until caches are flushed.
Conditions that change the design
The minimal design remains sufficient until one of the following triggers appears:
- Multiple domains or sub‑domains: You need a separate site identifier for each hostname, each with its own
base(possibly with a path prefix) and possibly distinct language variants. - Additional languages: Adding a second language requires a second entry in the
languageslist, with a uniquelanguageIdand optionally alanguagePrefix(e.g.,/en/or/de/). - Complex information architecture: When you need custom URL patterns (e.g., news articles under
/blog/<year>/<title>) you introducerouteEnhancersand possiblyslugconfiguration. - Headless or decoupled frontend: If the TYPO3 backend serves only JSON/API endpoints, you may split site handling: one site configuration for the traditional rendered frontend and another (or none) for the API, requiring separate caching strategies and possibly different base URLs.
When any of these conditions arise, revisit the site‑configuration files, add the necessary identifiers, language entries, or route enhancers, and repeat the operational checks outlined above.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.