Beiträge zu dem Tag: “Ansible”

Freifunkknoten mit Ansible konfigurieren

An dieser Stelle habe ich meine Vorgehensweise beschrieben wie ich einen einzelnen Router so konfiguriere das er bestimmte Rechner nicht verbindet.

Da ich dies zukünftig nicht nur auf einem Router machen muss und auch noch weitere Konfigurationen auf verschiedenen Routern verwalten muss bietet es sich natürlich an hier wie auf meinen anderen Servern auch Ansible zu verwenden.

Leider gibt es aktuell noch kein richtiges Modul um die Paket- und Variablenverwaltung anzusprechen aber mit dem Modul “raw” kann man die Befehle selbst ausführen. Es fehlt zwar die Rückmeldung über das Ergebnis aber es ist immer noch besser als einloggen und “befehle pasten”

Zuerst brauchen wir in unserem Inventory Gruppen mit den Routernamen.

  [freifunk]
  su-mck-1
  
  [ff-update-server]
  su-mck-1
  
  [ff-nodes-with-acl]
  su-mck-1 

Für jeden Router habe ich eine Datei mit Host spezifischen Variablen.

more host_vars/su-mck-1
---
  ansible_port: 22 
  ansible_host: 192.168.xxx.yy
  ansible_user : root
  ff_acl_enabled_radios:
  - radio0
  - radio1
  ff_acl_enabled_macs: "00:11:22:33:C6:2C 00:yy:ee:34" 

Der Router hat zwei Antennen und in der Variable ff_acl_enabled_macs stehen die verbotenen Mac Adressen.

Das Playbook selbst sieht so aus (Da werden zukünftig noch weiter Aufgaben dazukommen)

   more freifunk.yml 
     ---
     - name: manage-ff-nodes
       hosts: freifunk
       gather_facts: no
       roles:
       - freifunk 

Im Role Verzeichnis habe ich die dazugehörigen Dateien

more roles/freifunk/tasks/main.yml 
    ---
    - include : set-acl-list.yml hosts=ff-nodes-with-acl
 
 more roles/freifunk/tasks/set-acl-list.yml 
    ---
    - name: enable deny for configured radios
      raw:  uci set wireless.client_.macfilter=deny
      with_items: ""
    - name: set denied mac addresses 
      raw: uci set wireless.client_.maclist=''
      with_items: ""
      ignore_errors: yes
      notify:
      - uci commit
      - reload network

Fehlt noch die Datei mit dem “Handler”

  more roles/freifunk/handlers/main.yml 
  ---
  - name: uci commit
    raw: uci commit
  - name: reload network
    raw: /etc/init.d/network reload

Jetzt kann ich mit einem Befehl auf allen Routern für die ich in den Hostvars die verschiedenen Antennen und unterschiedlichen Mac Adressen angegeben habe den Router konfigurieren.

ansible-playbook freifunk.yml 
 
PLAY [manage-ff-nodes] ************

TASK [freifunk : enable deny for configured radios]**
changed: [su-mck-1] => (item=radio0)
changed: [su-mck-1] => (item=radio1)

TASK [freifunk : set denied mac addresses] **
changed: [su-mck-1] => (item=radio0)
changed: [su-mck-1] => (item=radio1)

RUNNING HANDLER [freifunk : uci commit] **
changed: [su-mck-1]

RUNNING HANDLER [freifunk : reload network] ***
changed: [su-mck-1]

PLAY RECAP ************************************
su-mck-1                   : ok=4    changed=4    unreachable=0    failed=0   
10.2.18
Weitere Beiträge zu: Freifunk   Ansible  

Ansible Informationen zu Jekyll exportieren

Ich verwende Ansible um die Konfiguration von Servern und Desktop Geräten zu automatisieren. Da ich Jekyll für meinen Blog verwende habe ich begonnen auch die Dokumentation der Server mit Hilfe des Dokumentations Templates zu pflegen. Neben der Beschreibung eines Servers ist es natürlich hilfreich auch technische Informationen dort abzulegen.

Und da ich ja schon viele Informationen in Ansible vorliegen habe lag es natürlich nahe ein Playbook zu schreiben das mir diese Daten direkt in das Jekyll Template exportiert.

