Browse Source

basic setup done

master
Daniel 1 week ago
commit
73b48915ca
15 changed files with 15351 additions and 0 deletions
  1. +24
    -0
      .ddev/config.yaml
  2. +19
    -0
      .env.example
  3. +47
    -0
      .gitignore
  4. +192
    -0
      README.md
  5. +33
    -0
      bin/console
  6. +35
    -0
      composer.json
  7. +14617
    -0
      composer.lock
  8. +3
    -0
      db/dump.sql
  9. +60
    -0
      public/.htaccess
  10. +47
    -0
      public/index.php
  11. +58
    -0
      public/preview.php
  12. +21
    -0
      scripts/db-export.sh
  13. +60
    -0
      scripts/pull-live-db.sh
  14. +39
    -0
      scripts/reset.sh
  15. +96
    -0
      scripts/setup.sh

+ 24
- 0
.ddev/config.yaml View File

@@ -0,0 +1,24 @@
name: my-contao-project

# -------------------------------------------------------
# Contao & PHP Version hier anpassen
# -------------------------------------------------------
php_version: "8.3" # Empfehlung: 8.3 | Alternativ: 8.4 (experimentell)
mariadb_version: "10.11"

# -------------------------------------------------------
# Projekt-Typ
# -------------------------------------------------------
type: php
docroot: public
webserver_type: nginx-fpm

router_http_port: "80"
router_https_port: "443"

upload_dirs:
- public/files

mutagen_enabled: true

additional_fqdns: []

+ 19
- 0
.env.example View File

@@ -0,0 +1,19 @@
# -------------------------------------------------------
# Kopiere diese Datei zu .env.local und fülle sie aus
# .env.local wird NICHT ins Git eingecheckt
# -------------------------------------------------------

# Live-Server SSH-Zugangsdaten (für pull-live-db.sh)
LIVE_SSH_HOST=
LIVE_SSH_USER=
LIVE_SSH_PORT=22
LIVE_SSH_PATH=/var/www/html # Pfad zur Contao-Installation auf dem Server

# Live-Datenbank
LIVE_DB_NAME=
LIVE_DB_USER=
LIVE_DB_PASS=
LIVE_DB_HOST=127.0.0.1 # meist localhost auf dem Server

# Live Files/Uploads synchronisieren (optional)
LIVE_FILES_PATH=/var/www/html/files

+ 47
- 0
.gitignore View File

@@ -0,0 +1,47 @@
# Contao
/assets/
/public/assets/
/public/bundles/
/public/system/
/public/share/
/public/files/
/var/
/vendor/

# Contao symlink
/public/assets

# Contao generiert
/system/logs
/system/themes/
/public/vendor/


# Contao Manager
public/contao-manager.phar.php

# Environment
.env
.env.local
.env.*.local

# Live-DB dump (nicht einchecken!)
db/live-dump.sql
db/live-dump.sql.gz

# DDEV
.ddev/.gitignore
.ddev/homeadditions/
.ddev/.webimageBuild/
.ddev/addon-metadata/
.ddev/commands/
.ddev/docker-compose.phpmyadmin*.yaml

# OS
.DS_Store
Thumbs.db

# IDE
.idea/
.vscode/
*.swp

+ 192
- 0
README.md View File

@@ -0,0 +1,192 @@
# Contao Blueprint

DDEV-basiertes Contao 5 Projekt-Blueprint für schnellen lokalen Entwicklungsstart.

---

## Voraussetzungen

