Browse Source

2016-04-03 Technik/Routing/Labornetz/etc/ansible (Tinc Konfigurationen mit Ansible erzeugen, siehe README)

Ignore-this: d14b2a426823588714291b3207cd8d7
FF-DO-Wiki mesh-j-4 9 years ago
parent
commit
5091bb636c
26 changed files with 596 additions and 0 deletions
  1. 63 0
      Technik/Routing/Labornetz/etc/ansible/README.page
  2. 15 0
      Technik/Routing/Labornetz/etc/ansible/Tinc.yaml
  3. 3 0
      Technik/Routing/Labornetz/etc/ansible/ansible.cfg
  4. 7 0
      Technik/Routing/Labornetz/etc/ansible/inventory/group_vars/FreeBSD.yaml
  5. 5 0
      Technik/Routing/Labornetz/etc/ansible/inventory/group_vars/Linux.yaml
  6. 4 0
      Technik/Routing/Labornetz/etc/ansible/inventory/host_vars/ffdorX.yaml
  7. 41 0
      Technik/Routing/Labornetz/etc/ansible/inventory/hosts
  8. 28 0
      Technik/Routing/Labornetz/etc/ansible/inventory/role_vars/tinc/ffdota.yaml
  9. 27 0
      Technik/Routing/Labornetz/etc/ansible/inventory/role_vars/tinc/ffdotb.yaml
  10. 10 0
      Technik/Routing/Labornetz/etc/ansible/roles/tinc/defaults/main.yaml
  11. 109 0
      Technik/Routing/Labornetz/etc/ansible/roles/tinc/files/rc.d-tincd
  12. 7 0
      Technik/Routing/Labornetz/etc/ansible/roles/tinc/tasks/host.yaml
  13. 11 0
      Technik/Routing/Labornetz/etc/ansible/roles/tinc/tasks/install-directory.yaml
  14. 34 0
      Technik/Routing/Labornetz/etc/ansible/roles/tinc/tasks/install.yaml
  15. 13 0
      Technik/Routing/Labornetz/etc/ansible/roles/tinc/tasks/keypair.yaml
  16. 13 0
      Technik/Routing/Labornetz/etc/ansible/roles/tinc/tasks/main.yaml
  17. 5 0
      Technik/Routing/Labornetz/etc/ansible/roles/tinc/tasks/package.yaml
  18. 21 0
      Technik/Routing/Labornetz/etc/ansible/roles/tinc/tasks/rc-freebsd.yaml
  19. 101 0
      Technik/Routing/Labornetz/etc/ansible/roles/tinc/tasks/stage.yaml
  20. 7 0
      Technik/Routing/Labornetz/etc/ansible/roles/tinc/tasks/tinc-conf.yaml
  21. 7 0
      Technik/Routing/Labornetz/etc/ansible/roles/tinc/tasks/tinc-up.yaml
  22. 5 0
      Technik/Routing/Labornetz/etc/ansible/roles/tinc/templates/host.j2
  23. 3 0
      Technik/Routing/Labornetz/etc/ansible/roles/tinc/templates/rc.conf-global.j2
  24. 6 0
      Technik/Routing/Labornetz/etc/ansible/roles/tinc/templates/rc.conf-instance.j2
  25. 24 0
      Technik/Routing/Labornetz/etc/ansible/roles/tinc/templates/tinc-up.j2
  26. 27 0
      Technik/Routing/Labornetz/etc/ansible/roles/tinc/templates/tinc.conf.j2

+ 63 - 0
Technik/Routing/Labornetz/etc/ansible/README.page

@@ -0,0 +1,63 @@
+---
+format: markdown
+toc: yes
+title: Tinc mit Ansible konfigurieren
+categories: VPN
+...
+
+Notation: `ffdorX` = Name des Tinc hosts (X = 1,2,...); `ffdotT` = Tinc Instanz (T = a,b,...).
+
+# Konfiguration
+
+Zunächst kopierst Du dieses Verzeichnis hier (also das, in dem dieses README liegt:) rekursiv auf Deinen [Ansible](http://docs.ansible.com/ansible/index.html) controller (zB Laptop), etwa nach ~/ansible. Dort führst Du die folgenden Konfigurationen durch.
+
+## inventory
+
+Ein Tinc host namens ffdorX ...
+
+- ... erhält ein file `inventory/host_vars/ffdorX.yaml`, in dem mindestens `tinc_hostname: ffdorX` enthalten ist.  
+  Wenn der tincd dieses hosts von außen erreichbar ist, dann sollte die lokale Adresse, mit denen er auf Verbindungen von außen lauschen soll, in `tinc_bindtoaddresses: [ "A.B.C.D" ]` gesetzt werden. Befindet sich der host hinter NAT mit port forwarding, so ist das seine lokale RFC1918-Adresse, an die der NAT router weiterleitet.  
+  Falls Ansible nur benutzt wird, um die Tinc Konfiguration für den Router ffdorX zu erzeugen, aber nicht um sie direkt per Ansible zu installieren, dann `tinc_install: no` setzen.
+- ... wird in `inventory/hosts` in diejenigen Tinc groups eingetragen, an denen er teilnehmen soll. Also jeweils unter [ffdotT] sowie dem zutreffenden Betriebssystem [FreeBSD] bzw. [Linux].
+- ... wird in die Variablendefinitionen der Tinc-Instanzen, an denen er teilnimmt, eingetragen. Diese befinden sich in `inventory/role_vars/ffdotT.yaml` und umfassen je beteiligtem host folgende Variablen:
+
+~~~
+  - tinc_hostname: ffdorX
+    tinc_hostnumber: X
+    tinc_addresses: [ "A.B.C.D", "A:B::C:D" ]
+    tinc_fib: F
+~~~
+
+  tinc_addresses (optional) sind die public IPs, unter denen dieser tincd Prozess erreichbar ist. tinc_fib (optional) ist die FIB (forwarding table des kernels), welche der tincd dieser Instanz benutzen soll. (tinc_fib funktioniert zZ nur mit FreeBSD; für Linux lässt sich das hoffentlich noch klären.)
+
+## secret
+
+Das Unterverzeichnis `secret` für die Tinc keys befindet sich nicht hier im repository. Du legst es also manuell an:
+
+- In das Verzeichnis `secret/tinc/ffdotT/hosts` werden die public keys der an Instanz T beteiligten hosts gelegt. (Ohne "Address" Zeilen o.dgl.!)
+- Für den host ffdorX, dessen Konfiguration Du mit Ansible erzeugst, legst Du dessen private key für die Instanz ffdotT an die Stelle `secret/tinc/ffdotT/ffdorX.priv`. Existiert dieser noch nicht, erzeugt Ansible ein Schlüsselpaar. (Zur Erzeugung eines Schlüsselpaares wird ein installierter tincd auf dem Ansible controller benötigt.)
+
+# Benutzung
+
+Der Aufruf von Ansible erfolgt im Ansible-Verzeichnis (also zB ~/ansible) mit
+
+	ansible-playbook Tinc.yaml
+
+Wenn die Konfiguration stimmig ist, findest Du anschließend im Unterverzeichnis `staging/ffdorX` die für den host ffdorX erzeugten Tinc-Dateien.
+
+Den Inhalt von staging/ffdorX kannst Du nun manuell auf den host ffdorX kopieren (zB als tarball).
+
+Wenn Du den Router ffdorX mit Ansible direkt managen willst (und dort Python und sudo installiert hast), dann solltest Du in `inventory/host_vars/ffdorX.yaml` ein `tinc_install: yes` setzen. Der aktuelle default Wert für diese und einige andere Variablen befindet sich `roles/tinc/defaults/main.yaml`.
+
+Nach getaner Arbeit kannst Du im Ansible-Verzeichnis mit `rm -rf staging work` aufräumen. Dort befinden sich nur Dateien, die von Ansible (bei jedem Durchlauf des playbooks) generiert werden.
+
+Du kannst das Result eines Durchlaufs aber auch zur Seite legen, um es mit dem Ergebnis eines Folgedurchlaufs zu vergleichen. Etwa um zu sehen, ob Deine Veränderungen an der Ansible-Konfiguration die gewünschten Änderungen am Ergebnis (also der Tinc-Konfiguration) erbracht haben:
+
+~~~
+% ansible-playbook Tinc.yaml
+% mv staging staging.bak
+% # vi inventory/...
+% # vi roles/tinc/templates/...
+% ansible-playbook Tinc.yaml
+% diff -r staging.bak staging
+~~~

+ 15 - 0
Technik/Routing/Labornetz/etc/ansible/Tinc.yaml

@@ -0,0 +1,15 @@
+---
+- hosts: Tinc
+  gather_facts: no
+  roles:
+    - role: tinc
+      _varsfile: ffdota.yaml
+      _phase: stage
+      when: inventory_hostname in groups['ffdota']
+    - role: tinc
+      _varsfile: ffdotb.yaml
+      _phase: stage
+      when: inventory_hostname in groups['ffdotb']
+    - role: tinc
+      _phase: install
+      when: tinc_install

+ 3 - 0
Technik/Routing/Labornetz/etc/ansible/ansible.cfg

@@ -0,0 +1,3 @@
+[defaults]
+inventory=inventory/hosts
+ansible_managed="This file is managed using Ansible: hands off;-)"

+ 7 - 0
Technik/Routing/Labornetz/etc/ansible/inventory/group_vars/FreeBSD.yaml

@@ -0,0 +1,7 @@
+---
+os_name: FreeBSD
+ansible_python_interpreter: /usr/local/bin/python2
+os_dir_etc: /usr/local/etc
+os_dir_sbin: /usr/local/sbin
+#ansible_become_method: su
+#ansible_become_user: toor

+ 5 - 0
Technik/Routing/Labornetz/etc/ansible/inventory/group_vars/Linux.yaml

@@ -0,0 +1,5 @@
+---
+os_name: Linux
+ansible_python_interpreter: /usr/bin/python2
+os_dir_etc: /etc
+os_dir_sbin: /usr/sbin

+ 4 - 0
Technik/Routing/Labornetz/etc/ansible/inventory/host_vars/ffdorX.yaml

@@ -0,0 +1,4 @@
+---
+tinc_hostname: ffdorX
+tinc_bindtoaddresses: [ "A.B.C.D" ]
+#tinc_install: no

+ 41 - 0
Technik/Routing/Labornetz/etc/ansible/inventory/hosts

@@ -0,0 +1,41 @@
+### hosts
+
+ffdorX		ansible_ssh_host=A.B.C.D
+
+### basic groups
+
+[local]
+# FreeBSD: "su" geht nur local und mit patch von ansible/playbook/play_context.py
+
+[ssh]
+ffdorX
+
+### groups
+
+[FreeBSD]
+
+[Linux]
+ffdorX
+
+[Tinc]
+
+[ffdota]
+ffdorX
+
+[ffdotb]
+ffdorX
+
+[Tinc:children]
+ffdota
+ffdotb
+
+### basic group vars
+
+[local:vars]
+ansible_connection=local
+
+[ssh:vars]
+ansible_connection=ssh
+pipelining=True
+
+### group vars -> group_vars/*.yaml

+ 28 - 0
Technik/Routing/Labornetz/etc/ansible/inventory/role_vars/tinc/ffdota.yaml

@@ -0,0 +1,28 @@
+---
+tinc_name: ffdota
+tinc_port: 10011
+tinc_device_tap: /dev/tap11
+tinc_vpn_ipv4_net: 193.43.221.128/28
+tinc_vpn_ipv6_net: 2a03:2260:300a:7001::/64
+tinc_hosts:
+  - tinc_hostname: ffdor1
+    tinc_hostnumber: 1
+    tinc_addresses: [ "2a03:2260:50:5::c12b:d981" ]
+    tinc_fib: 3
+  - tinc_hostname: ffdor2
+    tinc_hostnumber: 2
+    tinc_addresses: [ "2a03:2260:50:5::c12b:d982" ]
+    tinc_fib: 3
+#  - tinc_hostname: ffdor3
+#    tinc_hostnumber: 3
+#    tinc_addresses: [ "2a03:2260:50:5::c12b:d983" ]
+#  - tinc_hostname: ffdor4
+#    tinc_hostnumber: 4
+#    tinc_addresses: [ "2a03:2260:50:5::c12b:d984" ]
+#  - tinc_hostname: ffdor5
+#    tinc_hostnumber: 5
+#    tinc_addresses: [ "2a03:2260:50:5::c12b:d985" ]
+  - tinc_hostname: ffdor6
+    tinc_hostnumber: 6
+    tinc_addresses: [ "2a03:2260:50:5::c12b:d986" ]
+    tinc_fib: 3

+ 27 - 0
Technik/Routing/Labornetz/etc/ansible/inventory/role_vars/tinc/ffdotb.yaml

@@ -0,0 +1,27 @@
+---
+tinc_name: ffdotb
+tinc_port: 10012
+tinc_device_tap: /dev/tap12
+tinc_vpn_ipv4_net: 193.43.221.144/28
+tinc_vpn_ipv6_net: 2a03:2260:300a:7002::/64
+tinc_hosts:
+  - tinc_hostname: ffdor1
+    tinc_hostnumber: 1
+    tinc_addresses: [ "130.180.53.21" ]
+    tinc_fib: 1
+  - tinc_hostname: ffdor2
+    tinc_hostnumber: 2
+    tinc_addresses: [ "130.180.53.20" ]
+    tinc_fib: 1
+  - tinc_hostname: ffdor3
+    tinc_hostnumber: 3
+    tinc_addresses: [ "schuermann.dd-dns.de" ]
+  - tinc_hostname: ffdor4
+    tinc_hostnumber: 4
+    tinc_addresses: [ "195.253.27.62" ]
+#  - tinc_hostname: ffdor5
+#    tinc_hostnumber: 5
+#    tinc_addresses: [ "217.241.112.194", "2003:004d:eb71:b903::affe" ]
+  - tinc_hostname: ffdor6
+    tinc_hostnumber: 6
+    tinc_fib: 1

+ 10 - 0
Technik/Routing/Labornetz/etc/ansible/roles/tinc/defaults/main.yaml

@@ -0,0 +1,10 @@
+---
+tinc_maxtimeout: 60
+tinc_pingtimeout: 10
+tincd: "{{ os_dir_sbin }}/tincd"
+basedir_conf_tinc: "{{ os_dir_etc }}/tinc"
+rolevarsdir_tinc: "{{ inventory_dir }}/role_vars/tinc"
+secretdir_tinc: "{{ playbook_dir }}/secret/tinc"
+workdir_tinc: "{{ playbook_dir }}/work/tinc"
+stagedir: "{{ playbook_dir }}/staging"
+tinc_install: yes

+ 109 - 0
Technik/Routing/Labornetz/etc/ansible/roles/tinc/files/rc.d-tincd

@@ -0,0 +1,109 @@
+#!/bin/sh
+
+# $FreeBSD: head/security/tinc/files/tincd.in 406095 2016-01-14 06:02:05Z dinoex $
+#
+# PROVIDE: tincd
+# REQUIRE: ipfilter FILESYSTEMS sysctl netif
+# BEFORE:  SERVERS routing
+# KEYWORD: nojail
+#
+# Define these tincd_* variables in one of these files:
+#	/etc/rc.conf
+#	/etc/rc.conf.local
+#	/etc/rc.conf.d/tincd
+#
+# tincd_enable (bool):	Set to "NO" by default.
+#			Set it to "YES" to enable tincd.
+# tincd_cfg (str):	Set to "" by default.
+#			Set it to NETNAMEs to use (ex.: "vpn1 vpn2").
+# tincd_flags (str):	Set to "" by default.
+#			Set it to flags to use (ex.: "-d 1 --logfile").
+#
+# DO NOT CHANGE THESE DEFAULT VALUES HERE
+
+tincd_enable=${tincd_enable:-"NO"}
+
+. /etc/rc.subr
+
+name="tincd"
+rcvar="tincd_enable"
+command="/usr/local/sbin/tincd"
+start_cmd="tincd_start"
+stop_cmd="tincd_stop"
+reload_cmd="tincd_reload"
+extra_commands="reload"
+procname=${command:-tincd}
+ldconfig_command="/sbin/ldconfig"
+
+load_rc_config $name
+
+tincd_start()
+{
+	local setfib
+	setfib=/usr/sbin/setfib
+	${ldconfig_command} -elf -m /usr/local/lib
+	if test -z "${tincd_cfg}"
+	then
+		eval tincd_fib=\$${name}_fib
+		if [ -n "${tincd_fib}" ]
+		then
+			procname="${command}"
+			echo "Starting tincd"
+			$setfib -F ${tincd_fib} $command ${command_args}
+		else
+			echo "Starting tincd"
+			$command ${command_args}
+		fi
+	else
+		for cfg in ${tincd_cfg}
+		do
+			eval tincd_fib=\$${name}_${cfg}_fib
+			command_args="-n $cfg"
+			if [ -n "${tincd_fib}" ]
+			then
+				procname="${command}"
+				echo "Starting tincd"
+				$setfib -F ${tincd_fib} $command ${command_args}
+			else
+				echo "Starting tincd for: ${cfg}"
+				$command ${command_args}
+			fi
+		done
+	fi
+# code deliberately borrowed from /etc/rc.d/netif
+	if [ -f /etc/rc.d/ipfilter ] ; then
+		# Resync ipfilter
+		/etc/rc.d/ipfilter quietresync
+	fi
+}
+tincd_stop()
+{
+	if test -z "${tincd_cfg}"
+	then
+		echo "Stopping tincd"
+		$command -k
+	else
+		for cfg in $tincd_cfg
+		do
+			echo "Stopping tincd for: ${cfg}"
+			$command -n $cfg -k
+		done
+	fi
+}
+tincd_reload()
+{
+	if test -z "${tincd_cfg}"
+	then
+		echo "Sending HUP to tincd"
+		$command --kill=HUP
+	else
+		for cfg in $tincd_cfg
+		do
+			echo "Sending HUP to tincd for: ${cfg}"
+			$command -n $cfg --kill=HUP
+		done
+	fi
+}
+
+run_rc_command "$1"
+# eof

+ 7 - 0
Technik/Routing/Labornetz/etc/ansible/roles/tinc/tasks/host.yaml

@@ -0,0 +1,7 @@
+---
+- name: Tinc host file generation
+  template:
+    src: host.j2
+    dest: "{{ _destdir }}/{{ _tinc_host_name }}"
+    mode: 0640
+  delegate_to: localhost

+ 11 - 0
Technik/Routing/Labornetz/etc/ansible/roles/tinc/tasks/install-directory.yaml

@@ -0,0 +1,11 @@
+---
+- name: Install create installation directory (but not system dirs)
+  file:
+    path: "{{ _dir | replace('staging/' + inventory_hostname, '', 1) }}"
+    state: directory
+    recurse: no
+    mode: "{{ _mode }}"
+    #owner: "{{ _tinc_owner }}"
+    #group: "{{ _tinc_group }}"
+  when: _dir | match('^staging/' + inventory_hostname + os_dir_etc + '/.+$')
+  become: yes

+ 34 - 0
Technik/Routing/Labornetz/etc/ansible/roles/tinc/tasks/install.yaml

@@ -0,0 +1,34 @@
+---
+# Tinc install from staging area
+
+- name: Install find directories in staging area
+  find:
+    paths: [ "staging/{{ inventory_hostname }}" ]
+    file_type: directory 
+    recurse: yes
+  register: staging_directories
+  delegate_to: localhost
+
+- include: install-directory.yaml
+  vars:
+    _dir: "{{ item.path }}"
+    _mode: "{{ item.mode }}"
+  with_items: "{{ staging_directories.files | list }}"
+
+- name: Install find files in staging area
+  find:
+    paths: [ "staging/{{ inventory_hostname }}" ]
+    file_type: file 
+    recurse: yes
+  register: staging_files
+  delegate_to: localhost
+
+- name: Install copy files
+  copy:
+    src: "{{ item.path }}"
+    dest: "{{ item.path | replace('staging/' + inventory_hostname, '', 1) }}"
+    mode: "{{ item.mode }}"
+    #owner: "{{ _tinc_owner }}"
+    #group: "{{ _tinc_group }}"
+  with_items: "{{ staging_files.files | list }}"
+  become: yes

+ 13 - 0
Technik/Routing/Labornetz/etc/ansible/roles/tinc/tasks/keypair.yaml

@@ -0,0 +1,13 @@
+---
+- name: Tinc key generation
+  command: "{{ tincd }} -c '{{ _destdir }}' -o name={{ tinc_hostname }} --generate-keys=4096"
+  args:
+    creates: "{{ _destdir }}/{{ tinc_hostname }}.priv"
+  delegate_to: localhost
+
+- name: Tinc rename private key
+  command: "mv '{{ _destdir }}/rsa_key.priv' '{{ _destdir }}/{{ tinc_hostname }}.priv'"
+  args:
+    removes: "{{ _destdir }}/rsa_key.priv"
+    creates: "{{ _destdir }}/{{ tinc_hostname }}.priv"
+  delegate_to: localhost

+ 13 - 0
Technik/Routing/Labornetz/etc/ansible/roles/tinc/tasks/main.yaml

@@ -0,0 +1,13 @@
+---
+- name: Tinc include instance variables
+  include_vars: "{{ rolevarsdir_tinc }}/{{ _varsfile }}"
+  when: _phase == 'stage'
+
+- include: stage.yaml
+  when: _phase == 'stage'
+
+- include: package.yaml
+  when: _phase == 'install'
+
+- include: install.yaml
+  when: _phase == 'install'

+ 5 - 0
Technik/Routing/Labornetz/etc/ansible/roles/tinc/tasks/package.yaml

@@ -0,0 +1,5 @@
+---
+- name: Tinc package
+  pkgng: name=tinc state=present
+  become: yes
+  when: os_name == "FreeBSD"

+ 21 - 0
Technik/Routing/Labornetz/etc/ansible/roles/tinc/tasks/rc-freebsd.yaml

@@ -0,0 +1,21 @@
+---
+- name: Tinc rc.d script (FreeBSD)
+  copy:
+    src: rc.d-tincd
+    dest: "{{ _rcddir }}/tincd"
+    mode: 0755
+  delegate_to: localhost
+
+- name: Tinc rc.conf.d global file (FreeBSD)
+  template:
+    src: rc.conf-global.j2
+    dest: "{{ _rcconfdir }}/COMMON"
+    mode: 0644
+  delegate_to: localhost
+
+- name: Tinc rc.conf.d instance file (FreeBSD)
+  template:
+    src: rc.conf-instance.j2
+    dest: "{{ _rcconfdir }}/{{ tinc_name }}"
+    mode: 0644
+  delegate_to: localhost

+ 101 - 0
Technik/Routing/Labornetz/etc/ansible/roles/tinc/tasks/stage.yaml

@@ -0,0 +1,101 @@
+---
+- name: Tinc secret directory
+  file:
+    path: "{{ secretdir_tinc }}/{{ tinc_name }}"
+    state: directory
+    mode: 0700
+  delegate_to: localhost
+
+- name: Tinc secret directory / hosts subdirectory
+  file:
+    path: "{{ secretdir_tinc }}/{{ tinc_name }}/hosts"
+    state: directory
+    mode: 0700
+  delegate_to: localhost
+
+- include: keypair.yaml
+  vars:
+    _destdir: "{{ secretdir_tinc }}/{{ tinc_name }}"
+
+- name: Tinc work directory
+  file:
+    path: "{{ workdir_tinc }}/{{ tinc_name }}"
+    state: directory
+    mode: 0750
+  delegate_to: localhost
+
+- name: Tinc work directory / hosts subdirectory
+  file:
+    path: "{{ workdir_tinc }}/{{ tinc_name }}/hosts"
+    state: directory
+    mode: 0750
+  delegate_to: localhost
+
+- include: host.yaml
+  vars:
+    _tinc_host_name: "{{ item['tinc_hostname'] }}"
+    _tinc_host_addresses: "{{ item['tinc_addresses'] | default([]) }}"
+    _destdir: "{{ workdir_tinc }}/{{ tinc_name }}/hosts"
+    _key: "{{ lookup('file', secretdir_tinc + '/' + tinc_name + '/hosts/' + _tinc_host_name) }}"
+  with_items: "{{ tinc_hosts }}"
+
+- name: Tinc create staging directory
+  file:
+    path: "{{ stagedir }}/{{ inventory_hostname }}{{ basedir_conf_tinc }}/{{ tinc_name }}"
+    state: directory
+    mode: 0750
+  delegate_to: localhost
+
+- include: tinc-conf.yaml
+  vars:
+    _destdir: "{{ stagedir }}/{{ inventory_hostname }}{{ basedir_conf_tinc }}/{{ tinc_name }}"
+    _connecthosts: "{{ tinc_hosts | selectattr('tinc_addresses', 'defined') | map(attribute='tinc_hostname') | list }}"
+
+- include: tinc-up.yaml
+  vars:
+    _destdir: "{{ stagedir }}/{{ inventory_hostname }}{{ basedir_conf_tinc }}/{{ tinc_name }}"
+    _hostnumber: "{{ tinc_hosts | selectattr('tinc_hostname', 'equalto', tinc_hostname) | map(attribute='tinc_hostnumber') | first }}"
+
+- name: Tinc stage hosts directory
+  copy:
+    src: "{{ workdir_tinc }}/{{ tinc_name }}/hosts"
+    dest: "{{ stagedir }}/{{ inventory_hostname }}{{ basedir_conf_tinc }}/{{ tinc_name }}"
+    mode: 0640
+    directory_mode: 0750
+  delegate_to: localhost
+ 
+- name: Tinc stage private key
+  copy:
+    src: "{{ secretdir_tinc }}/{{ tinc_name }}/{{ tinc_hostname }}.priv"
+    dest: "{{ stagedir }}/{{ inventory_hostname }}{{ basedir_conf_tinc }}/{{ tinc_name }}/rsa_key.priv"
+    mode: 0600
+  delegate_to: localhost
+
+- name: Tinc rc.d directory (FreeBSD)
+  file:
+    path: "{{ stagedir }}/{{ inventory_hostname }}{{ os_dir_etc }}/rc.d"
+    state: directory
+    mode: 0755
+  delegate_to: localhost
+
+- name: Tinc rc.conf.d directory (FreeBSD)
+  file:
+    path: "{{ stagedir }}/{{ inventory_hostname }}{{ os_dir_etc }}/rc.conf.d"
+    state: directory
+    mode: 0755
+  delegate_to: localhost
+
+- name: Tinc rc.conf.d/tincd directory (FreeBSD)
+  file:
+    path: "{{ stagedir }}/{{ inventory_hostname }}{{ os_dir_etc }}/rc.conf.d/tincd"
+    state: directory
+    mode: 0755
+  delegate_to: localhost
+
+- include: rc-freebsd.yaml
+  vars:
+    _rcddir: "{{ stagedir }}/{{ inventory_hostname }}{{ os_dir_etc }}/rc.d"
+    _rcconfdir: "{{ stagedir }}/{{ inventory_hostname }}{{ os_dir_etc }}/rc.conf.d/tincd"
+    _tinc_fib: "{{ tinc_hosts | selectattr('tinc_hostname', 'equalto', tinc_hostname) | map(attribute='tinc_fib') | first | default(omit) }}"
+  when: tinc_name is defined
+

+ 7 - 0
Technik/Routing/Labornetz/etc/ansible/roles/tinc/tasks/tinc-conf.yaml

@@ -0,0 +1,7 @@
+---
+- name: Tinc tinc.conf
+  template:
+    src: "tinc.conf.j2"
+    dest: "{{ _destdir }}/tinc.conf"
+    mode: 0640 
+  delegate_to: localhost

+ 7 - 0
Technik/Routing/Labornetz/etc/ansible/roles/tinc/tasks/tinc-up.yaml

@@ -0,0 +1,7 @@
+---
+- name: Tinc tinc-up
+  template:
+    src: "tinc-up.j2"
+    dest: "{{ _destdir }}/tinc-up"
+    mode: 0750
+  delegate_to: localhost

+ 5 - 0
Technik/Routing/Labornetz/etc/ansible/roles/tinc/templates/host.j2

@@ -0,0 +1,5 @@
+# {{ ansible_managed }}
+{% if _tinc_host_addresses is defined %}{% for _tinc_address in _tinc_host_addresses %}
+Address = {{ _tinc_address }}{{ "" if " " in _tinc_address else " %s" % tinc_port }}
+{% endfor %}{% endif %}
+{{ _key }}

+ 3 - 0
Technik/Routing/Labornetz/etc/ansible/roles/tinc/templates/rc.conf-global.j2

@@ -0,0 +1,3 @@
+# {{ ansible_managed }}
+# global tinc settings
+tincd_enable=YES

+ 6 - 0
Technik/Routing/Labornetz/etc/ansible/roles/tinc/templates/rc.conf-instance.j2

@@ -0,0 +1,6 @@
+# {{ ansible_managed }}
+# settings for instance {{ tinc_name }}
+tincd_cfg="${tincd_cfg} {{ tinc_name }}"
+{% if _tinc_fib is defined %}
+tincd_{{ tinc_name }}_fib={{ _tinc_fib }}
+{% endif %}

+ 24 - 0
Technik/Routing/Labornetz/etc/ansible/roles/tinc/templates/tinc-up.j2

@@ -0,0 +1,24 @@
+#!/bin/sh
+
+# {{ ansible_managed }}
+
+OS=`uname`
+
+{% if tinc_vpn_ipv4_net is defined %}
+IPv4_HOSTPREFIX={{ tinc_vpn_ipv4_net | ipv4(_hostnumber) }}
+{% endif %}
+{% if tinc_vpn_ipv6_net is defined %}
+IPv6_HOSTPREFIX={{ tinc_vpn_ipv6_net | ipv6(_hostnumber) }}
+{% endif %}
+
+case $OS in
+	FreeBSD)
+		[ -z "$IPv4_HOSTPREFIX" ] || ifconfig $INTERFACE $IPv4_HOSTPREFIX
+		[ -z "$IPv6_HOSTPREFIX" ] || ifconfig $INTERFACE inet6 $IPv6_HOSTPREFIX
+		;;
+	Linux)
+		ip link set $INTERFACE up
+		[ -z "$IPv4_HOSTPREFIX" ] || ip addr add $IPv4_HOSTPREFIX dev $INTERFACE
+		[ -z "$IPv6_HOSTPREFIX" ] || ip -6 addr add $IPv6_HOSTPREFIX dev $INTERFACE
+		;;
+esac

