Skip to content

Instantly share code, notes, and snippets.

@ErHaWeb
Last active November 27, 2025 12:15
Show Gist options
  • Select an option

  • Save ErHaWeb/961dc1029ce05cee49825f4600219573 to your computer and use it in GitHub Desktop.

Select an option

Save ErHaWeb/961dc1029ce05cee49825f4600219573 to your computer and use it in GitHub Desktop.
TYPO3 Auto-Installation

TYPO3 Auto-Installation

Since I need a TYPO3 test environment from time to time, I use these bash scripts for the automatic installation and removal of TYPO3. The installation script currently supports TYPO3 versions 10, 11, 12, 13, 14 and dev.

Installation

I have stored the scripts under:

~/.shellscripts/typo3/

I use the following aliases:

alias install-typo3="bash ~/.shellscripts/typo3/install.sh"
alias remove-typo3="bash ~/.shellscripts/typo3/remove.sh"

Requirements

Since the installation script set up a local development environment based on Docker and DDEV, you must ensure that DDEV is installed in the latest available version and is working correctly on your machine before running it. For help with installing DDEV, please see the official DDEV documentation.

Usage

The installation script can be called with a version number as the first parameter, which can be "10", "11", "12", "13", "14" or "dev" (for the latest dev version), and any number of string parameters. Each string parameter after the version number is used as the DDEV project name and directory name of the TYPO3 instance.

Example:

install-typo3 13 domain1.com domain2.com domain3.com

This command creates three TYPO3 13 projects in the directories domain1.com/, domain2.com/ and domain3.com/.

If no directory names are specified, the name typo3-<version>-project is used. If no version number is specified, the latest version 14 will be installed in directory typo3-14-project.

What it does

  • The DDEV plugin DDEV-CRON automatically creates a cronjob that runs the TYPO3 scheduler every minute.
  • phpMyAdmin is also installed via DDEV plugin and can be called via ddev phpmyadmin.
  • Furthermore a packages/ directory is created and stored in the composer.json as local repository path.
  • Inside packages/ my sitepackage basic structure is cloned and changed to the branch matching the TYPO3 version.
  • With the installation of the sitepackage a root site is created with references to the Page TSconfig and TypoScript of the sitepackage, so you can start directly.

Backend-Login

With the following credentials you can log in to the backend:

Username: admin
Password: Password1%

Showcase on YouTube

I have recorded the installation process of all versions as a YouTube-video here:

Uninstall

If you don't need the TYPO3 test-installation anymore you can change to the directory of the installation and execute remove-typo3 (see alias above). This will A) delete the DDEV project and B) delete the whole directory (with sudo).

Disclaimer

Please note that the execution of these scripts is at your own risk and I assume no liability for anything. For this reason you should make sure that you have understood which steps are executed by the script.

