Safe and Reproducible Version Control Architecture for TYPO3 CMS
Contents
Abstract
Version-controlling an enterprise Content Management System (CMS) introduces fundamental tensions absent in pure software projects. Naive Git tracking inevitably causes database desynchronization, severe repository bloat from binary uploads, catastrophic credential leaks, and race conditions during production releases. This paper formulates an authoritative, production-tested blueprint for establishing version control on TYPO3 v13 installations.
We present a rigorous separation model distinguishing Code and Configuration from Content, Runtime Caches, and Environment Secrets. We introduce dynamic secret decoupling via TYPO3's additional.php override mechanism, provide an exhaustive .gitignore rule-matrix, examine the architectural advantages of Modern Composer mode over Classic tarball layouts, and define an atomic zero-downtime deployment pipeline with automated schema synchronization and cache invalidation.
1.Introduction
TYPO3 is an enterprise open-source Content Management Framework renowned for its extensibility, multi-site architecture, and strict security posture. However, deploying a fresh TYPO3 instance to a live Linux server (e.g., at /var/www/html/typo3) frequently leaves engineering teams with a critical architectural dilemma: How do we apply Version Control Systems (VCS) to a live system without breaking its runtime integrity or leaking sensitive infrastructure credentials?
git add . on a web root tracks volatile
temporary files, exposes database passwords stored in configuration arrays, and tracks thousands of media
uploads in Git's object database, permanently bloating the .git directory.
A professional VCS architecture ensures that a project can be cloned by any engineer, deployed through automated CI/CD runners, and recovered after hardware failure with 100% deterministic reproducibility.
2.The Core Separation Principle
Enterprise CMS architecture divides a running website into four orthogonal tiers. Only two of these tiers belong in Git.
| System Tier | Track in Git? | Path / Artifacts | Architectural Rationale |
|---|---|---|---|
| Code & Templates | Mandatory | typo3conf/ext/site_package/ |
Fluid templates, TypoScript constants/setup, backend controllers, frontend SCSS/JS assets. |
| Site Configuration | Mandatory | typo3conf/sites/*/config.yaml |
Deterministic routing, multi-language mapping, error handlers, and domain definitions. |
| User Media (Content) | Never | /fileadmin/ |
Binary assets uploaded by content editors. Must be backed up via S3 or rsync, not Git blobs. |
| Volatile Cache | Never | /typo3temp/, /var/cache/ |
Dynamic PHP opcode caches, fluid compile artifacts, processed thumbnail images. |
| Secrets & DB Keys | Never | settings.php, .env |
Production database credentials, Argon2i install tool hashes, encryption keys. |
3.Secret Isolation Threat Modeling
In TYPO3 v12 and v13, the primary configuration array resides in settings.php (located at typo3conf/system/settings.php in Classic mode or config/system/settings.php in Composer mode). By default, this file stores sensitive parameters in plain text:
Committing settings.php with plain-text ['DB']['Connections']['Default']['password'] or ['BE']['installToolPassword'] to Git repositories (especially remote repositories like GitHub or GitLab) violates basic compliance (OWASP Top 10, GDPR Article 32) and exposes your database to trivial compromise.
The Decoupling Strategy: additional.php + Environment Variables
TYPO3 provides a dedicated bootstrap hook: immediately after loading settings.php, it checks for and executes additional.php. We utilize this to inject infrastructure secrets at runtime without hardcoding them into tracked files.
<?php
defined('TYPO3') or die('Access denied.');
/**
* Enterprise Secret Isolation Layer
* Reads infrastructure credentials dynamically from OS environment or .env
*/
$dbHost = getenv('TYPO3_DB_HOST') ?: '127.0.0.1';
$dbName = getenv('TYPO3_DB_NAME') ?: 'typo3';
$dbUser = getenv('TYPO3_DB_USER') ?: 'typo3';
$dbPass = getenv('TYPO3_DB_PASSWORD');
if ($dbPass !== false) {
$GLOBALS['TYPO3_CONF_VARS']['DB']['Connections']['Default']['host'] = $dbHost;
$GLOBALS['TYPO3_CONF_VARS']['DB']['Connections']['Default']['dbname'] = $dbName;
$GLOBALS['TYPO3_CONF_VARS']['DB']['Connections']['Default']['user'] = $dbUser;
$GLOBALS['TYPO3_CONF_VARS']['DB']['Connections']['Default']['password'] = $dbPass;
}
// Ensure Install Tool password hash can also be injected via environment
if ($installToolHash = getenv('TYPO3_INSTALL_TOOL_PASSWORD')) {
$GLOBALS['TYPO3_CONF_VARS']['BE']['installToolPassword'] = $installToolHash;
}
4.Production-Grade .gitignore Strategy
Below is the definitive, field-tested .gitignore configuration tailored specifically for modern TYPO3 installations running under Linux.
# ==============================================================================
# Enterprise TYPO3 v13 Version Control Rules
# ==============================================================================
# 1. Credentials and Environment Variables
.env
.env.*
!.env.example
typo3conf/system/settings.php
# 2. Uploaded Media & Binary Storage (Managed via independent backup)
/fileadmin/
!/fileadmin/.gitkeep
# 3. Volatile Cache, Transpiled Assets, and Compilations
/typo3temp/*
!/typo3temp/.gitkeep
/var/cache/
/var/log/
/var/lock/
# 4. Core & External Dependencies (Installed via Composer / Release Archive)
/vendor/
/typo3/
/bin/
# 5. Localization / Translation Data (Downloaded from Crowdin)
/typo3conf/l10n/
# 6. Third-Party Extensions (Track only YOUR in-house site package)
/typo3conf/ext/*
!/typo3conf/ext/site_package/
!/typo3conf/ext/*_sitepackage/
# 7. Operating System & IDE Artifacts
.DS_Store
Thumbs.db
.idea/
.vscode/
*.log
*.sql
*.tar.gz
5.The Sitepackage Pattern
A common legacy mistake is configuring TYPO3 templates through the backend Database Template module (SysTemplate) and storing CSS/JS files directly inside fileadmin/.
The Sitepackage Pattern encapsulates all visual design, layout logic, custom content elements, and configurations into a dedicated, version-controlled extension:
Structure of site_package
typo3conf/ext/site_package/
├── Configuration/
│ ├── TypoScript/
│ │ ├── setup.typoscript
│ │ └── constants.typoscript
│ └── Sets/SitePackage/
├── Resources/
│ ├── Private/
│ │ ├── Layouts/
│ │ ├── Partials/
│ │ └── Templates/
│ └── Public/
│ ├── Css/
│ ├── Js/
│ └── Icons/
├── composer.json
└── ext_emconf.phpArchitectural Advantages
- Single Source of Truth: Frontend designers commit code directly to Git; no backend copy-pasting.
- Audit Trail: Every template change, button color tweak, or grid revision has a traceable Git commit hash and author.
- Zero DB Dependency for Layouts: Site structure loads from files, not fragile database records.
- Seamless Automated Testing: Fluid templates and custom PHP controllers can be tested with PHPUnit in CI.
6.Classic Mode vs. Modern Composer Mode
When evaluating a deployment at /var/www/html/typo3, engineers must understand the distinction between TYPO3's two operational modes:
In Classic mode, the web server's DocumentRoot points directly to the project root (/var/www/html/typo3). This layout works out-of-the-box but requires rigorous Nginx access restrictions (such as denying direct HTTP requests to /vendor/, composer.json, and hidden dotfiles).
Git Strategy: You track .gitignore, typo3conf/sites/, and your custom sitepackage inside typo3conf/ext/, while strictly excluding core symlinks, cache, and settings.php.
In modern TYPO3 projects, the repository root lives entirely outside the web server's public path. Only the public/ subfolder is exposed to Nginx:
my-typo3-project/ <-- Repository Root (Forbidden to Web Server)
├── .git/
├── .gitignore
├── composer.json <-- Defines exact TYPO3 v13 versions & packages
├── composer.lock <-- Lockfile guarantees bit-for-bit parity
├── config/
│ ├── sites/main/config.yaml <-- Tracked routing
│ └── system/additional.php <-- Environment secret overrides
├── packages/
│ └── site_package/ <-- Tracked custom extension
└── public/ <-- DocumentRoot exposed to Nginx (/var/www/...)
├── index.php
├── typo3/ <-- Symlinked backend entry point
├── typo3temp/ <-- Runtime temporary files
└── fileadmin/ <-- User uploads storageSecurity Benefit: Sensitive configuration, locks, git logs, and vendor code cannot be reached by web visitors even if Nginx misconfiguration occurs.
7.Step-by-Step Implementation Guide
Follow this exact execution protocol on your server to establish a clean Git repository on your existing site:
Pre-Flight Audit & Verification
Verify that you are in the correct directory and that no prior unmanaged repository exists:
cd /var/www/html/typo3
pwd
# Check if git is already initialized
git status
Deploy Secret Isolation Layer
Extract sensitive DB credentials and generate additional.php and a sample .env.example file:
# Create .env.example for team reference
cat << 'EOF' > /var/www/html/typo3/.env.example
TYPO3_DB_HOST=127.0.0.1
TYPO3_DB_NAME=typo3
TYPO3_DB_USER=typo3
TYPO3_DB_PASSWORD=your_secure_password_here
TYPO3_CONTEXT=Production
EOF
Install the Production .gitignore
Write the .gitignore file created in Section 4 to the project root.
Initialize Repository and Stage Code Base
Initialize the git repository, set the default branch to main, and verify staging status:
# Initialize Git
git init -b main
# Stage configuration and safety files
git add .gitignore .env.example typo3conf/sites/ typo3conf/PackageStates.php
# Verification: Confirm that fileadmin, typo3temp, and settings.php are IGNORED
git status --ignored
Commit Clean Baseline
Create the initial baseline commit:
git commit -m "chore: initial TYPO3 v13 configuration and site baseline"
8.Database Schema and Content Management
One of the most frequent misconceptions in CMS DevOps is attempting to track database SQL dumps directly inside Git.
Code Schema vs. Operational Content:
Database Schema (In Code): Extension table structures, added columns, and index definitions are declared in
ext_tables.sqlwithin sitepackages. When you deploy, TYPO3's CLI updates the database automatically:php typo3/sysext/core/bin/typo3 database:updateschema- Operational Content (In Database): News articles, pages, form submissions, and user accounts belong strictly in the database. Never overwrite production databases with local dumps.
9.Zero-Downtime CI/CD Deployment
Running git pull directly on a production server is dangerous. If a pull encounters a network timeout, merge conflict, or syntax error, the live site remains broken for users. Furthermore, file permissions between CLI users and www-data easily desynchronize.
The Symlink-Based Deployment Pipeline
Tools like Deployer (PHP), Ansible, or GitHub Actions execute zero-downtime releases using atomic directory symlinks:
/var/www/typo3-app/
├── current -> releases/20261015143000 <-- Nginx DocumentRoot
├── releases/
│ ├── 20261015120000/
│ └── 20261015143000/ <-- New release built & prepared
└── shared/
├── .env
└── fileadmin/ <-- Shared persistent storagePost-Deploy Automation Script
Every deployment automation job must execute these core operational steps in order:
- Sync schema:
php vendor/bin/typo3 database:updateschema - Flush runtime caches:
php vendor/bin/typo3 cache:flush - Warm up caches:
php vendor/bin/typo3 cache:warmup - Ensure ownership:
chown -R www-data:www-data /var/www/html/typo3
10.Conclusion and Checklist
A robust version control setup transforms TYPO3 from a fragile server installation into an enterprise-grade, automated web platform:
- Zero secrets in version control via
additional.phpand environment injection. - Strict
.gitignorepreventing media bloat and cache pollution. - Encapsulated custom presentation logic within a dedicated Sitepackage extension.
- Deterministic, repeatable CI/CD deployments without production downtime.
Verification Checklist
typo3conf/system/settings.php is untrackedfileadmin/ is excluded from gittypo3temp/ cache folder is excludedtypo3conf/sites/ YAML configs are committedsite_packagewww-data:www-dataReferences
- TYPO3 Documentation Team, “TYPO3 Explained: Complete Reference for TYPO3 CMS v13,”2026. docs.typo3.org
- TYPO3 Association, “Sitepackage Tutorial: Building modern TYPO3 extensions,”TYPO3 Association. docs.typo3.org
- A. Wiggins, “The Twelve-Factor App: Config and Stateless Processes,”2017. 12factor.net
- OWASP Foundation, “OWASP Top 10: Identification of Sensitive Data Exposure and Security Misconfiguration,”2025. owasp.org
- European Parliament and Council, “Regulation (EU) 2016/679 (GDPR), Article 32: Security of processing,”Official Journal of the European Union. eur-lex.europa.eu
- Deployer PHP Team, “Zero-Downtime Deployment for PHP Applications,”deployer.org. deployer.org