Configuring and Monitoring a Tor Middle Relay

The Tor network relies upon individuals and organizations to donate relays for user traffic. The more relays within network, the stronger and faster the network is. Below, we will create a middle relay which receives traffic and sends it off to another relay. Middle relays will never serve as exit points for traffic back out to the clear Internet (a job for an exit relay). Because of this, many see running a middle relay as a safer way of contributing to the Tor network as opposed to running an exit relay which could find an operator at fault if illegal activity or content exits his node.

For this guide, we assume a Debian Stretch (or similar) Linux system with a non-root, sudo user. It is also assumed that the target machine has been set up with some standard security practices such as disallowing root logins over SSH, and basic firewall rules. This Tor relay will be public, and should be secured like any public-facing server.


Installing Tor

Before configuring a relay, the Tor package must be set up on the system. While Debian does have a Tor package in the standard repositories, we will want to add the official Tor repositories and install from there to get the latest software and be able to verify its authenticity.

First, we will edit the sources list so that Debian will know about the official Tor repositories.

$ sudo nano /etc/apt/sources.list

At the bottom of the file, paste the following two lines and save/exit.

deb stretch main
deb-src stretch main

Now back in the console, we will add the Tor Project’s GPG key used to sign the Tor packages. This will allow verification that the software we are installing has not been tampered with.

$ gpg --keyserver --recv A3C4F0F979CAA22CDBA8F512EE8CBC9E886DDD89
$ gpg --export A3C4F0F979CAA22CDBA8F512EE8CBC9E886DDD89 | sudo apt-key add -

Lastly, run an update and install Tor from the repositories we just added.

$ apt-get update
$ apt-get install tor


Keeping Time

It is important that a Tor relay keeps accurate time, so we will change the timezone and set up the ntp client.

First, list timezones to and find which one corresponds to the location of the machine:

$ timedatectl list-timezones

Next, we set the timezone to the one for the machine’s location. Amsterdam is used below as an example.

$ sudo timedatectl set-timezone Europe/Amsterdam

Finally, install ntp:

$sudo apt-get install ntp

You can check your changes using the timedatectl command with no options:

$ timedatectl
      Local time: Sat 2017-12-30 21:49:25 CET
  Universal time: Sat 2017-12-30 20:49:25 UTC
        RTC time: Sat 2017-12-30 20:49:25
       Time zone: Europe/Amsterdam (CET, +0100)
     NTP enabled: yes
NTP synchronized: yes
 RTC in local TZ: no
      DST active: no
 Last DST change: DST ended at
                  Sun 2017-10-29 02:59:59 CEST
                  Sun 2017-10-29 02:00:00 CET
 Next DST change: DST begins (the clock jumps one hour forward) at
                  Sun 2018-03-25 01:59:59 CET
                  Sun 2018-03-25 03:00:00 CEST


Configuring the Relay

By default, all new relays are set up to be exit nodes. Since we want to create a middle relay, there is some configuration that needs to be done.

We will be editing the torrc file, so let’s bring it up in our text editor:

$ sudo nano /etc/tor/torrc

Going line by line in this file is tedious, and to minimize confusion, I will outline some configuration outlines and paste a sample torrc file below that you can use with minimal changes.

  • We don’t need a SOCKS proxy, so uncomment the line SOCKSPolicy reject *
  • We want to keep a separate log file, so uncomment the line Log notice file /var/log/tor/notices.log
  • We will be running as a daemon, so uncomment the line RunAsDaemon 1
  • We will be running monitoring via ARM, so uncomment the line ControlPort 9051
  • Relays need an ORPort for incoming connections, so uncomment the line ORPort 9001
  • It is recommended that a relay has an FQDN or at least a subdomain of one. If not, the machine’s IP address can be used. We will unncomment the line Address and use our address in place of
  • The relay should also have a nickname, so uncomment the line Nickname ididnteditheconfig and use our own nickname in place of ididnteditheconfig
  • Contact information should also be provided, so uncomment the line #ContactInfo Random Person and use our own info in place of Random Person
  • We will be running a directory port, so uncomment the line DirPort 9030
  • The most important option, we don’t want to allow any exits, so uncomment the line ExitPolicy reject *:*
  • Optionally, we may want to limit the bandwidth that Tor uses. To do so, uncomment the lines RelayBandwidthRate 100 KBytes and RelayBandwidthBurst 200 KBytes. These values are defined for one way transport, so note that the actual bandwidth rate above could be 200KB/s total (100KB/s for each input and output). Burst defines a maximum rate, so a burst of 200 KBytes means bandwidth could reach 400KB/s total (combined input and output). Many will likely want their relay to be considered Fast by the network, meaning that the relay’s bandwidth is in the top 7/8ths of all relays. At the time of writing, a rate of 500 KBytes/s seems to be on the low end of achieving this according to a Tor team member.
  • Optionally, we may want to limit the total traffic Tor uses over a period. To do so, uncomment the lines AccountingMax 40 GBytes and AccountingStart month 3 15:00. The AccountingMax value is defined for one way transport, so note that setting 40 GBytes could use 80 GBytes total (40 GBytes for each input and output). If the machine is on a provider that limits monthly bandwidth, it is a good idea to adjust this value to align with the provider’s data cap and adjust the AccountingStart values to reset to reset when the data cap does. NOTE: If you do set accounting, the relay will not advertise a directory port and you will not get directory connections. Relays with directories are expected to have a lot of bandwidth and limiting it will result in other nodes not making directory connections.

Now, here is a full sample torrc file for the tor middle relay:

## Configuration file for a typical Tor user

## Tor opens a SOCKS proxy on port 9050 by default -- even if you don't
## configure one below. Set "SOCKSPort 0" if you plan to run Tor only
## as a relay, and not make any local application connections yourself.
#SOCKSPort 9050 # Default: Bind to localhost:9050 for local connections.
#SOCKSPort # Bind to this address:port too.

## Entry policies to allow/deny SOCKS requests based on IP address.
## First entry that matches wins. If no SOCKSPolicy is set, we accept
## all (and only) requests that reach a SOCKSPort. Untrusted users who
## can access your SOCKSPort may be able to learn about the connections
## you make.
#SOCKSPolicy accept
#SOCKSPolicy accept6 FC00::/7
SOCKSPolicy reject *

## Logs go to stdout at level "notice" unless redirected by something
## else, like one of the below lines. You can have as many Log lines as
## you want.
## We advise using "notice" in most cases, since anything more verbose
## may provide sensitive information to an attacker who obtains the logs.
## Send all messages of level 'notice' or higher to /var/log/tor/notices.log
Log notice file /var/log/tor/notices.log
## Send every possible message to /var/log/tor/debug.log
#Log debug file /var/log/tor/debug.log
## Use the system log instead of Tor's logfiles
#Log notice syslog
## To send all messages to stderr:
#Log debug stderr

## Uncomment this to start the process in the background... or use
## --runasdaemon 1 on the command line. This is ignored on Windows;
## see the FAQ entry if you want Tor to run as an NT service.
RunAsDaemon 1

