Contao mit Ansible verwalten - Teil 2

von Kirsten Roschanski

Basisinstallation von Contao

Grundlage

Gestern habe ich bereits den Grundstein gelegt. Auf dieser Basis setze ich heute auf. Falls du es noch nicht gelesen hast hier der erste Teil der Serie.

Vorbereitung

In meine Struktur füge ich nun einen weiteren Ordner für Templates ein sowie das neue Playbook. Damit sieht meine Struktur nun wie folgt aus:

contao-ansible // Verzeichnis für Ansible-Playbooks
  customers // Verzeichnis für Installationen
    kirsten-roschanski.de.yml // Konfig meiner Webseite
  templates // Verzeichnis für Templates 
    composer.j2
    contao-manager-config.j2
    contao-manager-user.j2
    localconfig.php.j2
    parameters.sh.j2
  ansible.cfg
  update_base.yml
  install_base.yml

install_base.yml

---
- hosts: all
  tasks:

  - name: composer.json exists
    stat:
      path: "{{ websitePath }}/composer.json"
    register: composerJsonExists

  - name: create web dir
    file:
      path: "{{ websitePath }}/web"
      state: directory
    when: composerJsonExists.stat.exists == false

  - name: create contao-manager dir
    file:
      path: "{{ websitePath }}/contao-manager"
      state: directory
    when: composerJsonExists.stat.exists == false

  - name: generate contao-manager/config.json
    template:
      src: contao-manager-config.j2
      dest: "{{ websitePath }}/contao-manager/config.json"
    when: composerJsonExists.stat.exists == false

  - name: crypt Contao-Manger-User-Password
    shell:  htpasswd -nbB "" {{ contao_manager_pass }} | tr -d ':\n'
    register: contao_manager_pass_crypt
    delegate_to: 127.0.0.1

  - name: Set ontao-Manger-User-Password to variable
    set_fact:
      contao_manager_pass_crypt: "{{ contao_manager_pass_crypt.stdout }}"

  - name: generate contao-manager/user.json
    template:
      src: contao-manager-user.j2
      dest: "{{ websitePath }}/contao-manager/users.json"

  - name: download Contao Manager
    get_url:
      url: https://download.contao.org/contao-manager/stable/contao-manager.phar
      dest: "{{ websitePath }}/web/contao-manager.phar.php"
    when: composerJsonExists.stat.exists == false

  - name: generate composer.json
    template:
      src: composer.j2
      dest: "{{ websitePath }}/composer.json"
    when: composerJsonExists.stat.exists == false

  - name: install Contao
    shell: "{{ php_path }} -q -dmax_execution_time=0 -dmemory_limit=-1 -dallow_url_fopen=1 web/contao-manager.phar.php composer install --prefer-dist --no-dev --no-progress --no-ansi --no-interaction --optimize-autoloader"
    args:
      chdir: '{{ websitePath }}'
    when: composerJsonExists.stat.exists == false

  - name: create config dir
    file:
      path: "{{ websitePath }}/config"
      state: directory
    when: composerJsonExists.stat.exists == false

  - name: generate parameters.yml
    template:
      src: parameters.sh.j2
      dest: "{{ websitePath }}/config/parameters.yml"

  - name: crypt InstallPassword
    shell:  htpasswd -nbB "" {{ installPassword }} | tr -d ':\n'
    register: psk
    delegate_to: 127.0.0.1

  - name: Set InstallPassword to variable
    set_fact:
      psk: "{{ psk.stdout }}"

  - name: generate localconfig.php
    template:
      src: localconfig.php.j2
      dest: "{{ websitePath }}/system/config/localconfig.php"
    when:
      - composerJsonExists.stat.exists == false

  - name: lock Contao-InstallTool
    shell: "{{ php_path }} -d memory_limit=-1 {{ websitePath }}/vendor/bin/contao-console contao:install:lock"
    register: instStatus
    failed_when: "instStatus.rc not in [ 0, 1 ]"
  - debug:
     var: instStatus.stdout_lines

  - name: install Contao-Modules
    shell: "{{ php_path }} -q -dmax_execution_time=0 -dmemory_limit=-1 -dallow_url_fopen=1 web/contao-manager.phar.php composer require {{ item }} --prefer-dist --no-progress --no-ansi --no-interaction --optimize-autoloader"
    args:
      chdir: '{{ websitePath }}'
    loop: "{{ contao_modules }}"

  - name: update/create database-shema
    command: "{{ php_path }} -d memory_limit=-1 {{ websitePath }}/vendor/bin/contao-console contao:migrate"
    register: dbupdate
  - debug:
     var: dbupdate.stdout_lines

  - name: create Conato-BackendUser
    command: "{{ php_path }} -d memory_limit=-1 {{ websitePath }}/vendor/bin/contao-console contao:user:create --username={{ item[0] }} --name='{{ item[1] }}' --email='{{ item[2] }}' --password='{{ item[3] }}' --change-password {{ item[5] }} --language={{ item[4] }}"
    with_nested:
    - "{{ users }}"
    when:
      - composerJsonExists.stat.exists == false
      - ( contao_version == '4.10' ) or ( contao_version == '4.11' )

Was macht dieses Playbook?

Es werden 19 Tasks abgearbeitet:

  1. Es wird geprüft ob bereits eine Installation vorhanden ist, eine composer.json existiert. Danach werden einige Schritte übersprungen.
  2. Das Verzeichnis web wird angelegt, falls es noch nicht existiert.
  3. Das Verzeichnis contao-manager wird angelegt, falls es noch nicht existiert.
  4. Die Konfiguration des Contao-Manager wird aus dem Template angelegt.
  5. Das Passwort für dem Contao-Manager-Benutzer wird lokal verschlüsselt.
  6. Das verschlüsselte Passwort für dem Contao-Manager-Benutzer wird in eine Variable geschrieben.
  7. Das Admin Benutzerkonto des Contao-Manager wird aus dem Template angelegt.
  8. Der Contao-Manager wird her runtergeladen.
  9. Die Composer Datei wird aus dem Template angelegt.
  10. Die Contao-Installation wird durchgeführt.
  11. Das Verzeichnis config wird angelegt, falls es noch nicht existiert. (ehemals app/config)
  12. Die Contao-Datenbank-Konfiguration wird aus dem Template angelegt.
  13. Das Passwort für das Install-Tool wird lokal verschlüsselt.
  14. Das verschlüsselte Passwort für das Install-Tool wird in eine Variable geschrieben.
  15. Die Contao-Konfig wird aus dem Template angelegt.
  16. Das Install-Tool wird aus Sicherheitsgründen gesperrt.
  17. In der Konfigurationsdatei hinterlegte Contao-Module werden installiert.
  18. Die Datenbank wird aktualisiert/angelegt.
  19. Für Contao ab 4.10 können wir auch die Backend-Benutzer direkt anlegen.

templates/composer.j2

{
    "type": "project",
    "require": {
        "contao/conflicts": "*@dev",
        "contao/manager-bundle": "{{ contao_version }}.*"
    },
    "extra": {
        "contao-component-dir": "assets"
    },
    "scripts": {
        "post-install-cmd": [
            "Contao\\ManagerBundle\\Composer\\ScriptHandler::initializeApplication"
        ],
        "post-update-cmd": [
            "Contao\\ManagerBundle\\Composer\\ScriptHandler::initializeApplication"
        ]
    }
}
Information

Ich mache nur die Contao-Basis Installation wer möchte kann in seiner composer.j2 natürlich auch alle Contao-Module für die vollständige Installation hinterlegen.

templates/contao-manager-config.j2

{
    "__comment" : "{{ ansible_managed }}",
    "preferred-install": "dist",
    "store-auths": false,
    "optimize-autoloader": true,
    "sort-packages": true,
    "discard-changes": true
}

templates/contao-manager-user.j2

{
    "__comment" : "{{ ansible_managed }}",
    "users": {
        "{{ contao_manager_user }}": {
            "username": "{{ contao_manager_user }}",
            "password": "{{ contao_manager_pass_crypt }}"
        }
    }
}

templates/localconfig.php.j2

<?php
// {{ ansible_managed }}

### INSTALL SCRIPT START ###
$GLOBALS['TL_CONFIG']['licenseAccepted'] = true;
$GLOBALS['TL_CONFIG']['installPassword'] = '{{ psk }}';
$GLOBALS['TL_CONFIG']['websiteTitle'] = '{{ websiteTitle }}';
$GLOBALS['TL_CONFIG']['adminEmail'] = '{{ adminEmail }}';
$GLOBALS['TL_CONFIG']['minifyMarkup'] = true;
$GLOBALS['TL_CONFIG']['gzipScripts'] = true;
$GLOBALS['TL_CONFIG']['maxFileSize'] = 20480000;
$GLOBALS['TL_CONFIG']['imageWidth'] = 3000;
$GLOBALS['TL_CONFIG']['imageHeight'] = 3000;
### INSTALL SCRIPT STOP ###
Information

Ich habe hier einige Werte hart hinterlegt, die können natürlich auch individuell gesetzt werden und durch Variablen definiert werden.

templates/parameters.sh.j2

# {{ ansible_managed }}
parameters:
  database_host: {{ database_host | default("localhost") }}
  database_port: {{ database_port | default("3306") }}
  database_user: {{ database_user }}
  database_password: '{{ database_password }}'
  database_name: {{ database_name }}

Wie führe ich das nun aus?

Wenn ich nur eine Installation aktualisieren möchte, dann nutze ich folgenden Befehl:

ansible-playbook -i customers/kirsten-roschanski.de.yml install_base.yml

dieses kann ich nur machen, da mein SSH-Key auf dem Server hinterlegt ist. Wenn ich das Passwort eingeben muss, dann rufe ich das mit der Option -k auf:

ansible-playbook -i customers/kirsten-roschanski.de.yml -k install_base.yml
Notiz

Auch wenn hier mehre Installationen auf einmal neu aufsetzen kann und abfrage ob die Installation schon besteht. Verzichte ich bewusst darauf. Denn eine Installation führe ich nur einmal durch. Wie man die Installation aktualisiert habe ich in Teil 1 bereits gezeigt. Wie sie verwaltet wird, zeige ich in einem der nächsten Teile.

Wie geht es weiter?

Im nächsten Teil zeige ich in einem Playbook wie ich voll automatisch ein Contao-Upgrade mache. Denn ab morgen ist die 4.10 nicht mehr unterstützt und die Contao 4.11 erscheint. Da möchte ich natürlich so schnell wie möglich auf die neue Version wechseln.