Blog

Installing PEERVPN w/ ANSIBLЕ

Picture of ITGix Team
ITGix Team
Passionate DevOps & Cloud Engineers
10.01.2018
Reading time: 5 mins.
Last Updated: 08.01.2024

Table of Contents

What is Ansible?

In addition to the article about the PeerVPN installation and configuration, I will now show you a more advanced and quite ‘modern’ way to provision several servers and get your VPN client up really fast. You’ve probably heard of Ansible already. Well, one of its use cases is exactly what we need here: Configuration Manager. Many of us have experienced The Headache when we need to install, configure and then administer a whole environment. Yes, to repeat the same steps on hundreds of servers, where you have different OS distributions, application versions, and all kinds of dependencies, and all of that certainly leads to some problems.

Learn about Ansible

Read our comprehensive beginner guide on Ansible and learn all the basics!

Well, Ansible is here to help you with all that stuff. You can choose, set and customize anything that is required for a specific environment and suit its needs. So, let us start with an introduction to Ansible, its structure, and its components.
In my opinion, there are two approaches when you first start with Ansible. The first one is to read the official introduction to Ansible, which explains a lot about its structure, and then start with a simple playbook which you then extend to a role. Or the second one, where you make use of the Ansible Galaxy, which has a lot of community-provided roles open for use. Well, not every role is that much scalable and flexible as you want so you can simply combine both approaches, take an already-built role, and expand its functionalities. If you learn that quickly and all of that is boring, you can start building your own Ansible modules.

Now, let’s have a look at my PeerVPN role.

The directory structure:

 roles/
    PeerVPN/                       # this hierarchy represents a "role"
        tasks/                         #
            main.yml                 # <-- the main. yml file task file includes install.yml + configure.yml
            install.yml                #
            configure.yml          #
        templates/                
   # <-- files for use with the template resource

            peervpn.service.j2  # <---templates end in .j2, moved in a certain location
            peervpn.conf.j2       #
        defaults/                      #
            main.yml                 # <-- default lower priority variables for this

Tasks/main.yml:

- include: install.yml
- include: configure.yml
- service: name=peervpn state=started

Tasks/install.yml (NOTE the blankspaces at the start of the line):

- name: install dependencies
  yum:
    name: "{{ item }}"
    state: latest
  with_items:
    - gcc
    - openssl-devel
    - openssl 
    - python-urllib3
    - pyOpenSSL
  when: ansible_os_family == "RedHat"
- name: downloading PeerVPN
  unarchive: src=https://www.peervpn.net/files/peervpn-0-044-linux-x86.tar.gz dest=/tmp/ remote_src=yes
- name: moving extracted files [binary + config]
  command: /usr/bin/mv /tmp/peervpn-0-044/peervpn /usr/sbin/peervpn
  when: ansible_os_family == "RedHat"

Tasks/configure.yml (NOTE the blankspaces at the start of the line):

- name: create configuration directory
  file:
    path: /etc/peervpn
    state: directory
- name: write the peervpn config file
  template: src=../templates/peervpn.conf.j2 dest=/etc/peervpn/peervpn.conf
- name: create peervpn service
  template: src=../templates/peervpn.service.j2 dest=/usr/lib/systemd/system/peervpn.service
  when: ansible_os_family == "RedHat"

Templates/peervpn.service.j2:

[Unit]
Description={{ unit_description }}
{% if vpn_initpeers -%}
Requires={{ unit_requires }}
{% endif -%}
After={{ unit_after }}
ConditionPathExists={{ unit_condition_path }}
[Service]
Type={{ service_type }}
ExecStart={{ service_exec }}
PIDFile={{ service_pidfile }}
[Install]
WantedBy={{ install_wantedby }}

Templates/peervpn.conf.j2:

port {{ peervpn_port }}
networkname {{ peervpn_networkname }}
psk {{ peervpn_password }}
enabletunneling {{ peevpn_enabletunneling }}
interface {{ peervpn_interface }}
ifconfig4 {{ peervpn_ip }}
{% if vpn_initpeers -%}
initpeers {{ vpn_initpeers }}
{% endif -%} 