Die Idee: Ich nutze die Collections und exportiere die gewünschte Informationen als Input für ein Collectionstemplate.

Dazu brauchen wir also zuerst ein Playbook für den Export.

Für alle Hosts die in der etc-host von Ansible in der Gruppe “Doku” enthalten sind wird mit dem Template server.j2 eine Datei in dem Collection Verzeichnis “_server” erstellt das die gewünschten Ansible Informationen enthält.

vi ansible-2-doku.yml 
  ---
  - hosts: doku
    roles:
      - server-doku
  

vi roles/server-doku/defaults/main.yml 
  ---
  hosts: localhost
  connection: local
  path2jekyll: "/home/user/doku/_server/"

vi roles/server-doku/tasks/main.yml 
   ---
   - name: build collection input
     template: src=templates/server.j2 dest={{ path2jekyll }}/{{ ansible_hostname }}.md
     delegate_to: localhost

vi roles/server-doku/templates/server.j2 
   ---
   layout: server
   title: {{ ansible_hostname }}
   ip :  {{ ansible_fqdn }}
   os : {{ ansible_system }}
   permalink: /host-infos-{{ ansible_hostname }}.html
   tags: [Server, {{ ansible_hostname }} ]
   sidebar: mydoc_sidebar
   folder: mydoc
   ---

So jetzt brauchen wir noch die Collection Definition in Jekyll

 vi _config.yml 
   
   collections:
     server:
       output: true

 vi _layouts/server.html 
 
    ---
    layout: page
    ---
    IP Adresse: {{ page.ip }} <br>
    Betriebssystem : {{ page.os }} <br>
    .....

Jetzt bekommen wir bei jedem Lauf von Jekyll für jeden Server eine html Datei erstellt auf die wir aus anderen Seiten verlinken können.

24.9.17
Weitere Beiträge zu: Ansible   Jekyll  

Entwicklungsumgebungen mit #Ansible automatisieren

Allen, die sich regelmäßig einen LAMP Entwicklungserver aufsetzen müssen, möchte ich noch einmal Ansible ans Herz legen.

Ich bin inzwischen soweit, das ich so gut wie keine administrativen Aufgaben einfach so mit der Hand mache sondern direkt in Ansible automatisiere.

So kann ich inzwischen in 4 manuellen Schritten:

  • einen Debian Server aufsetzen
  • die notwendigen Nutzer mit ssh keys einrichten
  • den Mailversand konfigurieren
  • alle notwendigen Apache / Mysql / PHP Pakete installieren
  • die Mysql Datenbank mit Adminuser einrichten und die Testdaten importieren
  • Bilder und Images für die Anwendung aus einem Backup laden und an die richtige Stelle legen
  • den PHP Code mit Subversion an die richtige Stelle auschecken

und das ganze ist nach 15 Minuten fertig.

Wahrscheinlich könnte ich die Schritte auch noch in 2 zusammenfassen aber das ist mir zu aufwendig.

8.8.15
Weitere Beiträge zu: Ansible   DevOps  

Ansible Playbook: Linux User mit SSH Public Key und Sudo Rechten einrichten.

Das folgende Playbook erlaubt es schnell einen neuen Nutzer unter Linux einzurichten, den öffentlichen Schlüssel an die richtige Stelle zu kopieren und die gewünschten Sudo Rechte zu vergeben. Die Idee hierzu kam mir durch diesen Beitrag

Ausgangspunkt ist dabei ein “neues” Linux System auf das noch mit dem Root User und Kennwort zugegriffen werden kann. Zusätzlich ist der öffentliche Schlüssel über http erreichbar. Ist dieser Anwender eingerichtet sollte der Rootzugriff per Kennwort am besten ausgeschaltet werden

Zuerst die notwendige Software installieren

sudo apt-get install sshpass

Dann das Playbook