## The directory for keeping all the keys/etc. By default, we store
## things in $HOME/.tor on Unix, and in Application Data\tor on Windows.
#DataDirectory /var/lib/tor

## The port on which Tor will listen for local connections from Tor
## controller applications, as documented in control-spec.txt.
ControlPort 9051
## If you enable the controlport, be sure to enable one of these
## authentication methods, to prevent attackers from accessing it.
#HashedControlPassword 16:872860B76453A77D60CA2BB8C1A7042072093276A3D701AD684053EC4C
#CookieAuthentication 1

############### This section is just for location-hidden services ###

## Once you have configured a hidden service, you can look at the
## contents of the file ".../hidden_service/hostname" for the address
## to tell people.
## HiddenServicePort x y:z says to redirect requests on port x to the
## address y:z.

#HiddenServiceDir /var/lib/tor/hidden_service/
#HiddenServicePort 80

#HiddenServiceDir /var/lib/tor/other_hidden_service/
#HiddenServicePort 80
#HiddenServicePort 22

################ This section is just for relays #####################
## See for details.

## Required: what port to advertise for incoming Tor connections.
ORPort 9001
## If you want to listen on a port other than the one advertised in
## ORPort (e.g. to advertise 443 but bind to 9090), you can do it as
## follows.  You'll need to do ipchains or other port forwarding
## yourself to make this work.
#ORPort 443 NoListen
#ORPort NoAdvertise

## The IP address or full DNS name for incoming connections to your
## relay. Leave commented out and Tor will guess.

## If you have multiple network interfaces, you can specify one for
## outgoing traffic to use.
# OutboundBindAddress

## A handle for your relay, so people don't have to refer to it by key.
Nickname peer3famicoman

## Define these to limit how much relayed traffic you will allow. Your
## own traffic is still unthrottled. Note that RelayBandwidthRate must
## be at least 20 kilobytes per second.
## Note that units for these config options are bytes (per second), not
## bits (per second), and that prefixes are binary prefixes, i.e. 2^10,
## 2^20, etc.
RelayBandwidthRate 2048 KBytes  # Throttle traffic to 2048KB/s (16384Kbps)
RelayBandwidthBurst 3072 KBytes # But allow bursts up to 3072KB/s (24576Kbps)

## Use these to restrict the maximum traffic per day, week, or month.
## Note that this threshold applies separately to sent and received bytes,
## not to their sum: setting "40 GB" may allow up to 80 GB total before
## hibernating.
## Set a maximum of 40 gigabytes each way per period.
#AccountingMax 400 GBytes
## Each period starts daily at midnight (AccountingMax is per day)
#AccountingStart day 00:00
## Each period starts on the 3rd of the month at 15:00 (AccountingMax
## is per month)
AccountingStart month 24 15:00

## Administrative contact information for this relay or bridge. This line
## can be used to contact you if your relay or bridge is misconfigured or
## something else goes wrong. Note that we archive and publish all
## descriptors containing these lines and that Google indexes them, so
## spammers might also collect them. You may want to obscure the fact that
## it's an email address and/or generate a new address for this purpose.
#ContactInfo Random Person 
## You might also include your PGP or GPG fingerprint if you have one:
#ContactInfo 0xFFFFFFFF Random Person 
ContactInfo famicoman[at]gmail[dot]com - 1DVLNHpcoAso6rvisCnVQbCFN8dRir1GVQ

## Uncomment this to mirror directory information for others. Please do
## if you have enough bandwidth.
DirPort 9030 # what port to advertise for directory connections
## If you want to listen on a port other than the one advertised in
## DirPort (e.g. to advertise 80 but bind to 9091), you can do it as
## follows.  below too. You'll need to do ipchains or other port
## forwarding yourself to make this work.
#DirPort 80 NoListen
#DirPort NoAdvertise
## Uncomment to return an arbitrary blob of html on your DirPort. Now you
## can explain what Tor is if anybody wonders why your IP address is
## contacting them. See contrib/tor-exit-notice.html in Tor's source
## distribution for a sample.
#DirPortFrontPage /etc/tor/tor-exit-notice.html

## Uncomment this if you run more than one Tor relay, and add the identity
## key fingerprint of each Tor relay you control, even if they're on
## different networks. You declare it here so Tor clients can avoid
## using more than one of your relays in a single circuit. See
## However, you should never include a bridge's fingerprint here, as it would
## break its concealability and potentially reveal its IP/TCP address.
#MyFamily $keyid,$keyid,...

## A comma-separated list of exit policies. They're considered first
## to last, and the first match wins.
## If you want to allow the same ports on IPv4 and IPv6, write your rules
## using accept/reject *. If you want to allow different ports on IPv4 and
## IPv6, write your IPv6 rules using accept6/reject6 *6, and your IPv4 rules
## using accept/reject *4.
## If you want to _replace_ the default exit policy, end this with either a
## reject *:* or an accept *:*. Otherwise, you're _augmenting_ (prepending to)
## the default exit policy. Leave commented to just use the default, which is
## described in the man page or at
## Look at
## for issues you might encounter if you use the default exit policy.
## If certain IPs and ports are blocked externally, e.g. by your firewall,
## you should update your exit policy to reflect this -- otherwise Tor
## users will be told that those destinations are down.
## For security, by default Tor rejects connections to private (local)
## networks, including to the configured primary public IPv4 and IPv6 addresses,
## and any public IPv4 and IPv6 addresses on any interface on the relay.
## See the man page entry for ExitPolicyRejectPrivate if you want to allow
## "exit enclaving".
#ExitPolicy accept *:6660-6667,reject *:* # allow irc ports on IPv4 and IPv6 but no more
#ExitPolicy accept *:119 # accept nntp ports on IPv4 and IPv6 as well as default exit policy
#ExitPolicy accept *4:119 # accept nntp ports on IPv4 only as well as default exit policy
#ExitPolicy accept6 *6:119 # accept nntp ports on IPv6 only as well as default exit policy
ExitPolicy reject *:* # no exits allowed

## Bridge relays (or "bridges") are Tor relays that aren't listed in the
## main directory. Since there is no complete public list of them, even an
## ISP that filters connections to all the known Tor relays probably
## won't be able to block all the bridges. Also, websites won't treat you
## differently because they won't know you're running Tor. If you can
## be a real relay, please do; but if not, be a bridge!
#BridgeRelay 1
## By default, Tor will advertise your bridge to users through various
## mechanisms like If you want to run
## a private bridge, for example because you'll give out your bridge
## address manually to your friends, uncomment this line:
#PublishServerDescriptor 0

After saving the file, we are ready to restart Tor:

$ sudo service tor restart

Now, we need to make sure everything worked properly and that the relay is functioning as expected. To do so, we will check the logs:

$ sudo nano /var/log/tor/log

If everything worked as expected, the following lines should appear near the bottom of the log file:

[notice] Self-testing indicates your ORPort is reachable from the outside. Excellent.
[notice] Tor has successfully opened a circuit. Looks like client functionality is working.
[notice] Self-testing indicates your DirPort is reachable from the outside. Excellent. Publishing server descriptor.

If you see anything different, make sure your torrc file is configured properly and that your firewall is set to allow connections to the ports you set for the ORPort and DirPort (by default, 9001 and 9030 respectively).


Monitoring Your Relay with Nyx

To monitor Tor relays, many people use a popular tool called Nyx which provides graphical information about activity and status of the node. Nyx utilizes the ControlPort we set earlier to connect into our relay. This port shot not need to be accepted by a firewall if Nyx will be running on the same machine and should be password-protected otherwise.

First, Nyx needs to be installed:

$ sudo apt-get install python-setuptools
$ sudo easy_install pip
$ sudo pip install nyx

Then,Nyx can be run:

$ nyx

The result is a nice representation of the relay’s traffic, utilization, flags, and general information.


Monitoring Your Relay with ARM (Deprecated)

While ARM is no longer maintained, it does still function.

To monitor Tor relays, many people use a popular tool called ARM which provides graphical information about activity and status of the node. ARM utilizes the ControlPort we set earlier to connect into our relay. This port shot not need to be accepted by a firewall if ARM will be running on the same machine and should be password-protected otherwise.

First, ARM needs to be installed:

sudo apt-get install tor-arm

Then, ARM can be run:


The result is a nice representation of the relay’s traffic, utilization, flags, and general information.



While my relay picked up traffic quickly, it took a long time to be able to fully utilize the bandwidth rates that I gave it. A new Tor middle relay goes through many stages before it can be deemed stable and reliable by the network. I highly recommend reading The lifecycle of a new relay to understand the whole process and know why you may not see traffic right away.

You may notice in my screenshots of Nyx and ARM above, my relay has procured several flags. If you are trying to obtain certain flags for your relay (which sort of act like markers of the relay’s capabilities), I recommend reading this StackExchange post on the subject.

If you want to see some statistics for your relay or share them with others, consider checking out the Atlas and Globe projects. This provides information on a relay by fingerprint of that relay, though you can perform searches with the relay’s nickname. Check out my relay on Atlas and my relay on Globe for examples.

Now that your relay is functioning, you may wish to backup your torrc, backup your relay’s private key (/var/lib/tor/keys/secret_id_key), read and implement operational security practices, and join the tor-relays mailing list.




Bypass Your ISP’s DNS & Run A Private OpenNIC Server (2600 Article)

Now that the article has been printed in 2600 magazine, Volume 34, Issue 3 (2017-10-02), I’m able to republish it on the web. The article below is my submission to 2600 with some slight formatting changes and minor edits.

Bypass Your ISP’s DNS & Run A Private OpenNIC Server
By Mike Dank


With recent U.S. legislation regarding Internet privacy, we see another example of control moving away from consumers and towards service providers. Following the news of this change, many have taken a renewed interest in methods that can take back some of the control and privacy that ISPs and other organizations have slowly been chipping away.

