Purpose:The itertools module includes a set of functions for working with iterable (sequence-like) data sets.

Iteration Helpers: itertools

Iteration is a big part of the flow of Python and aside from the builtin syntax, there are some handy tools in the itertools package to make things easier. They also tend to make things run faster.

14.4.1. CHAIN()

The chain()method accepts an arbitrary number of iterable objects as arguments and returns an iterator that will iterate over each iterable in turn. Once the first is exhausted, it will move onto the next.
Without the chain() function, iterating over two lists would require creating a copy with the contents of both or adding the contents of one to the other.
>>> l1 = ['a', 'b', 'c']
>>> l2 = ['d', 'e', 'f']
>>> l1.extend(l2)
>>> l1
['a', 'b', 'c', 'd', 'e', 'f']
It?s much more efficient to use the chain() function which only allocates additional storage for some housekeeping data in the iterator itself.
>>> import itertools
>>> l1 = ['a', 'b', 'c']
>>> l2 = ['d', 'e', 'f']

>>> chained = itertools.chain(l1, l2)
>>> chained
<itertools.chain object at 0x100431250>

>>> [l for l in chained]
['a', 'b', 'c', 'd', 'e', 'f']

14.4.2. IZIP()

izip() is almost identical to the zip() builtin, in that it pairs up the contents of two lists into an iterable of 2-tuples. However, where zip() allocates a new list, izip() only returns an iterator.
>>> name = ['Jimmy', 'Robert', 'John Paul', 'John']
>>> instruments = ['Guitar', 'Vocals', 'Bass', 'Drums']

>>> zepp = zip(name, instruments)
>>> zepp
[('Jimmy', 'Guitar'), ('Robert', 'Vocals'), ('John Paul', 'Bass'), ('John', 'Drums')]

>>> zepp = itertools.izip(name, instruments)
>>> zepp
<itertools.izip object at 0x100430998>

>>> [musician for musician in zepp]
[('Jimmy', 'Guitar'), ('Robert', 'Vocals'), ('John Paul', 'Bass'), ('John', 'Drums')]


More

The functions provided are inspired by similar features of the “lazy functional programming language” Haskell and SML. They are intended to be fast and use memory efficiently, but also to be hooked together to express more complicated iteration-based algorithms.
Iterator-based code may be preferred over code which uses lists for several reasons. Since data is not produced from the iterator until it is needed, all of the data is not stored in memory at the same time. Reducing memory usage can reduce swapping and other side-effects of large data sets, increasing performance.

Merging and Splitting Iterators

The chain() function takes several iterators as arguments and returns a single iterator that produces the contents of all of them as though they came from a single sequence.
from itertools import *

for i in chain([1, 2, 3], ['a', 'b', 'c']):
    print i
$ python itertools_chain.py

1
2
3
a
b
c
izip() returns an iterator that combines the elements of several iterators into tuples. It works like the built-in function zip(), except that it returns an iterator instead of a list.
from itertools import *

for i in izip([1, 2, 3], ['a', 'b', 'c']):
    print i
$ python itertools_izip.py

(1, 'a')
(2, 'b')
(3, 'c')
The islice() function returns an iterator which returns selected items from the input iterator, by index. It takes the same arguments as the slice operator for lists: start, stop, and step. The start and step arguments are optional.
from itertools import *

print 'Stop at 5:'
for i in islice(count(), 5):
    print i

print 'Start at 5, Stop at 10:'
for i in islice(count(), 5, 10):
    print i

print 'By tens to 100:'
for i in islice(count(), 0, 100, 10):
    print i
$ python itertools_islice.py

Stop at 5:
0
1
2
3
4
Start at 5, Stop at 10:
5
6
7
8
9
By tens to 100:
0
10
20
30
40
50
60
70
80
90
The tee() function returns several independent iterators (defaults to 2) based on a single original input. It has semantics similar to the Unix tee utility, which repeats the values it reads from its input and writes them to a named file and standard output.
from itertools import *

r = islice(count(), 5)
i1, i2 = tee(r)

for i in i1:
    print 'i1:', i
for i in i2:
    print 'i2:', i
$ python itertools_tee.py

i1: 0
i1: 1
i1: 2
i1: 3
i1: 4
i2: 0
i2: 1
i2: 2
i2: 3
i2: 4
Since the new iterators created by tee() share the input, you should not use the original iterator any more. If you do consume values from the original input, the new iterators will not produce those values:
from itertools import *

