whoami
Lucas Jenß
cat /etc/motd
The Coding Journal ツ — Notes taken on an epic coding journey. Technical solutions, debugging notes, and practical guides from the trenches of software development.
ls -la ~/languages/
- drwxr-xr-x
- ▶ PHP
- ▶ Ruby
- ▶ Scala
- ▶ C#
- ▶ JavaScript
- ▶ Objective-C
- ▶ Shell Scripting
ls -la ~/toolchain/
- drwxr-xr-x
- ▶ Typo3
- ▶ Akka
- ▶ Capistrano
- ▶ Git
- ▶ MAMP
- ▶ Adobe Illustrator
- ▶ NSTrackingArea (Cocoa)
uname -a
- drwxr-xr-x
- ▶ Mac OS X
- ▶ Unix
Deploying a TYPO3 Site With Capistrano and Environment Config Files
Deploying a TYPO3 installation can feel like wrestling a friendly octopus once the site grows beyond a single developer machine. Configuration values get copied between servers by hand, file permissions drift, and the inevitable "works on my laptop" message creeps into Slack channels from Melbourne to Perth. A reproducible deployment pipeline saves hours each week and removes the guesswork that costs real billing hours.
Capistrano, the battle-tested Ruby tool that helped a generation of web shops push code in seconds, still earns its place for TYPO3 sites when paired with environment-specific configuration files. The trick is treating each environment as a separate target with its own credentials, its own database, and its own caching strategy. This article walks through a working setup that has shipped content for Australian publishers, agencies, and one stubborn newsletter run out of a Brisbane coworking space.
Why Capistrano Still Works For TYPO3
Capistrano predates most of the modern container-native deployment chains, yet it offers something those chains often make verbose. A small Ruby DSL describes what should happen on the target host, and the same script can roll back to the previous known-good release with a single command. For a TYPO3 project running on a modest VPS in Sydney or a managed server in Adelaide, this simplicity is more valuable than the latest GitOps ceremony.
The tool also assumes nothing about the application stack. TYPO3 runs on PHP, but Capistrano does not care which PHP version is installed or which lockfile is checked into Composer. It simply copies a release directory, swaps a symlink, and runs the tasks defined in the recipe. That neutrality fits Australian shops that mix legacy CMS projects with greenfield experiments and want one deployment workflow across the portfolio.
Setting Up The Repository And Server Layout
A standard Capistrano layout creates three directories on the target host. The releases/ folder holds timestamped snapshots of the code, the shared/ folder carries files that persist between releases such as uploaded media and the TYPO3 fileadmin/ directory, and current/ is a symlink pointing at the active snapshot. Adding environment-specific configuration files as symlinks inside shared/ keeps secrets out of the repository without breaking the deployment.
For an Australian team renting a VPS from a local provider, the path often lives under /var/www/typo3.example.com.au/. The shared/config/system/AdditionalConfiguration.php becomes the single source of truth for runtime settings. Capistrano's linked_files directive copies that file into each release, while the .env file containing database credentials is excluded from Git through .gitignore and recreated on the fly by a deployment task.
Crafting Environment-Specific Config Files
TYPO3 reads its primary configuration from LocalConfiguration.php, but the more flexible approach is to use AdditionalConfiguration.php to layer environment-specific overrides on top. A staging environment might point at a sanitised copy of the production database hosted in Brisbane, while production uses a managed database cluster in Sydney with read replicas. The same source code runs unchanged on every environment.
The cleanest pattern is a small loader that reads environment variables and applies them to the TYPO3 configuration array. The database host can be read from $_SERVER['TYPO3_DB_HOST'] with a sensible default that points at the local development container. Australian teams that need to satisfy the Notifiable Data Breaches scheme under the Privacy Act will appreciate that secrets stay inside the deployment pipeline rather than scattered across developer laptops.
The values below summarise how the three environments typically compare.
| Setting | Development | Staging | Production |
|---|---|---|---|
| Database host | localhost | staging-db.au.example.com | prod-db.example.com |
| Debug output | Enabled | Limited | Disabled |
| Cache backend | None | Redis (small) | Redis (HA pair) |
| Deploy branch | feature/* | main | tagged releases |
| Cache flush strategy | On every deploy | Post-deploy flush | Progressive warming |
| TYPO3_CONTEXT | Development | Production/Staging | Production |
Writing The Capistrano Deploy Script
The deploy.rb file sits at the root of the repository and defines the application name, the repository URL, and shared resources. Stages live in config/deploy/ as production.rb, staging.rb, and development.rb. Each stage file sets the server address, the deploy path, and any branch restrictions. A typical staging stage might target a server in Perth with branch restrictions limited to main, while production deploys only from tagged releases.
Within lib/capistrano/tasks/, custom tasks handle the bits that Capistrano does not cover out of the box. A :typo3_configure task copies the environment-specific AdditionalConfiguration.php into place. A :typo3_cache_flush task runs vendor/bin/typo3cms cache:flush against the freshly deployed release. Running these tasks after the symlink swap guarantees that the cache flush targets the live release rather than the previous one.
Handling Database Migrations And Cache Flushes
TYPO3 rarely needs destructive schema changes, but extension updates can introduce new tables or columns. The schema can be applied non-interactively using vendor/bin/typo3cms database:updateschema. Wrapping that command in a Capistrano task that runs only when a marker file is present in the release keeps accidental schema changes off the production hot path.
Flushing the cache in TYPO3 is rarely as cheap as a Redis flush. The system caches the entire frontend rendering output, and a cold cache can hammer a small VPS in Melbourne until it warms up. For sites that serve Australian audiences, scheduling the deploy outside of peak AEST viewing hours protects the user experience. Some teams have even experimented with progressive cache warming by warming the home page through a headless browser before flipping the symlink, but for most publishers a simple post-deploy flush is enough. The same attention to cache strategy pays off when trusted casino American roulette experiences traffic spikes, since predictable rollbacks matter most when the load is highest.
Rolling Back Safely And Monitoring Deploys
Capistrano keeps the previous five releases by default, which means cap production deploy:rollback restores the previous known-good release in seconds. Rolling back does not undo database changes, so the discipline of forward-only schema migrations matters as much here as it does in any other framework. A short README explaining which migrations are reversible and which require a manual fix keeps the on-call developer in Perth from paging the team at 3am.
Logs are the next layer of safety. Capistrano writes to log/captures-*.log on the local machine, but the real value comes from piping the output to a central log service. Australian teams using Datadog or New Relic can tail the deploy events alongside PHP-FPM logs to see exactly what happened during a deploy. Setting up NetBeans for PHP work gives the developer a local environment that matches the production PHP version closely, which cuts down on the class of bugs that only appear after a deploy.
Common Pitfalls In Australian Production Setups
A handful of recurring issues trip up teams moving from manual FTP deploys to Capistrano. The first is file ownership: a deployment running as one account cannot write to files owned by another, and the fix is to ensure the web server user and the deploy user share a common group. The second is cron timing: TYPO3's scheduler task often runs every five minutes, and if the deploy overlaps with a scheduler run, the symlink swap can produce a brief moment where the scheduler reads an inconsistent filesystem.
The third pitfall is more political than technical. Many Australian organisations must align with the Australian Cyber Security Centre's Essential Eight framework, which recommends strict access controls and patched systems. Capistrano deployments that run from a bastion host with key-only SSH access check that box automatically, while deployments that rely on password authentication fail the maturity model from the start. Finally, remember that daylight saving ends in different Australian states on different dates, so any cron schedule written against "AEST" needs an explicit timezone string rather than a wall clock.
Try a staging release today with the layout described above, then share the resulting cap staging deploy:check output with a colleague before the next production push. A reliable pipeline is one of those tools that quietly compounds value every time the team avoids a 2am rollback, and that compounding is what turns a content operation into infrastructure the whole business relies on.
cat ~/interests.json
| Key | Value |
|---|---|
| editor | Terminal-first workflow |
| os | Mac OS X / Unix |
| vcs | Git, distributed version control |
| deploy | Capistrano, cron automation |
| graphics | SVG, Adobe Illustrator troubleshooting |
| networking | IP validation, SSH, VPN |
git log --oneline --reverse
Solving SVG import issues in Adobe Illustrator CS6 and CC
When importing an SVG into Illustrator, the operation fails with an unknown error [CANT]. A workaround for this Adobe-side bug.
Solving NDK build issues on OS X
Troubleshooting native development kit compilation problems on Mac OS X.
Programmatically adding PHP generated TypoScript to the backend configuration
Integrating dynamically generated TypoScript into Typo3 backend setups using PHP.
ArgumentError: Could not parse PKey: no start line
Debugging an SSH key parsing error encountered during deployment.
Validating IP-Addresses in PHP
Using PHP filter functions with flags like FILTER_FLAG_IPV4 and FILTER_FLAG_IPV6, and understanding how filter_var handles reserved IP addresses.
Cocoa: Using NSTrackingArea
A short tutorial on using Cocoa's NSTrackingArea to capture mouseEntered and mouseExited events.
cat ~/contact.txt