Defaults/main.yml:

peervpn_port: 7000
peervpn_networkname: MyPeerVPN
peervpn_password: VqmWsJje18/qqIOEN2+pLHugDtAcN5So03J0TL9wIQomAkQwcNR23SzM+m7cuJyCeyXXuHDLoKbzVbk176eDVLPS8wLNoWSiwPF2yQn57Q4vjRz3qjI51nhE3yEyKmHZgotQga4Uz0vyvTGjJRxtPJqZ/igDN0YmI25nwhsYsyi34c6pIcqPCOHYlILndCUh8AYk3hGNPc0lSnkxW/sY+Uo+5BU0K6nB1LYcMlXA9Ij0deU+eyRTfoVggKnpXdl5FikrELbAOyoo71F0PEjL73k5fmyGmsoEE1f4yvgUXOKOzsPUaf567SP4Hm+h/EpqkWMR7JGc5jBDsOlY52LTp5XaZNn+l+VEInCsFQiKgTW3zvzSmUcrPB3GqQ1KXknwfHmtCJe4SRiRZLKtSeTiPdPvXC0HBMk+KK9TNk45dDUi3/ougCIwavMPEedH7Gh5fvG5iNXjZ24tAAOTle2oBHVgO2Wq7llh2VwKkrzyYATuchusVLbHa98D0YR2wA==
peevpn_enabletunneling: "yes"
peervpn_interface: pvpn0
peervpn_ip: 0.0.0.0
vpn_initpeers: false
unit_description: PeerVPN
unit_requires: network.target
unit_after: syslog.target network.target
unit_condition_path: /etc/peervpn/peervpn.conf
service_type: simple
service_exec: /usr/sbin/peervpn {{ unit_condition_path }}
service_pidfile: /var/run/peervpn/peervpn.pid
install_wantedby: multi-user.target

So, now we have the role. The only thing left is the playbook and the inventory file. In fact the inventory file can be skipped(you can parse the hosts as arguments when you run the command) or your target hosts can be placed in the default Ansible inventory file in /etc/ansible/hosts. Here is an example playbook, which is provisioning 2 hosts:

playbook.yml:

- name: Configuring and installing PeerVPN init peer
  hosts: VPN_init_peer 
  remote_user: root
  vars:
    peervpn_ip: 10.1.0.1/24
  roles:
    - PeerVPN
- name: Configuring and installing PeerVPN other peers
  hosts: Host_1
  remote_user: root
  vars:
    peervpn_ip: 10.1.0.2/24
    vpn_initpeers: "{{ groups.VPN_init_peer[0] }} {{ peervpn_port }}"
  roles:
    - PeerVPN

 Note that I am using an inventory file for keeping the hosts:

Inventory.yml:

[VPN_init_peer]
165.165.165.165
[Host_1]
170.170.170.170
To provision more hosts you need to simply add [Host_<2/3/4..etc>] and an IP in your inventory file and add accordingly paragraph(s) to the playbook file, with different peervpn_ip and hosts.
To run the above example, you need to have your public keys distributed on the target hosts because Ansible works over SSH by default. Now simply execute the following command in the dir where your playbook is: 
$ ansible-playbook playbook.yml -i inventory.yml

Leave a Reply

Your email address will not be published. Required fields are marked *

More Posts

Why etcd Backups are Critical In modern distributed systems, etcd plays a crucial role as a reliable and fast key-value store that serves as the backbone for storing critical configuration...
Reading
Learn effective strategies for Amazon S3 migration and explore advanced tools like Storage Lens, Athena, and QuickSight to gain actionable insights into your big data usage. Perfect for organizations optimizing...
Reading
Get In Touch
ITGix provides you with expert consultancy and tailored DevOps services to accelerate your business growth.
Newsletter for
Tech Experts
Join 12,000+ business leaders and engineers who receive blogs, e-Books, and case studies on emerging technology.