r = islice(count(), 5)
i1, i2 = tee(r)

for i in r:
    print 'r:', i
    if i > 1:
        break

for i in i1:
    print 'i1:', i
for i in i2:
    print 'i2:', i
$ python itertools_tee_error.py

r: 0
r: 1
r: 2
i1: 3
i1: 4
i2: 3
i2: 4

Converting Inputs

The imap() function returns an iterator that calls a function on the values in the input iterators, and returns the results. It works like the built-in map(), except that it stops when any input iterator is exhausted (instead of inserting None values to completely consume all of the inputs).
In the first example, the lambda function multiplies the input values by 2. In a second example, the lambda function multiplies 2 arguments, taken from separate iterators, and returns a tuple with the original arguments and the computed value.
from itertools import *

print 'Doubles:'
for i in imap(lambda x:2*x, xrange(5)):
    print i

print 'Multiples:'
for i in imap(lambda x,y:(x, y, x*y), xrange(5), xrange(5,10)):
    print '%d * %d = %d' % i
$ python itertools_imap.py

Doubles:
0
2
4
6
8
Multiples:
0 * 5 = 0
1 * 6 = 6
2 * 7 = 14
3 * 8 = 24
4 * 9 = 36
The starmap() function is similar to imap(), but instead of constructing a tuple from multiple iterators it splits up the items in a single iterator as arguments to the mapping function using the *syntax. Where the mapping function to imap() is called f(i1, i2), the mapping function to starmap() is called f(*i).
from itertools import *

values = [(0, 5), (1, 6), (2, 7), (3, 8), (4, 9)]
for i in starmap(lambda x,y:(x, y, x*y), values):
    print '%d * %d = %d' % i
$ python itertools_starmap.py

0 * 5 = 0
1 * 6 = 6
2 * 7 = 14
3 * 8 = 24
4 * 9 = 36

Producing New Values

The count() function returns an interator that produces consecutive integers, indefinitely. The first number can be passed as an argument, the default is zero. There is no upper bound argument (see the built-in xrange() for more control over the result set). In this example, the iteration stops because the list argument is consumed.
from itertools import *

for i in izip(count(1), ['a', 'b', 'c']):
    print i
$ python itertools_count.py

(1, 'a')
(2, 'b')
(3, 'c')
The cycle() function returns an iterator that repeats the contents of the arguments it is given indefinitely. Since it has to remember the entire contents of the input iterator, it may consume quite a bit of memory if the iterator is long. In this example, a counter variable is used to break out of the loop after a few cycles.
from itertools import *

i = 0
for item in cycle(['a', 'b', 'c']):
    i += 1
    if i == 10:
        break
    print (i, item)
$ python itertools_cycle.py

(1, 'a')
(2, 'b')
(3, 'c')
(4, 'a')
(5, 'b')
(6, 'c')
(7, 'a')
(8, 'b')
(9, 'c')
The repeat() function returns an iterator that produces the same value each time it is accessed. It keeps going forever, unless the optional times argument is provided to limit it.
from itertools import *

for i in repeat('over-and-over', 5):
    print i
$ python itertools_repeat.py

over-and-over
over-and-over
over-and-over
over-and-over
over-and-over
It is useful to combine repeat() with izip() or imap() when invariant values need to be included with the values from the other iterators.
from itertools import *

for i, s in izip(count(), repeat('over-and-over', 5)):
    print i, s
$ python itertools_repeat_izip.py

0 over-and-over
1 over-and-over
2 over-and-over
3 over-and-over
4 over-and-over
from itertools import *

for i in imap(lambda x,y:(x, y, x*y), repeat(2), xrange(5)):
    print '%d * %d = %d' % i
$ python itertools_repeat_imap.py

2 * 0 = 0
2 * 1 = 2
2 * 2 = 4
2 * 3 = 6
2 * 4 = 8

Filtering

The dropwhile() function returns an iterator that returns elements of the input iterator after a condition becomes false for the first time. It does not filter every item of the input; after the condition is false the first time, all of the remaining items in the input are returned.
from itertools import *

def should_drop(x):
    print 'Testing:', x
    return (x<1)

for i in dropwhile(should_drop, [ -1, 0, 1, 2, 3, 4, 1, -2 ]):
    print 'Yielding:', i
$ python itertools_dropwhile.py