vi install-deployment-user.yml
---
- hosts: '{{ target }}'
  remote_user: root
  vars:
     username: newuser
  tasks:
  - name: add user and create ssh key
    user: name={{username}}
  - name: download pubkey and placed as authorized_keys
    get_url: url="yourpublickeyurl" dest=/tmp/temp.authorized_keys
    delegate_to: 127.0.0.1
  - name: Create authorized_keys from the file that just downloaded
    authorized_key: user={{username}} key="{{ lookup('file', '/tmp/temp.authorized_keys') }}"
  - name: Create a sudoer file
    template:
    src=install-deployment-user-sudoers.j2
    dest=/etc/sudoers.d/{{username}}

und das SUDOER Template erstellen (die Berechtigungen natürlich wunschgemäß anpassen)

vi install-deployment-user-sudoers.j2 
    ALL=(ALL:ALL) NOPASSWD: ALL

Aufgerufen wird das ganze dann so

ansible-playbook -k --extra-vars "target=die-neue-ip-address" install-deployment-user.yml
10.11.14
Weitere Beiträge zu: SSH   Ansible  

Postfix "Satellite" Server mit Ansible verwalten

Folgendes Ansible Playbook werde ich verwenden um auf Entwicklungs- und Testservern den SMTP Server Postfix einzurichten. Die Konfiguration soll so erfolgen das alle Mails über einen Google Mail Account gerouted werden. Die Idee habe ich im wesentlichen von hier übernommen. Nur habe ich die Anmeldung mit Mandrill nicht hinbekommen.

Zuerst wird die Software installiert, dann die Kennwörter für Google eingerichet und die notwendigen Konfigurationsänderung vorgenommen.

Hier das Playbook

---
- hosts: dev-server
  sudo : yes
  tasks:
  - name: Installs postfix mail server
    apt: pkg=postfix state=installed update_cache=true
    notify:
    - start postfix
  - name: Upload gmail authentication info
    copy: src=postfix-gmail-password dest=/etc/postfix/sasl_passwd mode=0600 owner=root group=root
    register: gmail
    notify:
     - postmap sasl_passwd
  - name: remove empty mailrelay line
    lineinfile: dest=/etc/postfix/main.cf line="relayhost = " state=absent
  - name: Append gmail relay config
    lineinfile: 
      dest=/etc/postfix/main.cf
      line=""
    with_items:
      - { line: 'smtp_sasl_auth_enable = yes' }
      - { line: 'smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd' }
      - { line: 'smtp_sasl_security_options = noanonymous' }
      - { line: 'smtp_use_tls = yes' }
      - { line: 'relayhost = [smtp.gmail.com]:587' }  
      - { line: 'smtp_tls_security_level = may' }
    notify: 
      - restart postfix
   handlers:
  - name: start postfix 
    service: name=postfix state=started
  - name: make sure postfix user owns postfix dir 
    command: sudo chown postfix /etc/postfix
  - name: postmap sasl_passwd
    command: postmap /etc/postfix/sasl_passwd
    when: gmail|success
  - name: restart postfix
    service: name=postfix state=restarted

Das Template für die Anmeldeinformation

vi postfix-gmail-password

  [smtp.gmail.com]:587 user@gmail.com:password-for-gmail

Aufgerufen wird das dann einfach mit

 ansible-playbook postfix.yml

und schon wird auf allen Entwicklungsservern die gleiche Postfix Konfiguration verteilt.

17.10.14
Weitere Beiträge zu: postfix   Ansible  

SSH Konfigurationen mit Ansible absichern

Ich verwende einige “Standardmaßnahmen” um den Zugriff auf meine Server über SSH abzusichern. Im Prinzip gilt:

  • Kein Zugriff für root
  • Kein Anmelden über Username / Passwort
  • Zugriff über einen nicht Standardport
  • Anmelden nur über Public Key Verfahren für einen Nutzer

Bisher habe ich diese Änderungen immer manuell durchgeführt. Auf Basis dieses Beitrages habe ich für die Konfigurationsänderungen folgendes Ansible Playbook gebaut.

Ist später mal eine Änderung notwendig so kann man diese in das Playbook einfügen und mit einem Befehl sind alle Server wieder auf einem neuen und gleichen Stand.

ACHTUNG: Erst ausführen wenn der Nicht Root Administrator mit Public Key und Sudo Rechten eingerichtet ist