One such service that consumers can liberate (and run) for themselves is DNS. The Domain Name System is responsible for retrieving IP addresses (like from domain names (like For a simplified explanation, when you go to visit a website your machine hasn’t seen before, your machine will query a caching server that is usually owned by your ISP or a company like Google or OpenDNS. This server will return the proper IP address, if they have it cached, or query its way along a chain of DNS servers to the authoritative one controlling that domain. Once found, the IP address for the domain entered will trickle back to you and complete the initial request, allowing your machine to resolve it.

Companies that control these services have a direct look into the sites you are trying to visit. You can bet that more than just a few of them are logging queries and using them for marketing purposes or creating profiles based on who is sitting behind the keyboard at the address of origin. However, there are alternative DNS providers out there who can offer more privacy than others are willing to supply.

One such project, OpenNIC, has been operating a network of DNS servers for many years. Unlike traditional DNS providers, OpenNIC provides an alternate root to the ICANN system (which resolves traditional TLDs, top level domains like .com, .net, etc.) while maintaining backwards compatibility with them. Using OpenNIC, you can still resolve all of the same sites, but also get access to those run by OpenNIC operators, with TLDs such as .geek, .pirate, and .bbs. OpenNIC is made up of hobbyists, engineers, and tinkerers who not only want to explore the ins and outs of DNS, but also offer enhanced privacy and free domain registration for TLDs within their root! You may see OpenNIC as just-another-organization to query, but many operators are privacy-oriented, running their own servers devoid of logging and/or in countries that don’t poke around in your network traffic.

Aside from using an official OpenNIC DNS server to query your home traffic against directly, you can also set one up yourself. Using a modest VPS (512MB of RAM, 4GB of disk) hosted somewhere outside of the US (or the 14-eyes jurisdiction, if you prefer), you can subvert organizations who may be nefariously gathering information from your queries. While your server will still ultimately connect upstream to an OpenNIC server, any clients at home or on the go never will — they will only directly query your new DNS server directly.

Installation & Configuration

Setting up a DNS server is relatively easy to do with just a basic understanding of the shell. I’m running a Debian system, so some of the configuration may be different depending on the distribution you are running. Additionally, the steps below are for configuring a BIND server. There are many different DNS server packages out there to choose from, though BIND is arguably the most widespread on GNU/Linux hosts.

After logging into our server we will first want to switch to the root account to configure BIND.

$ su -

Next, we will install bind9 and DNS utilities using the package manager. This will automatically configure a (non-publicly accessible) DNS server for us to work with and various DNS tools that will aid in setting up the server (specifically, dig).

$ apt-get install bind9 dnsutils -y

Now, we will pull down the OpenNIC root hints file for BIND to use. The root hints file simply contains information about OpenNIC’s root DNS servers that control the alternative TLDs OpenNIC has to offer (as well as provide backwards compatibility to ICANN domains). On Debian, we save this information to ‘/etc/bind/db.root’ for BIND to access.

$ dig . NS @ > /etc/bind/db.root

While the root hints information does not change often, new TLDs can be added to OpenNIC periodically. We will set up a cron job that updates this file once a month (you can specify this to be more frequent is you wish) at 12:00AM on the first of the month. Let’s edit the crontab to add this recurring job.

$ crontab -e

At the bottom of the file, paste the following and save, activating our job.

0 0 1 * * /usr/bin/dig . NS @ > /etc/bind/db.root

Next, we will want to make some changes to the BIND configuration files. Specifically, we will allow recursive queries (so our BIND installation can query the OpenNIC root servers), enable DNSSEC validation (to verify integrity of DNS data on query to OpenNIC servers), and whitelist our client’s IP address. Edit ‘/etc/bind/named.conf.options’ and replace the contents with the following options block, making any edits as needed to specify a client’s IP address.

options {        
    directory "/var/cache/bind";

    //Allow localhost and a client IP of        
    allow-query { localhost;; };        
    recursion yes;

    dnssec-enable yes;        
    dnssec-validation yes;        
    dnssec-lookaside auto;

    auth-nxdomain no;    # conform to RFC1035        
    listen-on-v6 { any; };  //Only use if your server has an ipv6 iface! 

Now, we will also change the logging configuration so that no logs are kept for any queries to our server. This is beneficial in that we know our own queries will never be logged on our server (as well as queries from anyone else we might authorize to use our server at a later date) for any reason. To make this change, edit ‘/etc/bind/named.conf’ and add the following logging block to the bottom of the file.

logging {
    category default { null; };

Finally, restart BIND so it can use our new configuration.

$ /etc/init.d/bind9 restart

Now, make sure that our server is using itself for DNS by checking the ‘/etc/resolv.conf’ file. If it doesn’t exist already, place the following line above any other lines starting with “nameserver”.


Testing resolution of both OpenNIC and ICANN TLDs can be done with a few simple ping commands.

$ ping -c4 
$ ping -c4 opennic.glue

Conclusion & Next Steps

Now that the server is in place, you are free to configure your client machine(s), home router, etc. to make use of the new DNS server. Provided you have port 53 open for both UDP and TCP on the server’s firewall, you should be able to add a similar ‘nameserver’ line to the ‘/etc/resolv.conf’ file (as seen in the previous section) on any authorized client machine, using the server’s external IP address instead of the loopback ‘’ address.
Instructions for DNS configuration on many different operating systems and devices are readily available from a myriad of sources online if you aren’t using a Linux-based client machine. Upon successful configuration, your client should be able to execute the two ping commands in the previous section, verifying a proper setup!

As always, be sure to take precautions and secure your server if you have not done so already. With a functioning DNS server now configured, this project could be expanded upon (as a follow-up exercise/article) by implementing a tool such as DNSCrypt to authenticate and secure your DNS traffic.



Running & Using A Finger Daemon

The finger application was written in the 1970s to allow users on a network to retrieve information about other users. Back before Twitter and other micro-blogging platforms, someone could use the finger command to retrieve public contact information, project notes, GPG keys, status reporting, etc. from a user on a local or remote machine.

Finger has mostly faded into obscurity due to many organizations viewing the availability of public contact information as a potential security hole. With great ease, attackers could learn a target’s full name, phone number, department, title, etc. Still, many embraced the reach that finger could provide. Notably, John Carmack of id Software maintained detailed notes outlining his work in game development.

These days, finger is usually found only on legacy systems or for novelty purposes due to much of its functionality being replaced with the more-usable HTTP.
Installing finger & fingerd

This guide assumes we are running a Debian-based operating system with a non-root, sudo user. To allow finger requests from other machines, make sure the server has port 79 open and available.

The first thing we will need to do is install the finger client, finger daemon, and inet daemon:

sudo apt-get install finger fingerd inetutils-inetd

The inet daemon is necessary to provide network access to the finger daemon. inetd will listen for requests from clients on port 79 (designated for finger) and spawn a process to run the finger daemon as needed. The finger daemon itself cannot listen for these connections and must instead rely on inetd to act as the translator between the sockets and standard input/output.

To ensure that we have IPv6 compatibility (as well as maintain IPv4 compatibility), we will edit the inetd.conf configuration file:

sudo nano /etc/inetd.conf

Find the section that is labeled INFO, and comment out the line under it defining the finger service:

#finger    stream    tcp    nowait        nobody    /usr/sbin/tcpd    /usr/sbin/in.fingerd

Now below it we will add two lines that define the service for IPv4 and IPv6 explicitly:

finger    stream    tcp4    nowait        nobody    /usr/sbin/tcpd    /usr/sbin/in.fingerd
finger    stream    tcp6    nowait        nobody    /usr/sbin/tcpd    /usr/sbin/in.fingerd

Then we will restart inetd to run the changes:

sudo /etc/init.d/inetutils-inetd restart

Now we can use the finger command against our machine:

finger @locahost

User Configuration

Each user will have some user information displayed such as real name, login, home directory, shell, home phone, office phone, and office room. Many of these fields are probably not set for the current user account, but many of these can easily be updated with new information.

The chfn utility is built specifically to change information that is retrieved by the finger commands. We can run it interactively by invoking it:


If we run through this once, we may not be able to edit our full name or wipe out the contents of certain fields. Thankfully, chfn takes several flags to modify these fields individually (and with empty strings accepted!):

$ chfn -f "full name"
$ chfn -o "office room number"
$ chfn -p "office phone number"
$ chfn -h "home phone number"

Now that our information is set, we can start creating files that will be served by finger.

The first file will be the .plan file. This is typically used to store updates on projects, but can be used for pretty much anything such as schedules, favorite quotes, or additional contact information.

nano ~/.plan

Next, we can create a .project file. This file is traditionally used to describe a current project, but can house any content provided it displays on a single line.

nano ~/.project

Next, if we have a GPG key, it can also be included via the .gnupg file.

gpg --armor --output ~/.gnupg --export "my name"

Depending on our machine’s configuration, we can also set up mail forwarding which will be shown when our user account is queried via a .forward file.

echo > ~/.forward

Now that all the files are created, we need to change the permissions on them to allow them to properly be read by finger. This command will allow others to read and execute our new files:

chmod o+rx ~/.plan ~/.project ~/.gnupg ~/.forward

Afterwards, anyone with finger should be able to query the account provided the host is reachable and the port is exposed:

$ finger famicoman@peer0
Login: famicoman                        Name: mike dank
Directory: /home/famicoman              Shell: /bin/bash
Office: #phillymesh, famicoman@gmail    Home Phone: @famicoman
On since Wed Mar  1 18:28 (UTC) on pts/0 from
   5 seconds idle
No mail.
PGP key:
Version: GnuPG v1

Philly Mesh - -
+ Installed fingerd

* Configuring SILC network
* Documentation for fingerd and silcd

By default, finger can display login and contact information for all accounts on a machine. Luckily, accounts can be individually configured so that finger will ignore their existence if there is a .nofinger file in their home directories:

sudo touch /home/someotheraccount/.nofinger && chmod o+rx /home/someotheraccount/.nofinger


You should now have finger and fingerd installed and configured on your server for each user to make use of. Keep in mind that the information you enter here will be public (provided the server is) and people around the world may be able to gleam you contact information or even last login time via the finger command.


Building DIY Community Mesh Networks (2600 Article)

Now that the article has been printed in 2600 magazine, Volume 33, Issue 3 (2016-10-10), I’m able to republish it on the web. The article below is my submission to 2600 with some slight formatting changes for hyperlinks.

Building DIY Community Mesh Networks
By Mike Dank

Today, we are faced with issues regarding our access to the Internet, as well as our freedoms on it. As governmental bodies fight to gain more control and influence over the flow of our information, some choose to look for alternatives to the traditional Internet and build their own networks as they see fit. These community networks can pop up in dense urban areas, remote locations with limited Internet access, and everywhere in between.

Whether you are politically fueled by issues of net neutrality, privacy, and censorship, fed up with an oligarchy of Internet service providers, or just like tinkering with hardware, a wireless mesh network (or “meshnet”) can be an invaluable project to work on. Numerous groups and organizations have popped up all over the world, creating robust mesh networks and refining the technologies that make them possible. While the overall task of building a wireless mesh network for your community may seem daunting, it is easy to get started and scale up as needed.

What Are Mesh Networks?

Think about your existing home network. Most people have a centralized router with several devices hooked up to it. Each device communicates directly with the central router and relies on it to relay traffic to and from other devices. This is called a hub/spoke topology, and you’ll notice that it has a single point of failure. With a mesh topology, many different routers (referred to as nodes) relay traffic to one another on the path to the target machine. Nodes in this network can be set up ad-hoc; if one node goes down, traffic can easily be rerouted to another node. If new nodes come online, they can be seamlessly integrated into the network. In the wireless space, distant users can be connected together with the help of directional antennas and share network access. As more nodes join a network, service only improves as various gaps are filled in and connections are made more redundant. Ultimately, a network is created that is both decentralized and distributed. There is no single point of failure, making it difficult to shut down.

When creating mesh networks, we are mostly concerned with how devices are routing to and linking with one another. This means that most services you are used to running like HTTP or IRC daemons should be able to operate without a hitch. Additionally, you are presented with the choice of whether or not to create a darknet (completely separated from the Internet) or host exit nodes to allow your traffic out of the mesh.

Existing Community Mesh Networking Projects

One of the most well-known grassroots community mesh networks is Freifunk, based out of Germany, encompassing over 150 local communities with over 25,000 access points. based in Spain, boasts over 27,000 nodes spanning over 36,000 km. In North America we see projects like Hyperboria which connect smaller mesh networking communities together such as Seattle Meshnet, NYC Mesh, and Toronto Mesh. We also see standalone projects like PittMesh in Pittsburgh, WasabiNet in St. Louis, and People’s Open Network in Oakland, California.

While each of these mesh networks may run different software and have a different base of users, they all serve an important purpose within their communities. Additionally, many of these networks consistently give back to the greater mesh networking community and choose to share information about their hardware configurations, software stacks, and infrastructure. This only benefits those who want to start their own networks or improve existing ones.

Picking Your Hardware & OS

When I was first starting out with Philly Mesh, I was faced with the issue of acquiring hardware on a shoestring budget. Many will tell you that the best hardware is low-power computers with dedicated wireless cards. This however can incur a cost of several hundred dollars per node. Alternatively, many groups make use of SOHO routers purchased off-the-shelf, flashed with custom firmware. The most popular firmware used here is OpenWRT, an open source alternative that supports a large majority of consumer routers. If you have a relatively modern router in your house, there is a good chance it is already supported (if you are buying specifically for meshing, consider consulting OpenWRT’s wiki for compatibility. Based on Linux, OpenWRT really shines with its packaging system, allowing you to easily install and configure packages of networking software across several routers regardless of most hardware differences between nodes. With only a few commands, you can have mesh packages installed and ready for production.

Other groups are turning towards credit-card-sized computers like the BeagleBone Black and Raspberry Pi, using multiple USB WiFi dongles to perform over-the-air communication. Here, we have many more options for an operating system as many prefer to use a flavor of Linux or BSD, though most of these platforms also have OpenWRT support.

There are no specific wrong answers here when choosing your hardware. Some platforms may be better suited to different scenarios. For the sake of getting started, spec’ing out some inexpensive routers (aim for something with at least two radios, 8MB of flash) or repurposing some Raspberry Pis is perfectly adequate and will help you learn the fundamental concepts of mesh networking as well develop a working prototype that can be upgraded or expanded as needed (hooray for portable configurations). Make sure you consider options like indoor vs outdoor use, 2.4 GHz vs. 5 GHz band, etc.

Meshing Software

You have OpenWRT or another operating system installed, but how can you mesh your router with others wirelessly? Now, you have to pick out some software that will allow you to facilitate a mesh network. The first packages that you need to look at are for what is called the data link layer of the OSI model of computer networking (or OSI layer 2). Software here establishes the protocol that controls how your packets get transferred from node A to node B. Common software in this space is batman-adv (not to be confused with the layer 3 B.A.T.M.A.N. daemon), and open80211s, which are available for most operating systems. Each of these pieces of software have their own strengths and weaknesses; it might be best to install each package on a pair of routers and see which one works best for you. There is currently a lot of praise for batman-adv as it has been integrated into the mainline Linux tree and was developed by Freifunk to use within their own mesh network.

Revisiting the OSI model again, you will also need some software to work at the network layer (OSI layer 3). This will control your IP routing, allowing for each node to compute where to send traffic next on its forwarding path to the final destination on the network. There are many software packages here such as OLSR (Optimized Link State Routing), B.A.T.M.A.N (Better Approach To Mobile Adhoc Networking), Babel, BMX6, and CJDNS (Caleb James Delisle’s Networking Suite). Each of these addresses the task in its own way, making use of a proactive, reactive, or hybrid approach to determine routing. B.A.T.M.A.N. and OLSR are popular here, both developed by Freifunk. Though B.A.T.M.A.N. was designed as a replacement for OLSR, each is actively used and OLSR is highly utilized in the Commotion mesh networking firmware (a router firmware based off of OpenWRT).

For my needs, I settled on CJDNS which boasts IPv6 addressing, secure communications, and some flexibility in auto-peering with local nodes. Additionally, CJDNS is agnostic to how its host connects to peers. It will work whether you want to connect to another access point over batman-adv, or even tunnel over the existing Internet (similar to Tor or a VPN)! This is useful for mesh networks starting out that may have nodes too distant to connect wirelessly until more nodes are set up in-between. This gives you a chance to lay infrastructure sooner rather than later, and simply swap-out for wireless linking when possible. You also get the interesting ability to link multiple meshnets together that may not be geographically close.

Putting It Together

At this point, you should have at least one node (though you will probably want two for testing) running the software stack that you have settled on. With wireless communications, you can generally say that the higher you place the antenna, the better. Many community mesh groups try to establish nodes on top of buildings with roof access, making use of both directional antennas (to connect to distant nodes within the line of sight) as well as omnidirectional antennas to connect to nearby nodes and/or peers. By arranging several distant nodes to connect to one another via line of sight, you can establish a networking backbone for your meshnet that other nodes in the city can easily connect to and branch off of.

Gathering Interest

Mesh networks can only grow so much when you are working by yourself. At some point, you are going to need help finding homes for more nodes and expanding the network. You can easily start with friends and family – see if they are willing to host a node (they probably wouldn’t even notice it after a while). Otherwise, you will want to meet with like-minded people who can help configure hardware and software, or plan out the infrastructure. You can start small online by setting up a website with a mission statement and making a post or two on Reddit (/r/darknetplan in particular) or Twitter. Do you have hackerspaces in your area? Linux or amateur radio groups? A 2600 meeting you frequent? All of these are great resources to meet people face-to-face and grow your network one node at a time.


Starting a mesh network is easier than many think, and is an incredible way to learn about networking, Linux, micro platforms, embedded systems, and wireless communication. With only a few off-the-shelf devices, one can get their own working network set up and scale it to accommodate more users. Community-run mesh networks not only aid in helping those fed up with or persecuted by traditional network providers, but also those who want to construct, experiment, and tinker. With mesh networks, we can build our own future of communication and free the network for everyone.


I’m in 2600 Magazine

As of the Autumn 2016 issue, I now have an article appearing in 2600: The Hacker Quarterly! My article is titled “Building DIY Community Mesh Networks,” and covers topics in building and organizing local mesh networks.


The issue can be purchased in Barnes & Noble stores, as well as physically or digitally through the 2600 site and I will shortly be making the article available online as well.


(Re)Hacking a Boxee Box

I recently purchased an Amazon Fire TV Stick and love that it allows the ability to sideload applications like Kodi (I still hate that name, long live XBMC!) for media streaming. I mainly use Samba/SMB shares on my network for my media, with most of my content living on an old WDTV Live Hub. The WDTV Hub works great and is still pretty stable after all of these years (except for a few built-in apps like YouTube, I wish they kept going with updates), and the Fire TV will gladly chug away, playing any video over the network. However, I had the need to have my media stream to a third television and I didn’t want to uproot an existing device and carry it from room to room.

So I needed a third device. I already have a second generation Roku kicking around, but it doesn’t appear to be able to run anything other than the stock software at this time. I also considered a Raspberry Pi and wifi dongle, but this puts the price up to around $50 (which is more than the Fire TV Stick. I do want something cheap). I looked for a less expensive option with older media streamers and found a lot of information about the Boxee Box appliance put out by D-Link in 2008, discontinued in 2011. I first encountered this box in around 2012 when I was tasked to do some reverse engineering on it, but that’s another story. In the time since, a Google TV hacking team figured out they could do simple shell command injection when setting the Box’s host name, which eventually evolved into a group developing Boxee+Hacks, a replacement operating system. Since Boxee+Hacks, other developers have been working on a port of Kodi which you can install onto the Boxee to give you more options and better compatibility over the operating system’s built in features.

After some eBaying, I was able to get a Boxee for around $15, shipping included (Make sure you get model DSM-380!). The item description said that the box already had Boxee+Hacks installed and upgraded to the latest version, so I figured I was on my way to a quick installation of Kodi and could get up and running in minutes.

When I first booted the Boxee and checked out the Boxee+Hacks settings, I noticed that the device only had version 1.4 installed while the latest available was 1.6. The built-in updater did not work anymore, so the box never reported that there was an available Boxee+Hacks update.Navigating the Boxee+Hacks forums was a little cumbersome, but I eventually found the steps I needed to get updated and launch Kodi. I’ve outlined them below to help any other lost travelers out there.

First, though, go through your Boxee settings and clear any thumbnail caches, local file databases, etc. We need all the free space we can get and there will be installation errors if you don’t have enough free space. The installation script we will run later automatically clears the device’s temp directory, but doesn’t remove these cached files.

On the Boxee, go to Settings –> Network –> Servers and enable Windows file sharing.

If you already have Boxee+Hacks, connect the box and your computer to your home network and check the IP address for the box on either the Boxee’s settings page or by checking for a new device on your router’s console.

To make things really easy, telnet to your Boxee on port 2323 using your box’s IP address (Mine is

 telnet 2323

Once there, we need to download and run the installer script.

curl -L | sh

If you DO NOT have Boxee+Hacks installed already, never fear. On the same Settings –> Network –> Servers page on your Boxee, locate the Hostname filed and enter the following into it.

boxeebox;sh -c 'curl -L | sh'

Then, navigate away from the Settings page.

After executing the command through telnet, or through the Boxee settings page, the logo should glow red on the front of the box and you should receive on-screen instructions to perform an installation.

Boxee+Hacks installation screen, from

Boxee+Hacks installation screen, from forums.

The installation guide works pretty well. Here, you will be prompted to install Kodi in addition to Boxee+Hacks. At this point I chose NOT to install Kodi. From what I read, once you install it though the script, it can be difficult to remove, and I didn’t want to deal with the possibilities of a difficult upgrade.

Instead, I decided to install Kodi on a flash drive. I’ve had a cheap 512MB drive that has been kicking around for close to ten years, and it is perfect for fitting Kodi. To setup the flash drive, I formatted it as FAT32 and labeled the drive as MEDIA. I’m not sure if either of these matter, but this configuration worked for me. I downloaded the latest Kodi release built for Boxee from the boxeebox-xbmc repository (Version KODI_14.2-Git-2015-10-20-880982d-hybrid at the time of this writing) and unzipped it onto my flash drive. Make sure that the all of the Kodi files are in the root directory of the drive, and not within the KODI_14.2-Git-2015-10-20-880982d-hybrid directory you get from extracting the archive.

It might also help to label the drive

It might also help to label the drive

That’s all there is to it, just plug the flash drive into the back of the Boxee and it is good to go. If you leave the flash drive in, whenever you boot the Boxee it will go right into Kodi. Leave it out and it will boot to standard Boxee+Hacks. If you boot into Boxee+Hacks and then want to load up Kodi, just plug in the flash drive and it loads automatically.

This turns a seemingly unassuming and thought-obsolete device into a pretty powerful media center, and is a quick inexpensive solution to streaming your content to yet another television.


How to Run your Own Independent DNS with Custom TLDs

This article was originally written for and published at N-O-D-E on September 9th, 2015. It has been posted here for safe keeping.



After reading what feels like yet another article about a BitTorrent tracker losing its domain name, I started to think about how trackers could have an easier time keeping a stable domain if they didn’t have to register their domain through conventional methods Among their many roles, The Internet Corporation for Assigned Names and Numbers (ICANN), controls domain names on the Internet and are well known for the work with the Domain Name System (DNS) specifically the operation of root name servers and governance over top level domains (TLDs).

If you ever register a domain name, you pick a name you like and head over to an ICANN-approved registrar. Let’s say I want my domain to be “”. I see if I can get a domain with “n-o-d-e” affixed to the TLD “.net” and after I register it, I’m presented with an easy-to-remember identification string which can be used by anyone in the world to access my website. After I map my server’s IP address to the domain, I wait for the new entry to propagate. This means that the records for my domain are added/updated in my registrar’s records. When someone wants to visit my website, they type out “” in their address bar of their browser and hit the enter key. In the background, their set name server (usually belonging to the ISP) checks to see who controls records for this domain, and then works its way through the DNS infrastructure to retrieve the IP address matching this domain name and returns it back to you.

It’s a reliable, structured system, but it is still controlled by an organization who has been known to retract domains from whoever they like. What if you could resolve domains without going through this central system? What if there was a way to keep sites readily accessible without some sort of governing organization being in control?

I’m not the first to think of answers to these questions. Years ago, there was a project called Dot-P2P which aimed to offer “.p2p” TLDs to peer-to-peer websites as a way of protecting them against losing their domains. While the project had notable backing by Peter Sunde of The Pirate Bay, it eventually stagnated and dissolved into obscurity.

The organization that would have handled the “.p2p” domain registrations, OpenNIC, is still active and working on an incredible project itself. OpenNIC believes that DNS should be neutral, free, protective of your privacy, and devoid of government intervention. OpenNIC also offers new custom TLDs such as “.geek” and “.free” which you won’t find offered through ICANN. Anyone can apply for a domain and anyone can visit one of the domains registered through OpenNIC provided they use an OpenNIC DNS server, which is also backwards-compatible with existing ICANN-controlled TLDs. No need to say goodbye to your favorite .com or .net sites.

If you have the technical know-how to run your own root name server and submit a request to OpenNIC’s democratic body, you too could manage your own TLD within their established infrastructure.

Other projects like NameCoin aim to solve the issue of revoked domains by storing domain data for its flagship “.bit” TLD within its blockchain. The potential use cases for NameCoin take a radical shift from simple domain registrations when you consider what developers have already implemented for storing assets like user data in the blockchain alongside domain registrations.

But what if I wanted to run my own TLD without anyone’s involvement or support, and still be completely free of ICANN control? Just how easy is it to run your own TLD on your own root name server and make it accessible to others around the world?


It turns out that running your own DNS server and offering custom TLDs is not as difficult as it first appears. Before I set out to work on this project, I listed some key points that I wanted to make sure I hit:

– Must be able to run my own top level domain
– Must be able to have the root server be accessible by other machines
– Must be backwards compatible with existing DNS

Essentially, I wanted my own TLD so I didn’t conflict with any existing domains, the ability for others to resolve domains using my TLD, and the ability for anyone using my DNS to get to all the other sites they would normally want to visit (like


For this guide, you are going to need a Linux machine (a virtual machine or Raspberry Pi will work fine). My Linux machine is running Debian. Any Linux distribution should be fine for the job, if you use something other than Debian you may have to change certain commands. You will also want a secondary machine to test your DNS server. I am using a laptop running Windows 7.

Knowledge of networking and the Linux command line may aid you, but is not necessarily required.


I needed DNS software to run on my Linux machine, and decided upon an old piece of software called BIND. BIND has been under criticism lately because of various vulnerabilities, so make sure that you read up on any issues BIND may be experiencing and understand the precautions as you would with any other software you may want to expose publicly. I am not responsible if you put an insecure piece of software facing the internet and get exploited.

It is important to note that I will be testing everything for this project on my local network. A similar configuration should work perfectly for any internet-facing server.

Other DNS software exists out there, but I chose BIND because it is something of a standard with thousands of servers running it daily in a production environment. Don’t discount other DNS packages! They may be more robust or secure and are definitely something to consider for a similar project.


Step 1. Initial Configuration

Connect your Linux machine to the network and check the network interface status.


The response to the command should look similar to this:

eth0      Link encap:Ethernet  HWaddr f0:0d:de:ad:be:ef
                         inet addr:  Bcast:  Mask:
                         UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
                         RX packets:8209495 errors:0 dropped:386 overruns:0 frame:0
                         TX packets:9097071 errors:0 dropped:0 overruns:0 carrier:0
                         collisions:0 txqueuelen:1000
                         RX bytes:2124485459 (1.9 GiB)  TX bytes:1695684733 (1.5 GiB)

Make sure your system is up-to-date before we install anything.

sudo apt-get update
sudo apt-get upgrade

Step 2. Installing & Configuring BIND

Change to the root user and install BIND version 9. Then stop the service.

su -
apt-get install bind9
/etc/init.d/bind9 stop

Now that BIND is installed and not running, let’s create a new zone file for our custom TLD. For this example, I will be using “.node” as my TLD but feel free to use any TLD of your choosing.

cd /etc/bind

Paste the following into the file and edit any values you may see fit, including adding any domains with corresponding IP addresses. For a full explanation of these options visit which has a nice write-up on the format of a zone file. I did find that I needed to specify a NS SOA record with a corresponding A record or BIND would not start.

As you see below, a lot of this zone file is boilerplate but I did specify a record for “google” which signifies that “google.node” will point to the IP address “”

When you are done editing, save the file with CTRL-X.

       ; BIND data file for TLD “.node”
       $TTL    604800  ; (1 week)
       @       IN      SOA     node. root.node. (
       2015091220      ; serial (timestamp)
       604800          ; refresh (1 week)
       86400           ; retry (1 day)
       2419200         ; expire (28 days)
       604800 )        ; minimum (1 week)
       @         IN    NS    ns1.node.    ; this is required
       ;@        IN    A         ; unused right now, semicolon comments out the line
       google  IN    A
       ns1       IN    A         ; this is also required

Now, we need to edit the default zones configuration file to include our new zone.

nano named.conf.default-zones

A the bottom, paste the following block to add our new zone to the configuration.

zone “node.” {
                       type master;
                       file “/etc/bind/”;
                       allow-transfer { any;};
                       allow-query { any;};

Now find the block in the file similar to the below:

zone “.” {
               type hint;
               file “/etc/bind/db.root”;

Replace this block with the following to make our root server a slave to master root server This is one of OpenNIC’s public DNS servers and by marking it as a master, we can also resolve OpenNIC TLDs as well as any TLDs under control of ICANN.

zone “.” in {
                  type slave;
                  file “/etc/bind/db.root”;
                  masters {; };
                 notify no;

After saving the file, we want to generate a new root hints file which queries OpenNIC. This can be done with the dig command.

dig . NS @ > /etc/bind/db.root

Finally, restart BIND.

/etc/init.d/bind9 restart

You should see:

[ ok ] Starting domain name service…: bind9.

Configuration on the server on your Linux machine is now done!

Step 3. Configure Other Machines to Use Your Server

On your Windows machine (on the same local network), visit the Network Connections panel by going to Control Panel -> Network and Internet -> Network Connections.

Right-click on your current network connection and select Properties. On the resulting Network Connection Properties dialog, select Internet Protocol Version 4 (TCP/IPv4) if you are using IPv4 for your local network or Internet Protocol Version 6 (TCP/IPv6). Since I am using IPv4, I will be selecting the former.

Next, click the Properties button. On the resulting Internet Protocol Properties dialog, select the radio button for “Use the following DNS server addresses.” Enter the IP address of your Linux machine in the Preferred DNS server box ( from my example, but make sure you use the IP address of your Linux machine) and then click the OK button. Back on the Network Connection Properties dialog, click the Close button.

Now, load up a command shell and ping one of our defined domains.

ping google.node

You should see the following:

Pinging google.node [] with 32 bytes of data:
Reply from bytes=32 time=15ms TTL=55
Reply from bytes=32 time=17ms TTL=55
Reply from bytes=32 time=16ms TTL=55

Congratulations, you now have a DNS server which will not only resolve your custom TLD but be accessible to other machines.


This is just a proof of concept, and could easily be expanded upon for future projects. If you are wondering where to go from here, you could easily move on to make your DNS publicly accessible and expand the offerings. Further, you could construct multiple DNS nodes to act as slaves or links to your root server as a method of distributing the network to make it more reliable and geographically accessible

While I don’t think many BitTorrent trackers will be quick to adopt a system such as this, it still shows that you can create and resolve custom TLDs which may be useful for constructing alternative networks.




Automating Site Backups with Amazon S3 and PHP

This article was originally written for and published at TechOats on June 24th, 2015. It has been posted here for safe keeping.


I host quite a few websites. Not a lot, but enough that the thought of manually backing them up at any regular interval fills me with dread. If you’re going to do something more than three times, it is worth the effort of scripting it. A while back I got a free trial of Amazon’s Web Services, and decided to give S3 a try. Amazon S3 (standing for Simple Storage Service) allows users to store data, and pay only for the space used as opposed to a flat rate for an arbitrary amount of disk space. S3 is also scalable; you never have to worry about running out of a storage allotment, you get more space automatically.

S3 also has a web services interface, making it an ideal tool for system administrators who want to set it and forget it in an environment they are already comfortable with. As a Linux user, there were a myriad of tools out there already for integrating with S3, and I was able to find one to aide my with my simple backup automation.

First things first, I run my web stack on a CentOS installation. Different Linux distributions may have slightly different utilities (such as package managers), so these instructions may differ on your system. If you see anything along the way that isn’t exactly how you have things set up, take the time and research how to adapt the processes I have outlined.

In Amazon S3, before you back up anything, you need to create a bucket. A bucket is simply a container that you use to store data objects within S3. After logging into the Amazon Web Services Console, you can configure it using the S3 panel and create a new bucket using the button provided. Buckets can have different price points, naming conventions, or physical locations around the world. It is best to read the documentation provided through Amazon to figure out what works best for you, and then create your bucket. For our purposes, any bucket you can create is treated the same and shouldn’t cause any problems depending on what configuration you wish to proceed with.

After I created my bucket, I stumbled across a tool called s3cmd which allows me to interface directly with my bucket within S3.

To install s3cmd, it was as easy as bringing up my console and entering:

sudo yum install s3cmd

The application will install, easy as that.

Now, we need a secret key and an access key from AWS. To get this, visit and click the plus icon next to Access Keys (Access Key ID and Secret Access Key). Now, you can click the button that states Create New Access Key to generate your keys. They should display in a pop-up on the page. Leave this pop-up open for the time being.

Back to your console, we need to edit s3cmd’s configuration file using your text editor of choice, located in your user’s home directory:

nano ~/.s3cfg

The file you are editing (.s3cfg) needs both the access key and the secret key from that pop-up you saw earlier on the AWS site. Edit the lines beginning with:

access_key = XXXXXXXXXXXX
secret_key = XXXXXXXXXXXX

Replacing each string of “XXXXXXXXXXXX” with your respective access and secret keys from earlier. Then, save the file (CTRL+X in nano, if you are using it).

Now we are ready to write the script to do the backups. For the sake of playing different languages, I chose to write my script using PHP. You could accomplish the same behavior using Python, Bash, Perl, or other languages, though the syntax will differ substantially. First, our script needs a home, so I created a backup directory to house the script and any local backup files I create within my home directory. Then, I changed into that directory and started editing my script using the commands below:

mkdir backup
cd backup/
nano backup.php

Now, we’re going to add some code to our script. I’ll show an example for backing up one site, though you can easily duplicate and modify the code for multiple site backups. Let’s take things a few lines at a time. The first line starts the file. Anything after <?php is recognized as PHP code. The second line sets our time zone. You should use the time zone of your server’s location. It’ll help us in the next few steps.


So now we dump our site’s database by executing the command mysqldump through PHP. If you don’t run MySQL, you’ll have to modify this line to use your database solution. Replace the username, password, and database name on this line as well. This will allow you to successfully backup the database and timestamp it for reference. The following line will archive and compress your database dump using gzip compression. Feel free to use your favorite compression in place of gzip. The last line will delete the original .sql file using PHP’s unlink, since we only need the compressed one.

exec("mysqldump -uUSERNAMEHERE -pPASSWORDHERE DATABASENAMEHERE > ~/backup/".date('Y-m-d').".sql");
exec("tar -zcvf ~/backup/".date('Y-m-d').".tar.gz ~/backup/".date('Y-m-d').".sql");

The next line will archive and gzip your site’s web directory. Make sure you check the directory path for your site, you need to know where the site lives on your server.

exec("tar -zcvf ~/backup/".date('Y-m-d').".tar.gz /var/www/public_html/");

Now, an optional line. I didn’t want to keep any web directory backups older than three months. This will delete all web directory backups older than that. You can also duplicate and modify this line to remove the database archives, but mine don’t take up too much space, so I keep them around for easy access.

@unlink("~/backup/".date('Y-m-d', strtotime("now -3 month")).".tar.gz");

Now the fun part. These commands will push the backups of your database and web directory to your S3 bucket. Be sure to replace U62 with your bucket name.

exec("s3cmd -v put ~/backup/".date('Y-m-d').".tar.gz s3://U62");
exec("s3cmd -v put ~/backup/".date('Y-m-d').".tar.gz s3://U62");

Finally, end the file, closing that initial <?php tag.


Here it is all put together (in only ten lines!):

exec("mysqldump -uUSERNAMEHERE -pPASSWORDHERE DATABASENAMEHERE > ~/backup/".date('Y-m-d').".sql");
exec("tar -zcvf ~/backup/".date('Y-m-d').".tar.gz ~/backup/".date('Y-m-d').".sql");
exec("tar -zcvf ~/backup/".date('Y-m-d').".tar.gz /var/www/public_html/");
@unlink("~/backup/".date('Y-m-d', strtotime("now -3 month")).".tar.gz");
exec("s3cmd -v put ~/backup/".date('Y-m-d').".tar.gz s3://U62");
exec("s3cmd -v put ~/backup/".date('Y-m-d').".tar.gz s3://U62");

Okay, now our script is finalized. You should now save it and run it with the command below in your console to test it out!

php backup.php

Provided you edited all the paths and values properly, your script should push the two files to S3! Give yourself a pat on the back, but don’t celebrate just yet. We don’t want to have to run this on demand every time we want a backup. Luckily we can automate the backup process. Back in your console, run the following command:

crontab -e

This will load up your crontab, allowing you to add jobs to Cron: a time based scheduler. The syntax of Cron commands is out of the scope of this article, but the information is abundant online. You can add the line below to your crontab (pay attention to edit the path of your script) and save it so it will run on the first of every month.

0 0 1 * * /usr/bin/php /home/famicoman/backup/backup.php