- [Docker](https://docs.docker.com/get-docker/)
- [DDEV](https://ddev.readthedocs.io/en/stable/#installation)

---

## 🚀 Schnellstart

```bash
# 1. Blueprint-Dateien in neues Projektverzeichnis kopieren
# 2. Projektname anpassen (in .ddev/config.yaml): name: mein-projekt-name
# 3. Git initialisieren
git init
git remote add origin <neues-repo-url>

# 4. Setup ausführen — erledigt alles automatisch
bash scripts/setup.sh
```

Das war's. Am Ende des Setups wirst du aufgefordert einen Admin-Benutzer anzulegen.

- **Frontend:** https://mein-projekt-name.ddev.site
- **Backend:** https://mein-projekt-name.ddev.site/contao
- **phpMyAdmin:** https://mein-projekt-name.ddev.site:8036

---

## 📋 Was setup.sh automatisch macht

1. `.env` mit DDEV-Datenbankverbindung anlegen
2. DDEV Container starten
3. phpMyAdmin Add-on installieren
4. Composer-Abhängigkeiten installieren
5. Contao Web-Verzeichnis initialisieren
6. Symlinks setzen
7. Assets installieren
8. Cache leeren
9. Datenbank importieren (falls `db/dump.sql` vorhanden)
10. Contao-Migrationen ausführen
11. Admin-Benutzer anlegen

---

## 🔄 Täglicher Workflow

```bash
ddev start # Umgebung starten
ddev stop # Umgebung stoppen
ddev restart # Umgebung neu starten
ddev ssh # In den Container einloggen
ddev describe # URLs und Status anzeigen
ddev logs # Logs anzeigen
```

---

## 🗄️ Datenbank

### Lokalen Stand exportieren und einchecken

Nach Änderungen im CMS immer exportieren und committen:

```bash
bash scripts/db-export.sh
git add db/dump.sql
git commit -m "db: update dump"
git push
```

### Live-DB lokal ziehen

```bash
# Einmalig: .env.local mit Live-Zugangsdaten befüllen
# LIVE_SSH_HOST, LIVE_SSH_USER, LIVE_DB_* eintragen

bash scripts/pull-live-db.sh
```

> ⚠️ Der Live-Dump wird lokal importiert aber **nicht** ins Git eingecheckt.

---

## 🔧 Projekt zurücksetzen

Kompletten Neustart — löscht Container, vendor/ und composer.lock:

```bash
bash scripts/reset.sh
```

---

## ➕ Neuer Entwickler / neuer Rechner

```bash
git clone <repo-url>
cd mein-projekt
bash scripts/setup.sh
```

---

## ⚙️ Konfiguration anpassen

### Projektname

In `.ddev/config.yaml`:

```yaml
name: mein-projekt-name
```

### Contao-Version

In `composer.json`:

```json
"contao/manager-bundle": "5.7.*"
```

### PHP-Version

In `.ddev/config.yaml`:

```yaml
php_version: "8.3" # Alternativ: 8.4 (experimentell)
```

Nach Änderungen: `ddev restart`

### Extensions hinzufügen

In `composer.json` unter `require` eintragen:

```json
"vendor/extension-name": "*"
```

Dann:

```bash
ddev exec composer update
```

---

## 📚 Nützliche DDEV-Befehle

```bash
# Composer
ddev exec composer install
ddev exec composer update
ddev exec composer require vendor/paket

# Contao Console
ddev exec vendor/bin/contao-console contao:migrate
ddev exec vendor/bin/contao-console contao:user:create
ddev exec vendor/bin/contao-console cache:clear
ddev exec vendor/bin/contao-console cache:warmup
ddev exec vendor/bin/contao-console contao:symlinks
ddev exec vendor/bin/contao-console assets:install public

# Datenbank
ddev import-db --file=db/dump.sql # DB importieren
ddev export-db --file=db/dump.sql # DB exportieren
ddev mysql # MySQL CLI öffnen

# PHP
ddev php -v # PHP-Version anzeigen
ddev exec php -i # phpinfo ausgeben
```

---

## 🌐 Live-Server einrichten

Auf dem Live-Server einmalig eine `.env.local` anlegen:

```bash
APP_ENV=prod
APP_SECRET=einEchtesGeheimnis
DATABASE_URL=mysql://user:pass@localhost:3306/dbname
```

Diese Datei liegt **nicht** im Git und wird nie überschrieben.

+ 33
- 0
bin/console View File

@@ -0,0 +1,33 @@
#!/usr/bin/env php
<?php

declare(strict_types=1);

/*
* This file is part of Contao.
*
* (c) Leo Feyer
*
* @license LGPL-3.0-or-later
*/

use Contao\ManagerBundle\Console\ContaoApplication;
use Contao\ManagerBundle\HttpKernel\ContaoKernel;
use Symfony\Component\Console\Input\ArgvInput;

set_time_limit(0);
@ini_set('zlib.output_compression', '0');
@ini_set('display_errors', '0');

// System maintenance mode comes first as it has to work even if the vendor directory does not exist
if ('contao:cron' === ($_SERVER['argv'][1] ?? null) && file_exists(__DIR__.'/../var/maintenance.html')) {
exit;
}

require __DIR__.'/../vendor/autoload.php';

$input = new ArgvInput();
$kernel = ContaoKernel::fromInput(\dirname(__DIR__), $input);

$application = new ContaoApplication($kernel);
$application->run($input);

+ 35
- 0
composer.json View File

@@ -0,0 +1,35 @@
{
"name": "my-agency/contao-project",
"description": "Contao 5 Projekt",
"license": "proprietary",
"type": "project",
"require": {
"php": "^8.3",
"contao/manager-bundle": "5.7.*",
"contao/calendar-bundle": "5.7.*",
"contao/faq-bundle": "5.7.*",
"contao/listing-bundle": "5.7.*",
"contao/news-bundle": "5.7.*"
},
"conflict": {
"contao/core-bundle": "<5.7 || >=6.0"
},
"extra": {
"contao-component-dir": "assets",
"symfony": {
"allow-contrib": false
}
},
"config": {
"allow-plugins": {
"contao/manager-plugin": true,
"contao-components/installer": true,
"php-http/discovery": true
},
"optimize-autoloader": true,
"preferred-install": "dist",
"sort-packages": true
},
"scripts": {
}
}

+ 14617
- 0
composer.lock
File diff suppressed because it is too large
View File


+ 3
- 0
db/dump.sql View File

@@ -0,0 +1,3 @@
-- Hier kommt der initiale DB-Dump rein.
-- Nach dem ersten Setup exportieren:
-- bash scripts/db-export.sh

+ 60
- 0
public/.htaccess View File

@@ -0,0 +1,60 @@
<IfModule mod_rewrite.c>
RewriteEngine On

<IfModule mod_headers.c>
# Assets in /assets and /bundles either contain a hash in their filename
# or are called with a ?version suffix, therefore cache them for 1 year.
RewriteRule ^(assets|bundles)/ - [ENV=CONTAO_ASSETS:true]
Header set Cache-Control "max-age=31536000" env=CONTAO_ASSETS

# Allow CORS on the Contao TinyMCE skin.
RewriteRule ^assets/tinymce4/js/skins/contao/fonts/ - [ENV=CONTAO_TINYMCE_SKIN:true]
Header set Access-Control-Allow-Origin "*" env=CONTAO_TINYMCE_SKIN
</IfModule>

# Determine the RewriteBase automatically and set it as environment variable.
# If you are using Apache aliases to do mass virtual hosting or installed the
# project in a subdirectory, the base path will be prepended to allow proper
# resolution of the index.php file and to redirect to the correct URI. It will
# work in environments without path prefix as well, providing a safe, one-size
# fits all solution. But as you do not need it in this case, you can comment
# the following 2 lines to eliminate the overhead.
RewriteCond %{REQUEST_URI}::$1 ^(/.+)/(.*)::\2$
RewriteRule ^(.*) - [E=BASE:%1]

# Sets the HTTP_AUTHORIZATION header removed by Apache
RewriteCond %{HTTP:Authorization} .
RewriteRule ^ - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]

# Redirect to URI without front controller to prevent duplicate content
# (with and without `/index.php`). Only do this redirect on the initial
# rewrite by Apache and not on subsequent cycles. Otherwise, we would get an
# endless redirect loop (request -> rewrite to front controller ->
# redirect -> request -> ...).
# So in case you get a "too many redirects" error or you always get redirected
# to the start page because your Apache does not expose the REDIRECT_STATUS
# environment variable, you have 2 choices:
# - disable this feature by commenting the following 2 lines or
# - use Apache >= 2.3.9 and replace all L flags by END flags and remove the
# following RewriteCond (best solution)
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteRule ^index\.php(?:/(.*)|$) %{ENV:BASE}/$1 [R=301,L]

# If the requested filename exists, simply serve it.
# We only want to let Apache serve files and not directories.
RewriteCond %{REQUEST_FILENAME} -f
RewriteRule ^ - [L]

# Rewrite all other queries to the front controller.
RewriteRule ^ %{ENV:BASE}/index.php [L]
</IfModule>

<IfModule !mod_rewrite.c>
<IfModule mod_alias.c>
# When mod_rewrite is not available, we instruct a temporary redirect of
# the start page to the front controller explicitly so that the website
# and the generated links can still be used.
RedirectMatch 302 ^/$ /index.php/
# RedirectTemp cannot be used instead
</IfModule>
</IfModule>

+ 47
- 0
public/index.php View File

@@ -0,0 +1,47 @@
<?php

declare(strict_types=1);

/*
* This file is part of Contao.
*
* (c) Leo Feyer
*
* @license LGPL-3.0-or-later
*/

use Contao\ManagerBundle\HttpKernel\ContaoKernel;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\TerminableInterface;

// Suppress error messages (see #1422)
@ini_set('display_errors', '0');

// Disable the phar stream wrapper for security reasons (see #105)
if (in_array('phar', stream_get_wrappers(), true)) {
stream_wrapper_unregister('phar');
}

// System maintenance mode comes first as it has to work even if the vendor directory does not exist
if (file_exists(__DIR__.'/../var/maintenance.html')) {
$contents = file_get_contents(__DIR__.'/../var/maintenance.html');

http_response_code(503);
header('Content-Type: text/html; charset=UTF-8');
header('Content-Length: '.strlen((string) $contents));
header('Cache-Control: no-store');

die($contents);
}

$loader = require __DIR__.'/../vendor/autoload.php';

$request = Request::createFromGlobals();
$kernel = ContaoKernel::fromRequest(dirname(__DIR__), $request);

$response = $kernel->handle($request);
$response->send();

if ($kernel instanceof TerminableInterface) {
$kernel->terminate($request, $response);
}

+ 58
- 0
public/preview.php View File

@@ -0,0 +1,58 @@
<?php

declare(strict_types=1);

/*
* This file is part of Contao.
*
* (c) Leo Feyer
*
* @license LGPL-3.0-or-later
*/

use Contao\ManagerBundle\HttpKernel\ContaoKernel;
use FOS\HttpCache\TagHeaderFormatter\TagHeaderFormatter;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\TerminableInterface;

// Suppress error messages (see #1422)
@ini_set('display_errors', '0');

// Disable the phar stream wrapper for security reasons (see #105)
if (in_array('phar', stream_get_wrappers(), true)) {
stream_wrapper_unregister('phar');
}

// System maintenance mode comes first as it has to work even if the vendor directory does not exist
if (file_exists(__DIR__.'/../var/maintenance.html')) {
$contents = file_get_contents(__DIR__.'/../var/maintenance.html');

http_response_code(503);
header('Content-Type: text/html; charset=UTF-8');
header('Content-Length: '.strlen((string) $contents));
header('Cache-Control: no-store');

die($contents);
}

$loader = require __DIR__.'/../vendor/autoload.php';

$request = Request::createFromGlobals();
$request->attributes->set('_preview', true);

$kernel = ContaoKernel::fromRequest(dirname(__DIR__), $request);
$response = $kernel->handle($request);

// Prevent preview URLs from being indexed
$response->headers->set('X-Robots-Tag', 'noindex');

// Force no-cache on all responses in the preview front controller
$response->headers->set('Cache-Control', 'no-store');

// Strip all tag headers from the response
$response->headers->remove(TagHeaderFormatter::DEFAULT_HEADER_NAME);
$response->send();

if ($kernel instanceof TerminableInterface) {
$kernel->terminate($request, $response);
}

+ 21
- 0
scripts/db-export.sh View File

@@ -0,0 +1,21 @@
#!/bin/bash
# -------------------------------------------------------
# db-export.sh — Lokale DDEV-DB exportieren
# Exportiert nach db/dump.sql (wird ins Git eingecheckt)
# -------------------------------------------------------
set -e

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
cd "$SCRIPT_DIR/.."

DUMP_PATH="db/dump.sql"

echo "🗄️ Exportiere lokale Datenbank..."

ddev export-db --file=$DUMP_PATH

echo "✅ Datenbank exportiert nach: $DUMP_PATH"
echo ""
echo "Nicht vergessen:"
echo " git add db/dump.sql"
echo " git commit -m 'db: update dump'"

+ 60
- 0
scripts/pull-live-db.sh View File

@@ -0,0 +1,60 @@
#!/bin/bash
# -------------------------------------------------------
# pull-live-db.sh — Live-DB auf lokale DDEV-Instanz ziehen
#
# ACHTUNG: Nur Live → Local. Niemals umgekehrt!
# Dieser Dump wird NICHT ins Git eingecheckt.
# -------------------------------------------------------
set -e

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
cd "$SCRIPT_DIR/.."

# .env.local laden
if [ ! -f ".env.local" ]; then
echo "❌ .env.local nicht gefunden. Bitte .env.example kopieren und ausfüllen."
exit 1
fi
source .env.local

# Pflichtfelder prüfen
if [ -z "$LIVE_SSH_HOST" ] || [ -z "$LIVE_SSH_USER" ] || [ -z "$LIVE_DB_NAME" ]; then
echo "❌ Bitte LIVE_SSH_HOST, LIVE_SSH_USER und LIVE_DB_NAME in .env.local setzen."
exit 1
fi

TEMP_DUMP="/tmp/live-dump-$(date +%Y%m%d-%H%M%S).sql.gz"
LOCAL_DUMP="db/live-dump.sql"

echo "🔌 Verbinde mit ${LIVE_SSH_USER}@${LIVE_SSH_HOST}:${LIVE_SSH_PORT}..."
echo "🗄️ Exportiere Live-Datenbank '${LIVE_DB_NAME}'..."

# DB auf dem Server dumpen und direkt runterladen
ssh -p "${LIVE_SSH_PORT}" "${LIVE_SSH_USER}@${LIVE_SSH_HOST}" \
"mysqldump -u${LIVE_DB_USER} -p${LIVE_DB_PASS} -h${LIVE_DB_HOST} ${LIVE_DB_NAME} | gzip" \
> "${TEMP_DUMP}"

echo "📥 Dump heruntergeladen. Importiere in DDEV..."

gunzip < "${TEMP_DUMP}" > "${LOCAL_DUMP}.tmp"
ddev import-db --file="${LOCAL_DUMP}.tmp"
mv "${LOCAL_DUMP}.tmp" "${LOCAL_DUMP}"
rm -f "${TEMP_DUMP}"

echo ""
echo "✅ Live-DB erfolgreich lokal importiert."
echo "📁 Lokaler Dump gespeichert unter: ${LOCAL_DUMP} (nicht eingecheckt)"
echo ""

# Optional: Files synchronisieren
if [ ! -z "$LIVE_FILES_PATH" ]; then
read -p "📂 Auch files/ synchronisieren? (j/N): " sync_files
if [ "$sync_files" = "j" ] || [ "$sync_files" = "J" ]; then
echo "🔄 Synchronisiere files/..."
rsync -avz --progress \
-e "ssh -p ${LIVE_SSH_PORT}" \
"${LIVE_SSH_USER}@${LIVE_SSH_HOST}:${LIVE_FILES_PATH}/" \
"./public/files/"
echo "✅ Files synchronisiert."
fi
fi

+ 39
- 0
scripts/reset.sh View File

@@ -0,0 +1,39 @@
#!/bin/bash
# -------------------------------------------------------
# reset.sh — Projekt komplett zurücksetzen und neu aufsetzen
# -------------------------------------------------------

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
cd "$SCRIPT_DIR/.."

echo "⚠️ Projekt zurücksetzen"
echo "------------------------"
echo "Folgendes wird gelöscht:"
echo " - DDEV Container + Datenbank"
echo " - vendor/ Verzeichnis"
echo " - composer.lock"
echo ""

read -p "Bist du sicher? (j/N): " confirm
if [ "$confirm" != "j" ] && [ "$confirm" != "J" ]; then
echo "Abgebrochen."
exit 0
fi

read -p "Auch .env und .env.local löschen? (j/N): " delete_env

echo ""
echo "🗑️ Lösche DDEV Container und Datenbank..."
ddev delete -O

echo "🗑️ Lösche vendor/ und composer.lock..."
rm -rf vendor/ composer.lock

if [ "$delete_env" = "j" ] || [ "$delete_env" = "J" ]; then
rm -f .env .env.local
echo "🗑️ .env und .env.local gelöscht."
fi

echo ""
echo "🚀 Starte Setup..."
bash scripts/setup.sh

+ 96
- 0
scripts/setup.sh View File

@@ -0,0 +1,96 @@
#!/bin/bash
# -------------------------------------------------------
# setup.sh — Einmalig nach git clone ausführen
# -------------------------------------------------------
set -e

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
cd "$SCRIPT_DIR/.."
PROJECT_ROOT="$(pwd)"

echo "🚀 Contao Blueprint Setup"
echo "-------------------------"

# .env lokal anlegen (nicht im Git, wird nicht deployed)
if [ ! -f ".env" ]; then
echo "📋 Erstelle .env mit DDEV-Standardwerten..."
cat > .env << 'EOF'
APP_ENV=dev
APP_SECRET=pleasechangethis
DATABASE_URL=mysql://db:db@db:3306/db
EOF
echo "✅ .env erstellt."
else
echo "✅ .env bereits vorhanden."
fi

# .env.local für Live-Zugangsdaten anlegen (Vorlage)
if [ ! -f ".env.local" ]; then
cp .env.example .env.local
echo "✅ .env.local als Vorlage erstellt — Live-Zugangsdaten bei Bedarf eintragen."
fi

# DDEV starten
echo ""
echo "🐳 Starte DDEV..."
ddev start

# phpMyAdmin installieren
echo ""
echo "🗄️ Installiere phpMyAdmin Add-on..."
ddev add-on get ddev/ddev-phpmyadmin
ddev restart

# Composer im Container
echo ""
echo "📦 Installiere Composer-Abhängigkeiten..."
ddev exec composer install --no-interaction

# Contao Web-Verzeichnis initialisieren
echo ""
echo "📁 Initialisiere Contao Web-Verzeichnis..."
mkdir -p assets
ddev exec vendor/bin/contao-console contao:install-web-dir

# Symlinks setzen
echo ""
echo "🔗 Setze Symlinks..."
ddev exec vendor/bin/contao-console contao:symlinks

# Assets installieren
echo ""
echo "🎨 Installiere Assets..."
ddev exec vendor/bin/contao-console assets:install public

# Cache leeren und aufwärmen
echo ""
echo "🧹 Leere Cache..."
ddev exec vendor/bin/contao-console cache:clear
ddev exec vendor/bin/contao-console cache:warmup

# DB importieren falls Dump vorhanden
if [ -f "db/dump.sql" ]; then
echo ""
echo "🗄️ Importiere Datenbank aus db/dump.sql..."
ddev import-db --file="${PROJECT_ROOT}/db/dump.sql"
echo "✅ Datenbank importiert."
fi

# Contao Migrationen
echo ""
echo "⚙️ Führe Contao-Migrationen aus..."
ddev exec vendor/bin/contao-console contao:migrate --no-interaction

# Cache nochmal leeren nach Migrationen und DB-Import
ddev exec vendor/bin/contao-console cache:clear

# Admin-Benutzer anlegen
echo ""
echo "👤 Admin-Benutzer anlegen..."
ddev exec vendor/bin/contao-console contao:user:create

echo ""
echo "✅ Setup abgeschlossen!"
echo ""
echo "🌐 Frontend: https://$(ddev describe 2>/dev/null | grep -o '[a-z0-9-]*\.ddev\.site' | head -1)"
echo

Loading…
Cancel
Save