---
- hosts: all
  sudo: yes
  tasks:
    - name: Disallow root SSH access
      action: lineinfile dest=/etc/ssh/sshd_config regexp="^PermitRootLogin" line="PermitRootLogin no" state=present
    - name: Disallow password authentication
      action: lineinfile dest=/etc/ssh/sshd_config regexp="^PasswordAuthentication" line="PasswordAuthentication no" state=present
    - name: Change Default Port
      action: lineinfile dest=/etc/ssh/sshd_config regexp="^Port" line="Port 3422" state=present
    - name: Disallow ChallengeResponseAuthentication
      action: lineinfile dest=/etc/ssh/sshd_config regexp="^ChallengeResponseAuthentication" line="ChallengeResponseAuthentication no" state=present
12.10.14
Weitere Beiträge zu: SSH   Ansible  

Virtuelle Host Dateien von Apache mit Ansible verwalten

Auf einem Webserver kommen schnell unterschiedliche Dienste zusammen die man besser über virtuelle Host trennt. Für Apache muss hierzu eine bestimmte Konfigurationsdatei erstellt werden. Eine Möglichkeit dies zu bewerkstelligen ist es, eine meistens webbasierte Verwaltungsanwendung wie Webmin zu verwenden. Da ich solche Anwendungen nicht mag (wieder eine Anwendung mehr die man aktualisieren und überwachen muss) verwalte ich bisher alle meine Konfigurationen “manuell” über SSH. Das ist zwar “etwas fummeliger” aber am Ende auch nicht so schwierig. Bei ein oder zwei virtuellen Hosts geht das auch noch aber dann wird es unübersichtlich.

Wie bereits hier beschrieben möchte ich Ansible verwenden um dies zu automatisieren. Den genauen Funktionsumfang möchte ich hier nicht erklären, sondern nur meine notwendigen Schritte.

Die meisten vorhandenen Ansible Playbooks gehen von einem “nacktem” Standard Server aus. Dies ist bei mir nicht mehr der Fall und das Ansible Playbook muss es ermöglichen verschiedene Hostdefinitionen für PHP, Perl, HTML Server mit/und/oder SSL zu erstellen. Das folgende Playbook scheint dies zu erreichen. Der hier vorgestellte Ansatz beruht im wesentlichem auf diesem und diesem Dokument.

Zu erst das Playbook. Dort setzte ich im Abschnitt Vars die Variablen die ich später in der VHost Konfiguration brauche. Im Template kann ich dann über die Abrage “if item ‘Variable’ is defined” hostspezifische Variablen setzen.

vi vhost.yml 

---
- hosts: www.server1.de 
  sudo: yes
  vars:
    apache_vhosts_enabled:
    - servername: "www.server1.de "
      serveralias: "server1.de "
      serveradmin: "admin@server1.de "
      SuexecUserGroup: "server1user server1group"
      documentrootdir: "server1.de/public_html"
      logrootdir: "server1/logs"
      InternalAlias: "server1
      Options: "Indexes MultiViews -Includes -FollowSymLinks +ExecCGI"
      DirectoryIndex: "index.html"
      SSLCertificateFile: "path-to-cert.cert.pem"
      SSLCertificateKeyFile: "path-to-key.de.key.pem"
      SSLCACertificateFile: "path-to-CA.."
      SSLVerifyClient: "require"
  tasks:
  - name: Create a VirtualHost file for each enabled VirtualHost
    template:
      src=vhost.j2
      dest="/etc/apache2/sites-available/"{{ item.servername }} 
      owner=root
      group=root
      mode=0644
    with_items: apache_vhosts_enabled

Die relevanten Auszüge im Template sehen so aus.

vi vhost.j2 
    <VirtualHost *:443>
        ServerName {{ item.servername }}
        DocumentRoot /var/www/{{ item.documentrootdir }}
        ServerAdmin {{ item.serveradmin }}
        SuexecUserGroup  {{  item.SuexecUserGroup }}
        DirectoryIndex  {{ item.DirectoryIndex }}
        <Directory "/var/www/{{ item.documentrootdir }}">
            Options {{ item.Options }}
            Order allow,deny
            allow from all
        </Directory>
        CustomLog /var/www/{{ item.logrootdir }}/access.log common
        ErrorLog /var/www/{{ item.logrootdir }}/error.log
        SSLEngine on
{% if item.SSLVerifyClient is defined %}
        SSLVerifyClient require
        SSLVerifyDepth  1
{% endif %}
        SSLCertificateFile /etc/ssl/{{ item.SSLCertificateFile }}
        SSLCertificateKeyFile /etc/ssl/{{ item.SSLCertificateKeyFile }}
        SSLCACertificateFile /etc/ssl/{{ item.SSLCACertificateFile }}
        SSLProtocol All -SSLv2 -SSLv3
        ....
    ....
</VirtualHost>

Über den Befehl

ansible-playbook vhost.yml 

wird dann die Datei aus dem Template und den Variablen zusammengesetzt und über SSH auf dem Server deployed. Man könnte das Playbook jetzt auch noch erweitern das automatisch der Apache einen Reload macht aber am Anfang möchte ich die Ergebnisse erst noch einmal manuell prüfen bevor sie “scharf geschaltet” werden.

Dies ist mein erster Server den ich so konfiguriere und über die Variablen im Playbook und die “is defined” Abfragen im Template werden nach und nach noch weitere Server aufgenommen.

9.10.14
Weitere Beiträge zu: Apache   Ansible  

Getting started mit Ansible

Ich möchte zukünftig Konfigurationen und Einstellungen über verschiedenen Server hinweg automatisieren. Ziel ist es vor allem Fehler zu vermeiden aber natürlich spielt auch der Aspekt der Vermeidung von Aufwänden bei der manuellen Konfiguration eine Rolle. In vielen Quellen habe ich gelesen das Ansible hier eine gute Wahl sein soll.

Meine ersten Ziele sind

  • einheitliche Definition von virtuellen Hosts im Apache Server
  • einheitliche php einstellungen

Später würde ich dann gerne noch Software Installation automatisieren.

Wie immer sind diese Dokumentationen eher eine Aufzeichnung meiner Lernerfahrung als echte Best practises.

Vorrausetzung ist bei mir, das für alle Server der SSH Zugriff über Certificates erfolgt.

Zuerst die Installation

sudo apt-get install ansible

Zu Begin müssen die Server in ein “Inventar” eingetragen werden

sudo vi /etc/ansible/hosts

www.server1.de ansible_ssh_port=32323
www.server2.de ansible_ssh_port=33232

Als ersten Befehl sollte man wohl den berühmten “Ping” ausprobieren. Damit wird schon mal geprüft ob der Zugriff funktioniert

ansible all -m ping
  www.server1.de | success >> {
  "changed": false, 
  "ping": "pong"
 }

 www.server2.de | success >> {
    "changed": false, 
    "ping": "pong"
  }

Ansible soll es mir ja erlauben mit einem Befehl auf unterschiedlichen Servern gleiche Konfigurationen zu setzen oder Befehle auszuführen. Als ersten Test (der hoffentlich nichts kaputt machen kann) möchte ich eine Datei auf Basis eines Templates auf die beiden vorhandenen Server kopieren. Als Testballon habe ich mir dazu die “Message of the Day” (motd) ausgesucht. Der Inhalt dieser Datei wir angezeigt wenn sich ein Anwender einlogt. Als “Variable” möchte ich einen Servernamen verwenden den ich in der Inventardatei setze.

sudo vi /etc/ansible/hosts

www.server1.de ansible_ssh_port=32323 name="webserver"
www.server2.de ansible_ssh_port=33232 name="torserver"

Das verwendete “Template” soll erstmal ganz einfach sein

vi motd.j2
   Willkommen auf .

Das Playbook sieht dann so aus

vi motd.yml

 ---
 - hosts: all
 sudo: yes
 tasks:
 - name: MOTD
  action: template src=motd.j2 dest="/etc/motd" owner=root mode=0644

Aufgerufen sieht das dann so aus :

ansible-playbook  motd.yml

PLAY [all] ******************************************************************** 

GATHERING FACTS *************************************************************** 
ok: [www.server1.de]
ok: [www.server2.de]

TASK: [MOTD] ****************************************************************** 
ok: [www.server1.de]
changed: [www.server2.de]