#!/bin/bash
## INSTALLATION:
## -----------------
## Create a new alias in your Bash/ZSH startup file
## For Bash the startup file can be found here "~/.bashrc"
## and for ZSH it can be found here "~/.zshrc".
## Now copy this script to a local directory, e.g. under:
##
## ~/.shellscripts/typo3/install.sh
##
## and add the following alias to your startup file:
##
## alias install-typo3="bash ~/.shellscripts/typo3/install.sh"
##
##
## USAGE
## -----------------
## Call the script with one of the version numbers "10", "11", "12", "13", "14"
## or "dev" (for the latest dev version) and any number of following parameters,
## each of which stands for the installation directory name in which typo3 is
## to be installed.
##
## If no directory names are specified, the name typo3-<version>-project
## is used. If no version number is specified, the latest version 14 will
## be installed.
##
## Example for version 13 in directories "first-project" and "second-project":
## install-typo3 13 first-project second-project
##
##
## BACKEND LOGIN:
## -----------------
## Login-URL: https://directory.ddev.site/typo3/
## Username: admin
## Password: Password1%
##
## © 2025 Eric Harrer
##
set -Eeuo pipefail
# ANSI color codes
RED='\033[0;31m'
GREEN='\033[0;32m'
NC='\033[0m'
# Store initial working directory and ensure returning there on exit
START_DIR="$PWD"
cleanup() { cd "$START_DIR" >/dev/null 2>&1 || true; }
trap cleanup EXIT
# Preflight check
if ! command -v ddev >/dev/null 2>&1; then
printf "%b[ERROR]%b ddev is not installed. Please see https://ddev.readthedocs.io/\n" "$RED" "$NC"
exit 1
fi
execute_typo3_installation() {
local version=$1
shift
local directories=("$@")
# Validate TYPO3 version
if ! [[ "$version" =~ ^(10|11|12|13|14|dev)$ ]]; then
printf "\n--- %bInvalid TYPO3 version:%b %s\n" "$RED" "$NC" "$version"
printf "--- Supported versions are %b10, 11, 12, 13, 14, dev%b\n" "$GREEN" "$NC"
return 1
fi
# Default directory name if none provided
if [ ${#directories[@]} -eq 0 ]; then
directories=("typo3-${version}-project")
fi
for dir in "${directories[@]}"; do
if [ -d "$dir" ] && [ -n "$(ls -A "$dir" 2>/dev/null || true)" ]; then
printf "\n--- %bError:%b Directory %s exists and is not empty. Aborting to prevent data loss.\n" "$RED" "$NC" "$dir"
return 1
fi
printf "\n--- Creating directory: %b%s%b\n" "$GREEN" "$dir" "$NC"
mkdir -p "$dir"
cd "$dir" || return 1
# Determine PHP version based on TYPO3 main version
local php_version
case "$version" in
10) php_version="7.4" ;;
11) php_version="8.3" ;;
12) php_version="8.4" ;;
*) php_version="8.5" ;;
esac
# Determine MariaDB version based on TYPO3 main version
local mariadb_version
case "$version" in
10|11)
mariadb_version="10.11"
;;
*)
mariadb_version="11.4"
;;
esac
printf "\n--- Running ddev config\n"
ddev config \
--project-type=typo3 \
--docroot=public \
--php-version="$php_version" \
--webserver-type=apache-fpm \
--xdebug-enabled=false \
--database="mariadb:${mariadb_version}" \
--performance-mode=mutagen \
--webimage-extra-packages=graphicsmagick \
--use-dns-when-possible=true \
--timezone=Europe/Berlin \
--composer-version=2 \
--web-environment=TYPO3_CONTEXT=Development
printf "\n--- Installing DDEV Cron add-on\n"
ddev add-on get drud/ddev-cron
printf "\n--- Setting up TYPO3 Scheduler cron job\n"
mkdir -p .ddev/web-build
printf '* * * * * IS_DDEV_PROJECT=true /var/www/html/vendor/bin/typo3 scheduler:run -vv\n' > .ddev/web-build/typo3-scheduler.cron
printf "\n--- Installing DDEV phpMyAdmin add-on\n"
ddev add-on get ddev/ddev-phpmyadmin
printf "\n--- Starting environment\n"
ddev start -y
printf "\n--- Updating Composer to latest stable version\n"
if ! ddev exec composer self-update --stable --no-interaction --no-progress; then
printf "%b[WARNING]%b Composer self-update failed, continuing with current version.\n" "$RED" "$NC"
fi
ddev composer --version
printf "\n--- Ensuring Composer signature verification keys are installed (non-interactive)\n"
local composer_home_path="$(ddev exec sh -lc 'composer config --global home' | tr -d '\r')"
if [ -z "$composer_home_path" ]; then
printf "%b[WARNING]%b Unable to resolve Composer global home. Skipping key installation.\n" "$RED" "$NC"
else
ddev exec sh -lc "mkdir -p '$composer_home_path' && \
wget -qO '$composer_home_path/keys.tags.pub' https://composer.github.io/releases.pub && \
wget -qO '$composer_home_path/keys.dev.pub' https://composer.github.io/snapshots.pub" \
|| printf "%b[WARNING]%b Failed to download Composer public keys. Continuing without verification.\n" "$RED" "$NC"
fi
printf "\n--- Initializing Composer configuration\n"
ddev composer init \
--name="erhaweb/typo3-$version-autoinstallation" \
--description="TYPO3 $version Auto-Installation" \
--author="Eric Harrer <[email protected]>" \
--type="project" \
--homepage="https://www.eric-harrer.de" \
--stability="stable" \
--license="GPL-2.0-or-later" \
--repository='{"type":"path","url":"packages/*"}' \
--quiet
ddev composer config --no-interaction allow-plugins.typo3/class-alias-loader true
ddev composer config --no-interaction allow-plugins.typo3/cms-composer-installers true
ddev composer config --no-interaction platform.php "$php_version"
ddev composer config --no-interaction sort-packages true
case "$version" in
dev)
printf "\n--- %b[WARNING]%b minimum-stability set to 'dev'. Not suitable for production use.\n" "$RED" "$NC"
ddev composer config --no-interaction minimum-stability dev
ddev composer config --no-interaction prefer-stable true
;;
10|11)
printf "\n--- %b[WARNING]%b Composer security audit disabled. Not suitable for production use.\n" "$RED" "$NC"
ddev composer config --no-interaction audit.block-insecure false || true
;;
esac
# TYPO3 branch mapping
local typo3_branch
case "$version" in
10) typo3_branch="10.4" ;;
11) typo3_branch="11.5" ;;
12) typo3_branch="12.4" ;;
13) typo3_branch="13.4" ;;
14) typo3_branch="14.0" ;;
dev) typo3_branch="main" ;;
esac
printf "\n--- Downloading .editorconfig from TYPO3 branch %s\n" "$typo3_branch"
local editorconfig_url="https://raw.githubusercontent.com/TYPO3/typo3/refs/heads/$typo3_branch/.editorconfig"
[ "$version" = "14" ] && editorconfig_url="https://raw.githubusercontent.com/TYPO3/typo3/refs/heads/main/.editorconfig"
ddev exec wget -q "$editorconfig_url"
printf "\n--- Creating packages directory\n"
mkdir -p packages
local package_version sitepackage_branch
package_version="^${typo3_branch}"
[ "$typo3_branch" = "main" ] && package_version="dev-main"
sitepackage_branch="$version"
[ "$version" = "dev" ] && sitepackage_branch="main"
printf "\n--- Cloning base sitepackage (branch %s)\n" "$sitepackage_branch"
git clone --branch "$sitepackage_branch" https://github.com/ErHaWeb/sitepackage.git "packages/sitepackage/"
printf "\n--- Requiring sitepackage and TYPO3 core packages\n"
ddev composer require --no-install "vendorname/sitepackage:@dev"
ddev composer require --no-install \
"typo3/cms-adminpanel:${package_version}" \
"typo3/cms-backend:${package_version}" \
"typo3/cms-belog:${package_version}" \
"typo3/cms-beuser:${package_version}" \
"typo3/cms-core:${package_version}" \
"typo3/cms-dashboard:${package_version}" \
"typo3/cms-extbase:${package_version}" \
"typo3/cms-extensionmanager:${package_version}" \
"typo3/cms-felogin:${package_version}" \
"typo3/cms-filelist:${package_version}" \
"typo3/cms-filemetadata:${package_version}" \
"typo3/cms-fluid:${package_version}" \
"typo3/cms-fluid-styled-content:${package_version}" \
"typo3/cms-form:${package_version}" \
"typo3/cms-frontend:${package_version}" \
"typo3/cms-impexp:${package_version}" \
"typo3/cms-indexed-search:${package_version}" \
"typo3/cms-info:${package_version}" \
"typo3/cms-install:${package_version}" \
"typo3/cms-linkvalidator:${package_version}" \
"typo3/cms-lowlevel:${package_version}" \
"typo3/cms-opendocs:${package_version}" \
"typo3/cms-recycler:${package_version}" \
"typo3/cms-redirects:${package_version}" \
"typo3/cms-reports:${package_version}" \
"typo3/cms-rte-ckeditor:${package_version}" \
"typo3/cms-scheduler:${package_version}" \
"typo3/cms-seo:${package_version}" \
"typo3/cms-setup:${package_version}" \
"typo3/cms-sys-note:${package_version}" \
"typo3/cms-tstemplate:${package_version}" \
"typo3/cms-viewpage:${package_version}" \
"typo3/cms-workspaces:${package_version}"
# Version-specific core packages
case "$version" in
10)
ddev composer require --no-install \
"typo3/cms-t3editor:${package_version}" \
"typo3/cms-recordlist:${package_version}" \
"typo3/cms-about:${package_version}" \
"helhum/typo3-console:^6.7"
;;
11)
ddev composer require --no-install \
"typo3/cms-t3editor:${package_version}" \
"typo3/cms-recordlist:${package_version}" \
"typo3/cms-composer-installers:4.0.x@dev" \
"helhum/typo3-console:^8.2"
;;
12)
ddev composer require --no-install \
"typo3/cms-t3editor:${package_version}" \
"typo3/cms-reactions:${package_version}" \
"typo3/cms-webhooks:${package_version}"
;;
*)
ddev composer require --no-install \
"typo3/cms-reactions:${package_version}" \
"typo3/cms-webhooks:${package_version}"
;;
esac
printf "\n--- Installing all Composer packages\n"
ddev composer update
printf "\n--- Running composer diagnose (non-fatal)\n"
if ! ddev exec composer diagnose; then
printf "%b[WARNING]%b composer diagnose reported issues. See output above.\n" "$RED" "$NC"
fi
local additional_path
case "$version" in
10|11) additional_path="public/typo3conf/AdditionalConfiguration.php" ;;
*) additional_path="config/system/additional.php" ;;
esac
printf "\n--- Running ddev config --auto to ensure %s exists\n" "$additional_path"
ddev config --auto
local typo3_command="typo3"
[ "$version" = "10" ] && typo3_command="typo3cms"
printf "\n--- Running TYPO3 setup using current directory name '%s' as site name\n" "${PWD##*/}"
case "$version" in
10|11)
ddev "$typo3_command" install:setup \
--use-existing-database \
--database-driver="mysqli" \
--database-host-name="db" \
--database-port="3306" \
--database-socket="" \
--database-name="db" \
--database-user-name="db" \
--database-user-password="db" \
--admin-user-name="admin" \
--admin-password="Password1%" \
--site-name="${PWD##*/}" \
--site-setup-type="no" \
--site-base-url="/" \
--web-server-config="apache" \
--force \
--no-interaction
;;
*)
ddev "$typo3_command" setup \
--driver="mysqli" \
--host="db" \
--port=3306 \
--dbname="db" \
--username="db" \
--password="db" \
--admin-username="admin" \
--admin-user-password="Password1%" \
--admin-email="[email protected]" \
--project-name="${PWD##*/}" \
--server-type="apache" \
--force \
--no-interaction
;;
esac
local extension_setup_param=""
[ "$version" = "10" ] && extension_setup_param="sitepackage"
printf "\n--- Running extension:setup to initialize sitepackage data\n"
ddev "$typo3_command" extension:setup $extension_setup_param
printf "\n--- Flushing TYPO3 caches\n"
ddev "$typo3_command" cache:flush
printf "\n--- TYPO3 Backend Login:\nUsername: admin\nPassword: Password1%s\n" "%"
printf "\n--- Launching environment in browser\n"
ddev launch
cd "$START_DIR" >/dev/null 2>&1 || true
done
}
# Main script logic
if [ $# -eq 0 ]; then
execute_typo3_installation 14
elif [ $# -eq 1 ] && [[ "$1" =~ ^[0-9]+$|^dev$ ]]; then
execute_typo3_installation "$1"
else
execute_typo3_installation "$@"
fi
#!/bin/bash
## WHAT IT DOES:
## -----------------
## It is responsible for deleting an instance completely.
## Both the DDEV project and the base directory are removed.
## Don't worry, you will be warned and asked if you really
## want to run the removal when you run the script.
##
##
## INSTALLATION:
## -----------------
## Create a new alias in your Bash/ZSH startup file
## For Bash the startup file can be found here "~/.bashrc"
## and for ZSH it can be found here "~/.zshrc".
## Now copy this script to a local directory, e.g. under:
##
## ~/.shellscripts/typo3/remove.sh
##
## and add the following alias to your startup file:
##
## alias remove-typo3="bash ~/.shellscripts/typo3/remove.sh"
##
##
## USAGE:
## -----------------
## Go to the base directory of the project you want to
## remove and call the bash script as follows:
##
## cd directory.tld
## remove-typo3
##
## © 2025 Eric Harrer
##
set -Eeuo pipefail
current_dir=${PWD}
parent_dir=$(dirname "$current_dir")
project=${PWD##*/}
read -p "Remove DDEV project \"${project}\" (if exists) and directory \"${current_dir}\"? [y]es or [n]o (default) " -n 1 -r
if [[ $REPLY =~ ^[Yy]$ ]]; then
printf "\n\n--- Delete DDEV project \"%s\"\n" "${project}"
ddev delete "${project}" --omit-snapshot -y
printf "\n--- Remove directory \"%s\"\n" "${current_dir}"
# Attention! Be careful with the following line.
# Do not execute this command in the wrong directory!
# On macOS, run `mv filename ~/.trash/` instead to move to the trash only
sudo rm -R -f "${current_dir}"
printf "\n--- change to parent directory \"%s\"\n" "${parent_dir}"
cd "${parent_dir}" || exit
else
printf "\n--- Deletion of project \"%s\" was aborted\n" "${project}"
fi
@Riiiad
Copy link

Riiiad commented Feb 14, 2024

This is great. Thank you for the updates @ErHaWeb

@ErHaWeb
Copy link
Author

ErHaWeb commented Feb 14, 2024

@Riiiad You're welcome, I'm glad you like it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment