Inhaltsverzeichnis

Dieser Artikel ist älter als ein Jahr und könnte daher Informationen enthalten, die nicht mehr auf einem aktuellen Stand sind.

Ansible ist eine Open Source Software, mit der sich die Konfiguration von linuxbasierten IT-Systemen automatisieren lässt. Damit wird es ermöglicht, Test- und Entwicklungsumgebungen wiederkehrend auf einen bestimmten Stand zu bringen. Im Gegensatz zu eher komplexen Anwendungen wie Puppet oder Chef ist der Einarbeitungsaufwand und die Systemvoraussetzungen bei Ansible gering. Am Beispiel einer Testumgebung für das Shopssystem PrestaShop wird die Nutzung nachfolgend erläutert.

Voraussetzungen

Da PrestaShop in einer virtuellen Maschine laufen soll, wird zusätzlich eine Virtualisierungssoftware benötigt. Die Wahl fällt hier auf VirtualBox. Die Verbindung von VirtualBox und Ansible übernimmt Vagrant. Dateien zur Installation findet man auf folgenden Seiten für VirtualBox, Vagrant und Ansible. Unter Debian/Ubuntu ist die Installation per Apt schnell erledigt. Bei Vagrant sollte man vorher schauen, ob es zwischenzeitlich eine neue Version gibt und ob man die 32- oder 64bit-Version benötigt.

1 $ sudo apt-get install virtualbox virtualbox-qt virtualbox-dkms virtualbox-guest-dkms
2 
3 $ wget https://releases.hashicorp.com/vagrant/1.8.5/vagrant_1.8.5_x86_64.deb
4 $ sudo dpkg -i vagrant_1.8.5_x86_64.deb
5 
6 $ sudo apt-get install software-properties-common
7 $ sudo apt-add-repository ppa:ansible/ansible
8 $ sudo apt-get update
9 $ sudo apt-get install ansible

Dateistruktur

Wenn alle Verzeichnisse und Dateien angelegt wurden, die für die Erstellung der Testumgebung durch Ansible und Vagrant notwendig sind, ergibt sich die folgende Dateistruktur.

 1 ├── ansible
 2 │   ├── group_vars
 3 │   │   └── all
 4 │   ├── hosts
 5 │   ├── playbook.yml
 6 │   └── roles
 7 │       ├── apache
 8 │       │   ├── handlers
 9 │       │   │   └── main.yml
10 │       │   ├── tasks
11 │       │   │   └── main.yml
12 │       │   └── templates
13 │       │       └── etc-apache2-sites-available-default.j2
14 │       ├── apt
15 │       │   └── tasks
16 │       │       └── main.yml
17 │       ├── mail
18 │       │   ├── tasks
19 │       │   │   └── main.yml
20 │       │   └── templates
21 │       │       └── usr-local-bin-sendmail.j2
22 │       ├── mysql
23 │       │   ├── handlers
24 │       │   │   └── main.yml
25 │       │   └── tasks
26 │       │       └── main.yml
27 │       ├── php
28 │       │   └── tasks
29 │       │       └── main.yml
30 │       ├── prestashop
31 │       │   └── tasks
32 │       │       └── main.yml
33 │       └── utils
34 │           └── tasks
35 │               └── main.yml
36 ├── Vagrantfile
37 └── www

Die Dateien findet man auch auf https://github.com/stekan/PrestaShop-Ansible, so dass man diese nicht selbst anlegen muss.

Vagrant-Konfiguration

In der Datei Vagrantfile wird die Konfiguraton für Vagrant erstellt. Dort wird das Betriebssystem festgelegt, das die Grundlage innerhalb der virtuellen Maschine sein soll. In diesem Fall ist es die Ubuntu-Version Xenial Xerus.

Desweiteren der Hostname, die IP-Adresse und der Port, unter der die virtuelle Maschine erreichbar ist. Sowie das Verzeichnis, das zur Synchronisation zwischen Host -und Gastsystem genutzt wird und in dem später die PrestaShop-Dateien gespeichert werden.

Vagrant bietet mehrere Varianten, um Verzeichnisse zwischen Host- und Gastsystem zu synchronisieren. Aufgrund der besseren Geschwindigkeit wird bei config.vm.synced_folder die Variante rsync gewählt.

PROJECT_NAME = "PrestaShop-Ansible"
VAGRANTFILE_API_VERSION = "2"
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
  config.vm.box = "ubuntu/xenial64"
  config.vm.box_url = "https://vagrantcloud.com/ubuntu/boxes/xenial64"
  config.vm.hostname = 'prestashop.dev'
  config.vm.network :private_network, ip: "192.168.33.103"
  config.vm.network :forwarded_port, guest: 80, host: 8080
  config.vm.provider :virtualbox do |v|
    v.name = PROJECT_NAME
    v.customize ["modifyvm", :id, "--memory", 2048]
  end
  config.vm.synced_folder "www", "/var/www", :owner => "www-data", :group=>'vagrant', mount_options: ["dmode=775,fmode=664"], type: "rsync", rsync__exclude: "cache/", disabled: true
  if Vagrant.has_plugin?("vagrant-gatling-rsync")
    config.gatling.latency = 0.7
    config.gatling.rsync_on_startup = false
  end
  config.vm.provision "ansible" do |ansible|
    ansible.playbook = "ansible/playbook.yml"
    ansible.inventory_path = "ansible/hosts"
    ansible.verbose = "v"
    ansible.limit = "all"
  end
end

Ansible-Konfiguration

Die Konfigurationsdateien bei Ansible basieren auf dem YAML-Format. Bei der Konfiguration kann man unterscheiden zwischen:

  • Vars (Konfigurationswerte)
  • Tasks (Aktionen wie z.B. die Installation eines Webservers)
  • Handlers (sind auch Aktionen, die jedoch von anderen Tasks aufgerufen werden können wie z.B. der Neustart des Webservers)
  • Templates (Vorlagen für Konfigurationsdateien, die auf der Template-Engine Jinja2 basieren)

Diese vier Punkte können zu Roles zusammengefasst werden, damit man diese einfacher in andere Projekten übertragen kann.

Hosts

In der Datei ansible/hosts werden alle Host festgelegt, die Ansible verwalten soll. In diesem Fall gibt es nur einen Host.

[webservers]
192.168.33.103

Playbook

In der Datei ansible/playbook.yml wird festgelegt, auf welchen Hosts und mit welchen Benutzerrechten Anweisungen durchgeführt werden. Danach erfolgt die Angabe, welche Roles abgearbeitet werden sollen.

- hosts: all
  become: yes
  become_method: sudo
  gather_facts: no
  pre_tasks:
    - name: these pre_task install python2
      raw: sudo apt-get -y install python-simplejson
  roles:
    - apt
    - apache
    - mysql
    - php
    - mail
    - utils
    - prestashop

Konfigurationswerte

In der Datei ansible/group_vars/all werden Konfigurationswerte für MySQL, PHP und PrestaShop gesetzt, die dann bei der Ausführung ersetzt werden.

host_name: prestashop.dev:8080
mysql_db_host: localhost
mysql_db_name: prestashop
mysql_db_user: prestashop
mysql_db_password: prestashop
mysql_encoding: utf8
mysql_collation: utf8_general_ci
php_timezone: Europe/Berlin
ps_repo: https://github.com/PrestaShop/PrestaShop.git
ps_version: 1.6.1.6
ps_user_firstname: John
ps_user_lastname: Doe
ps_user_email: pub@prestashop.com
ps_user_password: 0123456789
ps_language: de
ps_timezone: Europe/Berlin
ps_country: de

Apt

Die Datei ansible/roles/apt/tasks/main.yml ist für die Aktualisierung der hinzugefügten Pakete per Apt zuständig und wird bei der Provisionierung nach der Ersteinrichtung aktiv. Mehr zu Aktualisierungen ganz unten.

---
# these tasks update and upgrade debian/ubuntu packages via apt
- name: apt update
  apt: update_cache=yes cache_valid_time=3600
  register: apt_result
  until: apt_result|success
  retries: 3
  delay: 1
  ignore_errors: yes
- name: retry if needed using command apt-get update
  command: apt-get update
  when: apt_result|failed

Apache-Webserver

Die Role zur Einrichtung des Webserver besteht aus drei Dateien. Task, Handler und das Template für die Einrichtung des VirtualHost.

Server installieren und konfigurieren

Die Datei ansible/roles/apache/tasks/main.yml ist für die Installation und Einrichtung zuständig. Dort wird außerdem mod_rewrite aktiviert und die Default-Website eingerichtet.

---
# these tasks install and started apache
- name: ensure apache is installed
  action: apt pkg=apache2 state=installed
- name: ensure apache is running
  action: service name=apache2 state=started
- name: ensure libapache2-mod-php is installed
  action: apt pkg=libapache2-mod-php state=installed
- name: enable mod_rewrite
  action: command /usr/sbin/a2enmod rewrite
- name: configuration file for our site
  action: template src=etc-apache2-sites-available-default.j2 dest=/etc/apache2/sites-available/default
- name: activate default host
  file: src=/etc/apache2/sites-available/default dest=/etc/apache2/sites-enabled/000-default.conf state=link
  notify: restart apache

VirtualHost festlegen

Die Datei ansible/roles/apache/templates/etc-apache2-sites-available-default.j2 ist die Template-Vorlage für den Standard-Host in Apache. Es handelt sich um die übliche Apache-Vorlage ergänzt um eine Umgebungsvariable SetEnv APPLICATION_ENV development.

<VirtualHost *:80>
    ServerAdmin webmaster@localhost
    DocumentRoot /var/www
    <Directory />
        Options FollowSymLinks
        AllowOverride All
    </Directory>
    <Directory /var/www/>
        Options Indexes FollowSymLinks MultiViews
        AllowOverride All
        Require all granted
        SetEnv APPLICATION_ENV development
    </Directory>
    ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/
    <Directory "/usr/lib/cgi-bin">
        AllowOverride All
        Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch
        Order allow,deny
        Allow from all
    </Directory>
    ErrorLog ${APACHE_LOG_DIR}/error.log
    # Possible values include: debug, info, notice, warn, error, crit,
    # alert, emerg.
    LogLevel warn
    CustomLog ${APACHE_LOG_DIR}/access.log combined
    Alias /doc/ "/usr/share/doc/"
    <Directory "/usr/share/doc/">
        Options Indexes MultiViews FollowSymLinks
        AllowOverride All
        Order deny,allow
        Deny from all
        Allow from 127.0.0.0/255.0.0.0 ::1/128
    </Directory>
</VirtualHost>

Handlers anlegen

In der Datei ansible/roles/apache/handlers/main.yml werden Handlers angelegt, damit andere Tasks den Webserver neu starten können. Der Aufruf lautet dann z.B. notify: restart apache.

---
- name: reload apache
  action: service name=apache2 state=reloaded
- name: restart apache
  action: service name=apache2 state=restarted

MySQL-Datenbank

In der Datei ansible/roles/mysql/tasks/main.yml geht es um die Installation von MySQL. Das Paket python-mysqldb wird von Ansible benötigt, damit unter anderem Datenbanken angelegt werden können.

---
# these tasks install and started mysql
- name: ensure mysql is installed
  apt:
    pkg: "{{item}}"
    update_cache: yes
  with_items:
    - mysql-server
    - mysql-client
    - python-mysqldb
- name: uncomment log_slow_queries
  lineinfile: dest=/etc/mysql/my.cnf regexp=^log_slow_queries line=#log_slow_queries
  notify : restart mysql
- name: ensure mysql is running
  service: name=mysql state=started

Auch bei MySQL gibt einen Handler zum Neustart. Dafür wird die Datei ansible/roles/mysql/handlers/main.yml angelegt.

---
- name: restart mysql
  service: name=mysql state=restarted

PHP

In der Datei ansible/roles/php/tasks/main.yml erfolgt die Installation und Konfiguration von PHP. Es werden einige Module geladen, die für PrestaShop notwendig sind. Desweiteren werden PHP-Einstellungen angepaßt, um eine bessere Entwicklungsumgebung zu erhalten.

---
# these tasks install php modules
- name: ensure php modules are installed
  apt:
    pkg: "{{item}}"
    update_cache: yes
  with_items:
    - php
    - php-curl
    - php-mcrypt
    - php-gd
    - php-mysql
    - php-cli
    - php-memcache
    - php-intl
    - php-xdebug
    - php-xml
    - php-simplexml
    - php-zip
- name: configure php settings
  lineinfile: dest=/etc/php/7.0/apache2/php.ini regexp="^{{ item.param }} =" line="{{ item.param }} = {{ item.value }}"
  with_items :
    - { param: 'error_reporting', value: 'E_ALL' }
    - { param: 'display_errors', value: 'On' }
    - { param: 'upload_max_filesize', value: '10M' }
    - { param: 'post_max_size', value: '10M' }
    - { param: 'max_execution_time', value: '240' }
    - { param: 'memory_limit', value: '512M' }
  notify : restart apache
- name: configure php xdebug
  lineinfile: dest=/etc/php/mods-available/xdebug.ini regexp="^{{ item.param }} =" line="{{ item.param }} = {{ item.value }}" create=yes mode=0644
  with_items :
    - { param: 'xdebug.remote_enable', value: '1' }
    - { param: 'xdebug.scream', value: '1' }
    - { param: 'xdebug.cli_color', value: '1' }
    - { param: 'xdebug.show_local_vars', value: '1' }
    - { param: 'xdebug.max_nesting_level', value: '400' }
  notify : restart apache
- name: set timezone
  lineinfile: dest=/etc/php/7.0/apache2/php.ini regexp="^[#|;]?date.timezone =" insertafter="^[#|;]?date.timezone =" line="date.timezone = {{ php_timezone }}"
  notify: restart apache
- name: set timezone php cli
  lineinfile: dest=/etc/php/7.0/cli/php.ini regexp="^[#|;]?date.timezone =" insertafter="^[#|;]?date.timezone =" line="date.timezone = {{ php_timezone }}"
  notify: restart apache

E-Mails

In der Datei ansible/roles/mail/tasks/main.yml geht es darum, dass die von PrestaShop versandten E-Mails abgefangen und im Verzeichnis /var/log/mail als Datei gespeichert werden sollen. Außerdem wird das Logging der Mails in die Datei /var/log/mail/mail.log aktiviert.

---
# these tasks configure catch emails to logfile
- name: ensure mail directory exists
  file: dest=/var/log/mail state=directory mode=0777
- name: file to catch emails
  action: template src=usr-local-bin-sendmail.j2 dest=/usr/local/bin/sendmail mode=0755
- name: change sendmail_path
  lineinfile: dest=/etc/php/7.0/apache2/php.ini regexp="^[#|;]?sendmail_path =" insertafter="^[#|;]?sendmail_path =" line="sendmail_path = /usr/local/bin/sendmail"
  notify: restart apache
- name: activate log
  lineinfile: dest=/etc/php/7.0/apache2/php.ini regexp="^[#|;]?mail.log =" insertafter="^[#|;]?mail.log =" line="mail.log = /var/log/mail/mail.log"
  notify: restart apache

Die Datei ansible/roles/mail/templates/usr-local-bin-sendmail.j2 ist eine Vorlage, um die per sendmail versandten E-Mails abzufangen und in /var/log/mail/ zu speichern.

#!/usr/bin/php
<?php
$input = file_get_contents('php://stdin');
$filename = '/var/log/mail/'.time().'.txt';
file_put_contents($filename, $input);
?>

Als Alternative zu dieser Methode bietet sich der Einsatz von mailcatcher an. Dort wird ein einfacher SMTP-Server mit Weboberfläche zur Verfügung gestellt, so dass man HTML-Emails besser anschauen kann. Es ist auch möglich, dass man in PrestaShop den Versand auf SMTP ändert, so dass man einen externen Server für die E-Mails nutzt.

Weitere Installationen

Mit der Datei ansible/roles/utils/tasks/main.yml werden weitere Programme installiert, die für die Einrichtung und den Betrieb von PrestaShop sinnvoll sind. Git wird für den Installationsprozess benötigt.

---
# these tasks install utils
- name: ensure utils are installed
  apt:
    pkg: "{{item}}"
    update_cache: yes
  with_items:
    - curl
    - unzip
    - git
    - memcached

PrestaShop

Abschließend wird mit der Datei ansible/roles/prestashop/tasks/main.yml PrestaShop installiert und eingerichtet. Es gibt bei PrestaShop die Möglichkeit, die Installation per Kommandozeile zu erledigen, so dass der üblicherweise manuelle Installationsvorgang im Browser entfällt.

Der Debug-Modus wird in PrestaShop aktiviert, so dass Fehlermeldungen sichtbar sind und die Dateirechte werden großzügig vergeben. In einem Produktivshop würde man diese Einstellungen nicht vornehmen, aber es geht ja hier um eine Umgebung zum Kennenlernen von PrestaShop oder zum Entwickeln von Modulen und Themes.

---
# these tasks install and configure prestashop
- name: remove apache default directory
  file: path=/var/www state=absent
- name: clone prestashop github repository and submodules
  git: repo={{ ps_repo }} dest=/var/www/ version={{ ps_version }} recursive=yes
- name: create a mysql user
  mysql_user: host={{ mysql_db_host }} name={{ mysql_db_user }} password={{ mysql_db_password }} priv=*.*:ALL state=present
- name: setup empty database for project
  mysql_db: name={{ mysql_db_name }} encoding={{ mysql_encoding }} collation={{ mysql_collation }} state=present login_host={{ mysql_db_host }} login_user={{ mysql_db_user }} login_password={{ mysql_db_password }}
- name: install prestashop using cli
  command: /usr/bin/php index_cli.php --domain={{ host_name }} --db_server={{ mysql_db_host }} --db_user={{ mysql_db_user }} --db_password={{ mysql_db_password }} --db_name={{ mysql_db_name }} --db_clear=1 --language={{ ps_language }} --timezone={{ ps_timezone }} --country={{ ps_country }} --firstname={{ ps_user_firstname }} --lastname={{ ps_user_lastname }} --password={{ ps_user_password }}  --email={{ ps_user_email }} --newsletter=0 chdir=/var/www/install-dev
- name: activate debug modus
  lineinfile: dest=/var/www/config/defines.inc.php regexp="define('_PS_MODE_DEV_', false);" line="define('_PS_MODE_DEV_', true);" owner=www-data group=www-data mode=0644 backrefs=yes
- name: set permissions
  file: path=/var/www mode=0777 recurse=yes state=directory owner=www-data group=ubuntu
- name: ensure apache is running
  service: name=apache2 state=started

Virtuelle Box starten

Sofern noch nicht geschehen, muss man noch ein Verzeichnis www anlegen, dass für die Synchronisation zwischen Host- und Gastsystem dienen soll. Außerdem muss ein Eintrag in die lokale Hostdatei erfolgen. Üblicherweise findet man die unter /etc/hosts.

127.0.0.1       prestashop.dev

Wenn alle Dateien und Verzeichnisse angelegt wurden, reicht ein vagrant up, damit der Download und die Einrichtung beginnt. Nach Fertigstellung kann man den fertig eingerichteten PrestaShop im Browser aufrufen:

  • Frontend: http://prestashop.dev:8080
  • Backoffice: http://prestashop.dev:8080/admin-dev/
    • E-Mail: pub@prestashop.com
    • Password: 0123456789

Die erstmalige Einrichtung kann einige Zeit in Anspruch nehmen. Das Betriebssystem Ubuntu wird zwischengespeichert und muss beim Anlegen neuer virtuellen Maschinen nicht erneut heruntergeladen werden.

PrestaShop 1.7

Man kann auch die kommende PrestaShop-Version 1.7 testen, wobei dafür noch manuelle Aktionen notwendig sind. Zuerst ist in der Datei ansible/group_vars/all die Version auf ps_version: develop zu ändern. Wenn man bereits mit vagrant up PrestaShop 1.6 installiert hatte, muss man die Provisionierung erneut ausführen.

1 vagrant provision

Für die Installation muss man sich auf dem Gastsystem einloggen, Composer laden und ausführen sowie Dateirechte setzen und die Installation von PrestaShop manuell im Browser durchlaufen. Eventuell muss man sich einen Github-Token holen, damit man Composer ausführen kann.

1 vagrant ssh
2 sudo -i
3 curl -sS https://getcomposer.org/installer | php
4 mv composer.phar /usr/local/bin/composer.phar
5 ln -s /usr/local/bin/composer.phar /usr/local/bin/composer
6 cd /var/www
7 composer install
8 chown -R www-data:ubuntu ./

Es werden dabei einige Parameter abgefragt, wobei man nur database_user und database_password angeben muss.

 1 database_host (127.0.0.1):
 2 database_port (null):
 3 database_name (prestashop):
 4 database_user (root): prestashop
 5 database_password (null): prestashop
 6 database_prefix (ps_):
 7 database_engine (InnoDB):
 8 mailer_transport (smtp):
 9 mailer_host (127.0.0.1):
10 mailer_user (null):
11 mailer_password (null):
12 secret (ThisTokenIsNotSoSecretChangeIt):
13 ps_caching (CacheMemcache):
14 ps_cache_enable (false):
15 cookie_key (ThisTokenIsNotSoSecretChangeIt):
16 cookie_iv (ThisTokenIsNotSoSecretChangeIt):

Danach muss man den Installationsprozess im Browser durchlaufen.

  • Installation: http://prestashop.dev:8080/install-dev/

Sollten keine Parameter abgefragt worden sein, dann erhält man eine Fehlermeldung Access denied for user 'root'@'localhost'. In dem Fall kann man die Datenbank-Zugangsdaten manuell in der Datei app/config/parameters.php ergänzen.

Probleme

Nachfolgend Hinweise zu möglicherweise auftretenden Probleme beim Booten der virtuellen Box.

Timed out while waiting for the machine boot.

Bei dieser Fehlermeldung könnte man probieren, die 32bit-Version zu laden. Dazu muss man in der Datei Vagrantfile den Namen und die URL anpassen.

config.vm.box = "ubuntu/xenial32"
config.vm.box_url = "https://vagrantcloud.com/ubuntu/boxes/xenial32"

Es könnte auch daran liegen, dass die Virtualisierungsfunktion Intel VT-x nicht aktiviert ist. Die findet man im BIOS häufig unter: Advanced --> Processor Configuration --> Intel(R) Virtualization Technology

become is not a legal parameter

Beim Auftauchen dieser Fehlermeldung ist sicherlich eine ältere Ansible-Version installiert worden. Kann man feststellen mit ansible --version. Sofern nicht mindestens die Version 1.9 vorhanden ist, muss man folgende Änderung in ansible/playbook.yml machen.

user: vagrant
sudo: true

anstelle von

become: yes
become_method: sudo

Aktualisierung

Man muss zwischen der Vagrant-Box und der per Ansible hinzugefügten Software unterscheiden. Sofern ein Update der Vagrant-Box zur Verfügung steht, wird dies auf der Konsole gemeldet:

A newer version of the box ‘ubuntu/xenial64’ is available!

Um die Box ubuntu/xenial64 auf den aktuellen Stand zu bringen, reicht folgender Befehl:

1 $ vagrant box update

Die per Ansible hinzugefügte Software kann man aktualisieren, in dem man das Provisionierung durchführt. Provisionierung bedeutet, dass die obigen Ansible-Dateien erneut ausgeführt werden. Dies erreicht man mit folgender Anweisung:

1 $ vagrant provision
Kommentar hinzufügen

Die E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind markiert *

Bitte keine HTML-Tags einfügen.