PLAY RECAP ******************************************************************** 
www.server1.de    : ok=2    changed=0    unreachable=0    failed=0   
www.server2.de    : ok=2    changed=1    unreachable=0    failed=0   

In diesem Fall wurde auf dem ersten Server die Datei nicht verändert, da dies bereits bei einem vorherigen Testlauf geschehen ist und nur die Datei auf dem zweiten Server wurde verändert.

Ach übrigens, wenn man die Destination im Playbook nicht in “” setzt bekommt man diese Fehlermeldung.

failed to parse json:     add_file_common_args=True,
  File "/home/hbauer/.ansible/tmp/ansible-tmp-1412593058.39-183192779237883/copy", line 450, in __init__
    self._log_invocation()
  File "/home/hbauer/.ansible/tmp/ansible-tmp-1412593058.39-183192779237883/copy", line 1057, in _log_invocation
    syslog.syslog(syslog.LOG_NOTICE, unicode(msg).encode('utf8'))
   UnicodeDecodeError: 'ascii' codec can't decode byte 0xe2 in position 144: ordinal not in range(128)
8.10.14
Weitere Beiträge zu: Ansible  

Erste Schritte mit Ansible

Ich habe inzwischen viel gutes über ein Werkzeug namens ansible gehört. Es erlaubt recht einfach Konfigurationen für mehrere Maschinen zu automatisieren ohne das auf diesen Software installiert sein muss.

Ansible is the easiest way to deploy, manage, and orchestrate computer systems you've ever seen. You can get started in minutes.


OK, das mit den Minuten würde ich eher in "in a hour" hochstufen.

Hier meine Schritte auf einem Ubuntu 12.04. Sie basieren im wesentlichen auf dieser Dokumentation. Zuerst eine Abhängigkeiten installieren

sudo apt-get install python-yaml python-jinja2  python-paramiko git

Dann ansible auf Github auschecken:

git clone git://github.com/ansible/ansible.git
Cloning into 'ansible'...
remote: Counting objects: 18889, done.
remote: Compressing objects: 100% (5064/5064), done.
remote: Total 18889 (delta 12608), reused 18230 (delta 12470)
Receiving objects: 100% (18889/18889), 4.27 MiB | 357 KiB/s, done.
Resolving deltas: 100% (12608/12608), done.

und Umgebungsvariablen setzen:

source ./hacking/env-setup
PATH=/home/hbauer/Daten/ansible/ansible/bin:/usr/lib/lightdm/lightdm:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games
PYTHONPATH=/home/hbauer/Daten/ansible/ansible/lib:
ANSIBLE_LIBRARY=/home/hbauer/Daten/ansible/ansible/library
MANPATH=/home/hbauer/Daten/ansible/ansible/docs/man:
Reminder: specify your host file with -i
Done.

In einer bestimmten Datei werden die Rechner mit Namen versehen und können in Gruppen eingeteilt werden. Zuerst mal einige Rechner aus dem Netzwerk hinzufügen bei denen eine Certifikatsbasiertes Login ermöglicht worden ist.

vi ansible_hosts
export ANSIBLE_HOSTS=ansible_hosts


Dann mal einen ersten kleinen Test starten (localhost erlaubt kein Login. Der Fehler ist also "normal")

ansible all -m ping
127.0.0.1 | FAILED => FAILED: [Errno 111] Connection refused
192.168.221.6 | success >> {
    "changed": false,
    "ping": "pong"
}
192.168.221.160 | success >> {
    "changed": false,
    "ping": "pong"
}

Ist man auf dem Zielrechner auch für passwordloses sudo berechtigt kann man als harten Test kann man ja dann mal einen Neustart testen

ansible 192.168.221.xx6 -a "/sbin/reboot" --sudo

Jetzt müsste ich noch

  • Ansible in den Pfad aufnehmen
  • Die Umgebungsvariablen aus ./hacking/env-setup und
  • ansible_host in die Loginvariablen aufnehmen
     
26.11.12
Weitere Beiträge zu: Ansible  

Dies ist ein privater Blog von Hagen Bauer- berufstätiger Vater, Ehemann, Naturliebhaber, Läufer, Zelter, technikverliebt.


Creative Commons License
This blog is licensed under a Creative Commons License