· ansible tinc devops

Tinc VPN - setting up a mesh network

Have you ever wanted to connect up your home network, your personal servers, your laptop, and maybe some virtual machines running inside your laptop? I’ve always used OpenVPN for production networks, however, tinc is extremely convenient. It sets up a mesh between all of the members of the network. Instead of re-routing all traffic through a central server, this node to node connection decreases the latency. Tinc’s configuration is a bit painful though, so here comes a post about ansible…again.

The role is available on github at: https://github.com/tjheeta/ansible-tinc-role

To get a tunnel setup inside a container, you’ll have to add the /dev/net device. Also, it may need to be run in privileged mode.

mkdir /dev/net
mknod /dev/net/tun c 10 200
chmod 0666 /dev/net/tun

I’ve setup an ansible playbook that uses the static binary compiled against musl for x86_64 from my slashpackage post . It is compiled against libressl and musl and comes out to be 1.5 meg and works over all distributions. Kind of handy if you have a bunch of heterogeneous machines.

Now for something here that you can do with ansible that you can’t do with any other configuration management. Since all the inventory management is done locally, we can pre-assign all the ipaddresses for all the servers. This means no race-conditions with chef search, no manually setting ip’s in configuration files, and all the other rigamarole that goes with this. On top of that, it will setup hosts file entries for each of the nodes that you specify. In the role, it runs a script called setup.py which looks for the hosts and assigns them ip addresses. This is done by judacious use of delegate_to:

# Fetch the ip addresses and keys from the hosts
- fetch: src=/etc/tinc/{{ tinc_netname }}/ansible_ipaddress dest={{ tinc_tmpdir }}/{{ tinc_netname }}/ip/{{ ansible_hostname }} flat=yes
  ignore_errors: yes
- fetch: src=/etc/tinc/{{ tinc_netname }}/rsa_key.pub dest={{ tinc_tmpdir }}/{{ tinc_netname }}/pubkeys/{{ ansible_hostname }} flat=yes
  ignore_errors: yes

# Set an ipaddress for each host in set if they don't have already
- script: setip.py {{ tinc_tmpdir }}/{{ tinc_netname }}/pubkeys {{ tinc_tmpdir }}/{{ tinc_netname }}/ip {{ tinc_subnet }}
  tags: test
  register: ip_output
  delegate_to: localhost

- template: src=host_configuration.j2 dest="{{ tinc_tmpdir }}/{{ tinc_netname }}/current/{{ ansible_hostname }}"
  tags: test
  delegate_to: localhost

For instance, let’s say you want to install it on a few hosts, and in your ansible hosts file you have a single public host, let’s call it publichost. Here’s a sample playbook. Runit is required, you can either install the package or use the runit role.

---
- name: Setup tinc
  hosts: tinc_hosts
  sudo: true
  gather_facts: true
  vars: 
    tinc_netname: mesh
    tinc_connectto:
      publichost1: 1.2.3.4
      publichost2: 1.2.3.5
    tinc_subnet: 10.11.0.0/24
    tinc_port: 2005
    tinc_state: present
    tinc_static_binary: true
  roles:
    - tinc

tl;dr - tinc sets up a mesh vpn, binary works on all x86_64 distros, ansible assigns all ip addresses

  • LinkedIn
  • Tumblr
  • Reddit
  • Google+
  • Pinterest
  • Pocket