Configuring Tinc, an encrypted P2P VPN

What is tinc?

Tinc a is dead simple, yet super flexible, VPN daemon.

It also has some nice features, such as:

  • encryption
  • automatic mesh routing
  • compression
  • NAT traversal
  • IPv6 support

This article will demonstrate how to create a basic two-node VPN.

Topology cheatsheet

| | Node A | Node B |
| Public IPv4 | | |
| VPN Address | | |
| VPN Network Name | PsychoVPN | PsychoVPN |

Updating the OS

As always, start with refreshing your package list on both nodes.

apt update

…and preferably upgrade the packages

apt upgrade -y

Now you can go ahead and install tinc:

apt install tinc -y

Creating Configuration Files

Main Configuration File

Tinc requires a main configuration file named tinc.conf. The folder in which you put the tinc.conf file has to match the designated name of your VPN - in my case: /etc/tinc/PsychoVPN.

mkdir -p /etc/tinc/PsychoVPN/hosts && cd /etc/tinc/PsychoVPN

Tinc has a lot of configurable options:

  • Name - this is our node name within the network
  • Device - Determines the virtual network to use.
  • AddressFamily - indicates which type of address to use (ipv4|ipv6|any)
  • ConnectTo - Specifies which other tinc daemons to connect to on startup. Multiple ConnectTo variables may be specified, in which case, outgoing connections to each specified tinc daemon are made. The names should be known to this tinc daemon (i.e. there should be a host configuration file for the name on the ConnectTo line). This also gives the ability to create a centralized interconnection (make NodeA and NodeB connect only to NodeC and from there make NodeC connect to both servers). If you don’t specify a host with ConnectTo, tinc won’t try to connect to other daemons at all, and will instead just listen for incoming connections.
  • BindToAddress = [address] [port] - If your computer has more than one IPv4 or IPv6 address, tinc will by default listen on all of them for incoming connections. Multiple BindToAddress variables may be specified. If no port is specified, the socket will be bound to the port specified by the Port option, or to port 655 if neither is given. To only bind to a specific port but not to a specific address, use * for the address.
  • BindToInterface = [interface] - If your computer has more than one network interface, tinc will by default listen on all of them for incoming connections. It is possible to bind only to a single interface with this variable.
  • More options available here

Here is a simple main configuration for NodeA:

Node A: /etc/tinc/PsychoVPN/tinc.conf

Name = NodeA
Device = /dev/net/tun
AddressFamily = ipv4
ConnectTo = NodeB

…and here is for NodeB

Node B: /etc/tinc/PsychoVPN/tinc.conf

Name = NodeB
Device = /dev/net/tun
AddressFamily = ipv4
ConnectTo = NodeA

Host configuration files

Because tinc is a P2P VPN it needs to communicate with the other servers. A very basic host file looks like this and has to be named after the node name:

Address =
Subnet =

We also have to add the public key of a specific node to that file.

On Node A we are going to create a NodeA file under the ../hosts folder.

Node A: /etc/tinc/PsychoVPN/hosts/NodeA

Address =
Subnet =

…and similarly on Node B (../hosts/NodeB)

Node B: /etc/tinc/PsychoVPN/hosts/NodeB

Address =
Subnet =

Now we have to create a 4096-bit pair of keys on each node

tincd -n PsychoVPN -K 4096

Make sure to save both and rsa_key.priv to the root of your working directory (/etc/tinc/PsychoVPN)

Now we can append those public keys to the corresponding hosts files:

On Node A:

cat >> hosts/NodeA

On Node B:

cat >> hosts/NodeB

We should exchange the hosts files between the nodes. You can use scp for example:

From NodeA

scp /etc/tinc/PsychoVPN/hosts/NodeA <user>@<NodeB>:/etc/tinc/PsychoVPN/hosts/NodeA

From NodeB

scp /etc/tinc/PsychoVPN/hosts/NodeB <user>@<NodeA>:/etc/tinc/PsychoVPN/hosts/NodeB

Control Scripts

Control scripts are responsible for setting up virtual interfaces on each server. They’re needed on both servers.

Script for enabling tinc interface on Node A:

Node A: /etc/tinc/PsychoVPN/tinc-up

ip link set $INTERFACE up
ip addr add dev $INTERFACE
ip route add dev $INTERFACE

Script for disabling tinc interface on Node A:

Node A: /etc/tinc/PsychoVPN/tinc-down

ip route del dev $INTERFACE
ip addr del dev $INTERFACE
ip link set $INTERFACE down

…enabling tinc interface on Node B:

Node B: /etc/tinc/PsychoVPN/tinc-up

ip link set $INTERFACE up
ip addr add dev $INTERFACE
ip route add dev $INTERFACE

…disabling tinc interface on Node B:

Node B: /etc/tinc/PsychoVPN/tinc-down

ip route del dev $INTERFACE
ip addr del dev $INTERFACE
ip link set $INTERFACE down

After creating the control scripts, you have to adjust the permissions on both servers:

chmod -v +x /etc/tinc/PsychoVPN/tinc-{up,down}

Testing tinc

Your newly configured VPN should be ready to test. Start the daemon on both servers:

tincd -n PsychoVPN -LD -d3

Now you should be able to ping Node B from Node A and vice versa from new terminal window. You may notice that CTRL+C is not terminating tinc, instead, it’s elevating the debug level from 3 to 5. To stop tincd press CTRL+\. If you ran tincd in the background you can use the -k option to kill the running tincd.

Run tinc on startup

To run tinc on startup you will need to set up a systemd unit file on each node. An example systemd unit file is below.


Description=Tinc PsychoVPN Encrypted P2P Network

ExecStart=/usr/sbin/tincd -n PsychoVPN -LD -d2
ExecStop=/usr/sbin/tincd -n PsychoVPN -k


To enable the service automatically starting on system startup, run

sudo systemctl enable PsychoVPN.service

You can start and stop the service using

systemctl start|stop PsychoVPN.service

So you've read the whole article? How about signing up for more?

Email Address

No spam, I promise