Testing: -1
Testing: 0
Testing: 1
Yielding: 1
Yielding: 2
Yielding: 3
Yielding: 4
Yielding: 1
Yielding: -2
The opposite of dropwhile()takewhile() returns an iterator that returns items from the input iterator as long as the test function returns true.
from itertools import *

def should_take(x):
    print 'Testing:', x
    return (x<2)

for i in takewhile(should_take, [ -1, 0, 1, 2, 3, 4, 1, -2 ]):
    print 'Yielding:', i
$ python itertools_takewhile.py

Testing: -1
Yielding: -1
Testing: 0
Yielding: 0
Testing: 1
Yielding: 1
Testing: 2
ifilter() returns an iterator that works like the built-in filter() does for lists, including only items for which the test function returns true. It is different from dropwhile() in that every item is tested before it is returned.
from itertools import *

def check_item(x):
    print 'Testing:', x
    return (x<1)

for i in ifilter(check_item, [ -1, 0, 1, 2, 3, 4, 1, -2 ]):
    print 'Yielding:', i
$ python itertools_ifilter.py

Testing: -1
Yielding: -1
Testing: 0
Yielding: 0
Testing: 1
Testing: 2
Testing: 3
Testing: 4
Testing: 1
Testing: -2
Yielding: -2
The opposite of ifilter()ifilterfalse() returns an iterator that includes only items where the test function returns false.
from itertools import *

def check_item(x):
    print 'Testing:', x
    return (x<1)

for i in ifilterfalse(check_item, [ -1, 0, 1, 2, 3, 4, 1, -2 ]):
    print 'Yielding:', i
$ python itertools_ifilterfalse.py

Testing: -1
Testing: 0
Testing: 1
Yielding: 1
Testing: 2
Yielding: 2
Testing: 3
Yielding: 3
Testing: 4
Yielding: 4
Testing: 1
Yielding: 1
Testing: -2

Grouping Data

The groupby() function returns an iterator that produces sets of values grouped by a common key.
This example from the standard library documentation shows how to group keys in a dictionary which have the same value:
from itertools import *
from operator import itemgetter

d = dict(a=1, b=2, c=1, d=2, e=1, f=2, g=3)
di = sorted(d.iteritems(), key=itemgetter(1))
for k, g in groupby(di, key=itemgetter(1)):
    print k, map(itemgetter(0), g)
$ python itertools_groupby.py

1 ['a', 'c', 'e']
2 ['b', 'd', 'f']
3 ['g']
This more complicated example illustrates grouping related values based on some attribute. Notice that the input sequence needs to be sorted on the key in order for the groupings to work out as expected.
from itertools import *

class Point:
    def __init__(self, x, y):
        self.x = x
        self.y = y
    def __repr__(self):
        return 'Point(%s, %s)' % (self.x, self.y)
    def __cmp__(self, other):
        return cmp((self.x, self.y), (other.x, other.y))

# Create a dataset of Point instances
data = list(imap(Point, 
                 cycle(islice(count(), 3)), 
                 islice(count(), 10),
                 )
            )
print 'Data:', data
print

# Try to group the unsorted data based on X values
print 'Grouped, unsorted:'
for k, g in groupby(data, lambda o:o.x):
    print k, list(g)
print

# Sort the data
data.sort()
print 'Sorted:', data
print

# Group the sorted data based on X values
print 'Grouped, sorted:'
for k, g in groupby(data, lambda o:o.x):
    print k, list(g)
print
$ python itertools_groupby_seq.py

Data: [Point(0, 0), Point(1, 1), Point(2, 2), Point(0, 3), Point(1, 4), Point(2, 5), Point(0, 6), Point(1, 7), Point(2, 8), Point(0, 9)]

Grouped, unsorted:
0 [Point(0, 0)]
1 [Point(1, 1)]
2 [Point(2, 2)]
0 [Point(0, 3)]
1 [Point(1, 4)]
2 [Point(2, 5)]
0 [Point(0, 6)]
1 [Point(1, 7)]
2 [Point(2, 8)]
0 [Point(0, 9)]

Sorted: [Point(0, 0), Point(0, 3), Point(0, 6), Point(0, 9), Point(1, 1), Point(1, 4), Point(1, 7), Point(2, 2), Point(2, 5), Point(2, 8)]

Grouped, sorted:
0 [Point(0, 0), Point(0, 3), Point(0, 6), Point(0, 9)]
1 [Point(1, 1), Point(1, 4), Point(1, 7)]
2 [Point(2, 2), Point(2, 5), Point(2, 8)]

Recently, I try to create a trie tree with python. My data has 3M+ different words, which ate 2G+ of my memory. It made me rather disappointed, so I searched online for solutions. And I found the greatest improvement is to using __slots__ property. It saves me 50% of the memory, so I think this a damn pitfall. Watch out, really, if you've not been familiar with it yet.

Example:

class Node(object):
    '''without __slots__
    '''

    ChildrenFactory = dict

    def __init__(self, value=NULL):
        self.value = value
        self.children = self.ChildrenFactory()


class Node(object):
    '''
    :ivar value: The value of the key corresponding to this node or :const:`NULL`
        if there is no such key.
    :ivar children: A ``{key-part : child-node}`` mapping.
    '''
    __slots__ = ('value', 'children')

    ChildrenFactory = dict

    def __init__(self, value=NULL):
        self.value = value
        self.children = self.ChildrenFactory()


So what is __slots__ doing here?

Quoting Jacob Hallen:
The proper use of __slots__ is to save space in objects. Instead of having a dynamic dict that allows adding attributes to objects at anytime, there is a static structure which does not allow additions after creation. This saves the overhead of one dict for every object that uses slots. While this is sometimes a useful optimization, it would be completely unnecessary if the Python interpreter was dynamic enough so that it would only require the dict when there actually were additions to the object.
Unfortunately there is a side effect to slots. They change the behavior of the objects that have slots in a way that can be abused by control freaks and static typing weenies. This is bad, because the control freaks should be abusing the metaclasses and the static typing weenies should be abusing decorators, since in Python, there should be only one obvious way of doing something.
Making CPython smart enough to handle saving space without __slots__ is a major undertaking, which is probably why it is not on the list of changes for P3k (yet).

How to set up shared folders in a Windows XP virtualbox guest (say ubuntu host)?