+ 27 - 0
Technik/Routing/Labornetz/etc/ansible/roles/tinc/templates/tinc.conf.j2

@@ -0,0 +1,27 @@
+# {{ ansible_managed }}
+Name = {{ tinc_hostname }}
+{% if (tinc_device_tap is defined) and (os_name == "FreeBSD") %}
+Device = {{ tinc_device_tap }}
+{% endif %}
+Mode = switch
+{% if tinc_af is defined %}
+AddressFamily = {{ tinc_af }}
+{% endif %}
+{% if tinc_port is defined %}
+Port = {{ tinc_port }}
+{% endif %}
+{% if tinc_bindtoaddresses is defined %}{% for _bindtoaddress in tinc_bindtoaddresses %}
+BindToAddress = {{ _bindtoaddress }}
+{% endfor %}{% endif %}
+{% if tinc_maxtimeout is defined %}
+MaxTimeout = {{ tinc_maxtimeout }}
+{% endif %}
+{% if tinc_pingtimeout is defined %}
+PingTimeout = {{ tinc_pingtimeout }}
+{% endif %}
+GraphDumpFile = /var/run/tinc.{{ tinc_name }}.dot
+{% if _connecthosts is defined %}{% for _connecthost in _connecthosts %}
+{% if _connecthost != tinc_hostname %}
+ConnectTo = {{ _connecthost }}
+{% endif %}
+{% endfor %}{% endif %}