Beiträge zu “Ansible”
Cisco SIP Telefone für Asterisk mit Ansible verwalten
Ich verwende seit kurzem wieder ausschließlich Asterisk als Telefonanlage und dazu Cisco 7960 SIP Telefone.
Generell ist diese Konfiguration in diesem Privathaushalt mit Homeoffice recht einfach. Jeder darf mit jedem telefonieren und ich lege zentral fest welches Telefon bei welcher externen Nummer klingel soll. Also keine Benutzer mit Kennwörtern sondern nur Geräte mit Nummern. Das macht es mir möglich einen Großteil der Konfiguration in Ansible zu verwalten.
Die Konfiguration ist im Prinzip nicht schwer, geschieht aber an verschiedenen Stellen und ist deshalb etwas fusselig.
Telefongeräte
Für jedes Telefongerät muss eine Konfiguration erstellt werden die sich das Telefon beim Booten von einem TFTP Server zieht. Dort stehen also schon mal Namen und Kennwörter. Diese Konfigurationsdatei muss in dem Namen die MAC Adresse des Telefons haben.
Asterisk
Auch hier wird für jedes Telefon ein “Account” angelegt und es muss festgelegt werden unter welcher Nummer es extern erreichbar ist, welche Nummer es beim telefonieren verwenden soll und das man es intern erreichen kann.
Neuanlage eines Telefons
Man trägt also für jedes Telefon zuerst die Nummer in der SIP Configuration ein, legt einen Eintrag für die Extension an und dann noch mal diese SIP Konfiguration auf dem FTP Server.
Und überall stehen im wesentlichen nur ein paar Informationen wiederholt drin.

Automatisierung mit Ansible
(Der folgende Text setzt schon Ansible Wissen voraus.)
Das Playbook besteht aus folgenden Dateien
roles/asterisk/
├── handler
│ └── main.yml
├── tasks
│ └── main.yml
└── templates
├── interne-erreichbarkeit-sip-conf.j2
├── sip-config-xml.j2
└── sip-conf.j2
In der Konfiguration des Asterisk Servers sind folgende Variablen für jedes Telefon enthalten
- sipname: "311"
name: "311"
callerid_name: "Familie Bauer"
callerid_num: "+49222xxxx"
logo_url: "http://server.domain.lcl/eigenes-cisco-logo.bmp"
mac: "0016Cxx228E"
Asterisk Extensions
Es wird für jedes Telefon eine Datei angelegt in der steht unter welcher Nummer ein Telefon erreichbar ist
- name: create config directory in asteriskdir
file:
path: "/etc/asterisk/my/"
state: directory
mode: 0750
- name: Create a rule for internal-calls.conf
template:
src=interne-erreichbarkeit-sip-conf.j2
dest=/etc/asterisk/my/internal-calls-{{ item.name }}.conf
owner=asterisk
group=asterisk
mode=0750
with_items: "{{ sipphones }}"
Das Template sie so aus und enthält nur eine Zeile.
exten => {{ item.name }} ,1,Dial(SIP/{{ item.name }})
In der extension.conf werden alle diese Konfigurationen eingebunden
#include "my/internal-calls-\*.conf"
Damit ist gibt es für jedes Telefon eine Anrufmöglichkeit.
Telefon Definition
Ähnlich baue ich die SIP Definitionen
Task:
- name: Create a sip1.conf
template:
src=sip-conf.j2
dest=/etc/asterisk/my/sip-{{ item.name }}.conf
owner=asterisk
group=asterisk
mode=0750
with_items: "{{ sipphones }}"
Template:
[{{ item.name }}] ; Name
type=friend
username = {{ item.name }}
secret = {{ item.name }}
pickupgroup = 1
callgroup = 1
context=mycontext;
setvar=EXTERNAL_CALLERID=”{{ item.callerid_name }}” <{{ item.callerid_num }}>;
....
.....
.....
{% if item.mailbox is defined %}
mailbox= {{ item.mailbox }}
{% endif %}
In der /etc/asterisk/sip.conf steht dann
#include /etc/asterisk/my/sip-\*.conf
Telefonkonfiguraton
Bleibt noch die Konfiguration der Telefone selbst. Auch die ist recht einfach gehalten aber mit etwas Logik kann man das auch komplizierter machen.
Tasks:
- name: Create a Phone XML Configuration
template:
src=sip-config-xml.j2
dest=/opt/tftp/diskless/SIP{{ item.mac }}.cnf
owner=asterisk
group=asterisk
mode=0750
with_items: "{{ sipphones }}"
Template:
phone_label: "{{ item.name }}"
proxy_register: 1
line1_name: "{{ item.name }}"
line1_displayname: "{{ item.name }}"
line1_shortname: "{{ item.name }}"
line1_authname: "{{ item.name }}"
line1_password: "{{ item.name }}"
{% if item.logo_url is defined %}
logo_url: "{{ item.logo_url }}"
{% endif %}
Ergebniss
Jetzt trage ich nur noch in der Ansible Server Konfiguration ein neues Telefon mit der gewünschten Nummer und der Mac Adresse ein und mit einem Befehl wird der Account definiert, die Nummer eingerichtet und die Telefonkonfiguration erstellt.
ansible-playbook asterisk.yml -b
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

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.

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.
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
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.
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
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.
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)
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