You have to install the Virtualbox Guest Addition (GA) to be able to share with the host if using Windows.
First create a folder to share in with the host. For example, create a folder called X in your Host's Desktop and before or after installing the Guest Addition right click on the guest os in your Virtualbox main window. Go to settings and look for the Shared Folder option.
Select it and choose the X folder you just made. Now boot the guest OS with the Guest Addition already installed (if you haven't installed it yet do so) and on the terminal type net use x: \\vboxsrv\x that is all. It should tell you that you are now sharing.

From https://www.digitalocean.com/community/tutorials/how-to-install-tinc-and-set-up-a-basic-vpn-on-ubuntu-14-04

Introduction

In this tutorial, we will go over how to use Tinc, an open source Virtual Private Network (VPN) daemon, to create a secure VPN that your servers can communicate on as if they were on a local network. We will also demonstrate how to use Tinc to set up a secure tunnel into a private network. We will be using Ubuntu 14.04 servers, but the configurations can be adapted for use with any other OS.
A few of the features that Tinc has that makes it useful include encryption, optional compression, automatic mesh routing (VPN traffic is routed directly between the communicating servers, if possible), and easy expansion. These features differentiate Tinc from other VPN solutions such as OpenVPN, and make it a good solution for creating a VPN out of many small networks that are geographically distributed. Tinc is supported on many operating systems, including Linux, Windows, and Mac OS X.

Prerequisites

To complete this tutorial, you will require root access on at least three Ubuntu 14.04 servers. Instructions to set up root access can be found here (steps 3 and 4): Initial Server Setup with Ubuntu 14.04.
If you are planning on using this in your own environment, you will have to plan out how your servers need to access each other, and adapt the examples presented in this tutorial to your own needs. If you are adapting this to your own setup, be sure to substitute the highlighted values in the examples with your own values.
If you would like to follow this tutorial exactly, create two VPSs in the same datacenter, with private networking, and create another VPS in a separate datacenter. We will create two VPSs in the NYC2 datacenter and one in AMS2 datacenter with the following names:
  • externalnyc: All of the VPN nodes will connect to this server, and the connection must be maintained for proper VPN functionality. Additional servers can be configured in a similarly to this one to provide redundancy, if desired.
  • internalnyc: Connects to externalnyc VPN node using its private network interface
  • ams1: Connects to externalnyc VPN node over the public Internet

Our Goal

Here is a diagram of the VPN that we want to set up (described in Prerequisites):
Tinc VPN Setup
The green represents our VPN, the gray represents the public Internet, and the orange represents the private network. All three servers can communicate on the VPN, even though the private network is inaccessible to ams1.
Let's get started by installing Tinc!

Install Tinc

On each VPS that you want to join the private network, install Tinc. Let's start by updating apt:
sudo apt-get update
Then install Tinc via apt:
sudo apt-get install tinc
Now that Tinc is installed, let's look at the Tinc configuration.

Tinc Configuration

Tinc uses a "netname" to distinguish one Tinc VPN from another (in case of multiple VPNs), and it is recommended to use a netname even if you are only planning on configuring one VPN. We will call our VPN "netname" for simplicity.
Every server that will be part of our VPN requires the following three configuration components:
  • Configuration files: tinc.conf, tinc-up, and tinc-down, for example
  • Public/private key pairs: For encryption and node authentication
  • Host configuration files: Which contain public keys and other VPN configuration
Let's start by configuring our externalnyc node.

Configure externalnyc

On externalnyc, create the configuration directory structure for our VPN called "netname":
sudo mkdir -p /etc/tinc/netname/hosts
Now open tinc.conf for editing:
sudo vi /etc/tinc/netname/tinc.conf
Now add the following lines:
Name = externalnyc
AddressFamily = ipv4
Interface = tun0
This simply configures a node called externalnyc, with a network interface that will use IPv4 called "tun0". Save and quit.
Next, let's create an externalnyc hosts configuration file:
sudo vi /etc/tinc/netname/hosts/externalnyc
Add the following lines to it (substitute the public IP address of your VPS here):
Address = externalnyc_public_IP
Subnet = 10.0.0.1/32
Ultimately, this file will be used on other servers to communicate with this server. The address specifies how other nodes will connect to this server, and the subnet specifies which subnet this daemon will serve. Save and quit.
Now generate the public/private keypair for this host with the following command:
sudo tincd -n netname -K4096
This creates the private key (/etc/tinc/netname/rsa_key.priv) and appends the public key to the externalnyc hosts configuration file that we recently created (/etc/tinc/netname/hosts/externalnyc).
Now we must create tinc-up, the script that will run whenever our netname VPN is started. Open the file for editing now:
sudo vi /etc/tinc/netname/tinc-up
Add the following lines:
#!/bin/sh
ifconfig $INTERFACE 10.0.0.1 netmask 255.255.255.0
When we start our VPN, this script will run to create the network interface that our VPN will use. On the VPN, this server will have an IP address of 10.0.0.1.
Let's also create a script to remove network interface when our VPN is stopped:
sudo vi /etc/tinc/netname/tinc-down
Add the following lines:
#!/bin/sh
ifconfig $INTERFACE down
Save and quit.
Lastly, make tinc network scripts executable:
sudo chmod 755 /etc/tinc/netname/tinc-*
Save and quit.
Let's move on to our other nodes.

Configure internalnyc and ams1

These steps are required on both internalnyc and ams1, with slight variations that will be noted.
On internalnyc and ams1, create the configuration directory structure for our VPN called "netname" and edit the Tinc configuration file:
sudo mkdir -p /etc/tinc/netname/hosts
sudo vi /etc/tinc/netname/tinc.conf
Add the following lines (substitute the name with the node name):
Name = node_name
AddressFamily = ipv4
Interface = tun0
ConnectTo = externalnyc
These nodes are configured to attempt to connect to "externalnyc" (the node we created prior to this). Save and quit.
Next, let's create the hosts configuration file:
sudo vi /etc/tinc/netname/hosts/node_name
For internalnyc, add this line:
Subnet = 10.0.0.2/32
For ams1, add this line:
Subnet = 10.0.0.3/32
Note that the numbers differ. Save and quit.
Next, generate the keypairs:
sudo tincd -n netname -K4096
And create the network interface start script:
sudo vi /etc/tinc/netname/tinc-up
For internalnyc, add this line:
ifconfig $INTERFACE 10.0.0.2 netmask 255.255.255.0
For ams1, add this line:
ifconfig $INTERFACE 10.0.0.3 netmask 255.255.255.0
These IP addresses are how these nodes will be accessed on the VPN. Save and quit.
Now create the network interface stop script:
sudo vi /etc/tinc/netname/tinc-down
And add this line:
ifconfig $INTERFACE down
Save and quit.
Lastly, make tinc network scripts executable:
sudo chmod 755 /etc/tinc/netname/tinc-*
Save and quit.
Now we must distribute the hosts configuration files to each node.

Distribute the Keys

If you happen to use a configuration management system, here is a good application. Minimally, each node that wants communicate directly with another node must have exchanged public keys, which are inside of the hosts configuration files. In our case, for example, only externalnyc needs to exchange public keys with the other nodes. It is easier to manage if you just copy each public key to all members of the node. Note that you will want to change the "Address" value in externalnyc's hosts configuration file to its private IP address when it is copied to internalnyc, so that connection is established over the private network.
Because our VPN is called "netname", here is the location of the hosts configuration files: /etc/tinc/netname/hosts

Exchange Keys Between externalnyc and internalnyc

On internalnyc, copy its hosts configuration file to externalnyc:
scp /etc/tinc/netname/hosts/internalnyc user@externalnyc_private_IP:/tmp
Then on externalnyc, copy the internalnyc's file into the appropriate location:
cd /etc/tinc/netname/hosts; sudo cp /tmp/internalnyc .
Then on externalnyc again, copy its hosts configuration file to internalnyc:
scp /etc/tinc/netname/hosts/externalnyc user@internalnyc_private_IP:/tmp
On internalnyc, copy externalnyc's file to the appropriate location:
cd /etc/tinc/netname/hosts; sudo cp /tmp/externalnyc .
On internalnyc, let's edit externalnyc's hosts configuration file so the "Address" field is set to externalnyc's private IP address (so internalnyc will connect to the VPN via the private network). Edit externalnyc's hosts configuration file:
sudo vi /etc/tinc/netname/hosts/externalnyc
Change the "Address" value to externalnyc's private IP address:
Address = externalnyc_private_IP
Save and quit. Now let's move on to our remaining node, ams1.

Exchange Keys Between externalnyc and ams1

On ams1, copy its hosts configuration file to externalnyc:
scp /etc/tinc/netname/hosts/ams1 user@externalnyc_public_IP:/tmp
Then on externalnyc, copy the ams1's file into the appropriate location:
cd /etc/tinc/netname/hosts; sudo cp /tmp/ams1 .
Then on externalnyc again, copy its hosts configuration file to ams1:
scp /etc/tinc/netname/hosts/externalnyc user@ams1_public_IP:/tmp
On ams1, copy externalnyc's file to the appropriate location:
cd /etc/tinc/netname/hosts; sudo cp /tmp/externalnyc .

Exchange Keys Between Additional Nodes

If you are creating a larger VPN, now is a good time to exchange the keys between those other nodes. Remember that if you want two nodes to directly communicate with each other (without a forwarding server between), they need to have exchanged their keys/hosts configuration files, and they need to be able to access each other's real network interfaces. Also, it is fine to just copy each hosts configuration to every node in the VPN.

Test Our Configuration

On each node, starting with externalnyc, start Tinc in debug mode like so (netname is the name of our VPN):
sudo tincd -n netname -D -d3
After starting the daemon on each node, you should see output with the names of each node as they connect to externalnyc. Now let's test the connection over the VPN.
In a separate window, on ams1, ping internalnyc's VPN IP address (which we assigned to 10.0.0.2, earlier):
ping 10.0.0.2
The ping should work fine, and you should see some debug output in the other windows about the connection on the VPN. This indicates that ams1 is able to communicate over the VPN through externalnyc to internalnyc. Press CTRL-C to quit pinging.
You may also use the VPN interfaces to do any other network communication, like application connections, copying files, and SSH.
On each Tinc daemon debug window, quit the daemon by pressing CTRL-\.
Note: If the connections aren't working, ensure that your firewall is not blocking the connections or forwarding.

Configure Tinc To Startup on Boot

Before the Tinc init script will function properly, we have to put our VPN's name into the nets.boot configuration file.
On each node, edit nets.boot:
sudo vi /etc/tinc/nets.boot
Add the name of your VPN(s) into this file. Ours is "netname":
# This file contains all names of the networks to be started on system startup.
netname
Save and quit. Tinc is now configured to start on boot, and it can be controlled via theservice command. If you would like to start it now run the following command on each of your nodes:
sudo service tinc start
Congrats! Your Tinc VPN is set up.

Conclusion

Now that you have gone through this tutorial, you should have a good foundation to build out your VPN to meet your needs. Tinc is very flexible, and any node can be configured to connect to any other node (that it can access over the network) so it can act as a mesh VPN, not relying on a single node.
Good luck!

Popular Posts