Setting Up a "Hardened" Linux Server


(If you have any comments or questions about this guide, please let me know in this thread on




Preliminary to any cryto-coin project is setting up the computer/server which runs it, and it is vitally important that this be done in a secure manner.  These instruction will take you, step-by-step, through the process of doing exactly that, using the very popular Ubuntu Linux.


While these instructions were written with Darkcoin in mind, they can very easily be applied to setting up a hardened server for just about any purpose or application.


1.  Create Server, Add Users

1(a)  Create Server

I created a new cloudserver from scratch as my REMOTE server for this, which is a fairly straightforward process.  There are a number of online services for creating a cloudserver.  I also created a new virtual machine on my home computer as my LOCAL machine.  This ensures that both the REMOTE and LOCAL machines are in a “fresh” state, and that someone else could follow these instructions step-by-step and should have the same results.  (In other words, no unpleasant surprises.)

For my REMOTE machine I used Ubuntu 14.04 LTS, with 2 gig of ram.  (As a reminder, these intructions were written for Darkcoin, and ultimately for creating a Darkcoin mining pool with P2Pool.  2G may have been the minimum recommended size for my purposes; if I had created a swapfile then 1G should have been enough.  I may show how to set up a swapfile in another tutorial, but I am trying to keep this as simple as possible for now.  If you are setting up your server for different purposes, you may not need 2G.) 


Since I am running a Masternode with an external "cold" wallet I also needed to set up a LOCAL machine.  For my LOCAL machine I used Ubuntu 12.04 LTS; if you are NOT running a Masternode, then you don't need a LOCAL machine.  (As far as I can tell, Ubuntu 12.04 and 14.04 both work for either machine, so if you want to follow my instructions, PLEASE use only these versions.)

As a note of caution: When you create your REMOTE server be sure to copy your server password and ssh login address, which you should have created or obtained when creating the server.  You will need these to login with ssh.

In these instructions I will assume you have created the machines with the specifications given.

1(b)  Log-in with ssh; change root password

Assuming you have created your machines, use a terminal program on you LOCAL machine to log-in to your REMOTE server:  (The part in <brackets> is meant to represent the ip address of your REMOTE server.  Throughout this tutorial, any time you see <brackets> it means that you should substitute your own value.  You should not type the brackets themselves, or the text inside of them, into your commands; rather replace the given brackets and text with your value for whatever is indicated.)


ssh root@<>

1(c)  Create needed users

Only the root user exists by default, but we don't want to be logging in and doing general administration with root, because that's an insecure way of doing things.  So, we'll create a general-user with sudo capabilities for all of our administration tasks, and a separate login-user without sudo capabilities just for logging-in via ssh.

Create the General User (make up a name for the general-user):

adduser <general-user>

Add the general-user to sudoers:

sudo usermod -a -G sudo <general-user>

Create the Login User (again, make up a name for the login-user):

adduser <login-user>

2  Hardening the Server Against Attacks

We have created our server and added necessary users.  Before going further we should first harden our server security.  (If we mess this up then we might not be able to log-in to the server at all and then have to start again from scratch, so it is wise not to get too far ahead of ourselves here.) 


This will involve:

  • configuring ssh so that the only user allowed to log-in is our login-user,  and is EITHER required to use the private ssh key and a special passphrase to login -OR- all users have been set up with SUPREMELY secure passwords;
  • closing all ports except those which are required to be open.



2(a) Setting Up SUPREMELY Secure Passwords


For some, the process of creating and keeping track of public/private keys may be a bit too technical, and can be especially difficult to deal with when trying to log in from a new operating system or different computer.  At one time such extreme security measures were definitely needed, as operating a masternode required that 1000DRK be stored on the REMOTE server, thus making the remote server a serious target for hackers.  Now that Darkcoin Masternodes can be run using an "external" wallet, this threat has diminished greately. 


While I still recommend using public/private keys as the most secure method, for some less-eperienced users it might be better to simply create SUPREMELY secure passwords for your login-user, your general-user, and your root user.  These should be at least 30 CHARACTERS LONG, and consist of both UPPER- and LOWER-CASE LETTERS and NUMBERS, and should be COMPLETELY RANDOM.  Each should be stored on an encrypted removable usb stick so they are portable, and can be used on whatever machine you happen to be logging in from.


Again, the public/private key method is more secure, is more technical and harder to deal with for the less-experienced when problems arise.  The SUPREMELY secure password methoc is a bit less secure, but easier to handle for the less-experienced.  The choice is ultimately up to you.  If you decide to go with the public/private key method, simply skip to step 2(b).  If you decide instead to go with the SUPREMELY secure password method, you simply need to change the passwords for each of your users to something SUPREMELY secure, as described here:


Switch to the login-user and change its password to something SUPREMELY secure:


su <login-user>



Exit from the login-user, switch to the general-user, and change its password to something SUPREMELY secure:



su <general-user>



Exit from the general-user, and switch the root password to something SUPREMELY secure:




Then just skip ahead to step 2(f) Configuring Ports.


2(b)  Create SSH Public/Private Keys on LOCAL Machine

We need to generate a public/private key pair for ssh.  We will be doing this on our LOCAL machine, NOT our remote cloud server.   We will also create a means to handle multiple ssh key pairs; otherwise we would only be able to use ssh keys to connect to one remote server.  We will create these pairs in the ~/.ssh folder of our LOCAL machine, so create this directory if it does not exist:

mkdir ~/.ssh

Then create the file name for our keys.  This will be a new, descriptive file name, such as “~/.ssh/my_server_001” (and if you had multiple servers you could simply increment the digits) or anything else which seems appropriate to you.  (We will represent the name of this server key as <darkcoin-server-key> in this tutorial; you will replace this with whatever seems appropriate to you, as stated.)

touch /home/<your-LOCAL-user-name>/.ssh/<darkcoin-server-key>
ssh-keygen -t rsa

Rather than accepting the default file name “~/.ssh/id_rsa” which would over-write any pre-existing keys, we will use the name of the file we just created:


Create a really long and hard to guess passphrase when prompted.

Set permissions on both the public and private key we have just created:

chmod 644 /home/<your-LOCAL-user-name>/.ssh/<darkcoin-server-key>.pub
chmod 600 /home/<your-LOCAL-user-name>/.ssh/<darkcoin-server-key>

2(c)  Create/Edit ~/.ssh/config File on LOCAL Machine to Handle Multiple Keys

In order to handle having multiple keys on the same LOCAL machine, we will create a configuration file (“~/.ssh/config”) to handle the multiple keys.

Create  and chmod the ~/.ssh/config if it doesn't already exist:

touch ~/.ssh/config
chmod 644 ~/.ssh/config


Open the config file for editing:

nano ~/.ssh/config

Then edit your ~/.ssh/config file so each host has its own entry.  (We will only be showing our REMOTE server here, but you can ultimately add as many as you need, including any which you might have previously set up to connect with via shh keys.  We are also showing Host and Hostname using the ip address, but you could also use names like “” or whatever yours actually is.)

Host <>
        Hostname <>
        PreferredAuthentications publickey
        IdentityFile ~/.ssh/<darkcoin-server-key>

2(d)  Copy Public Key to REMOTE Server, and Set Permissions

We will now copy the public key onto the REMOTE server by creating the file /home/<login-user>/.ssh/authorized_keys and simply copying/pasting the contents of the LOCAL file ~/.ssh/<darkcoin-server-key>.pub into it.

On the REMOTE machine:

mkdir /home/<login-user>/.ssh/
touch /home/<login-user>/.ssh/authorized_keys
nano /home/<login-user>/.ssh/authorized_keys


Now simply copy/paste the contents from the LOCAL /.ssh/<darkcoin-server-key>.pub into the REMOTE .ssh/authorized_keys

Then set the permissions.

chown -R <login-user>:<login-user> /home/<login-user>/.ssh
chmod 700 /home/<login-user>/.ssh
chmod 600 /home/<login-user>/.ssh/authorized_keys

2(e)  Configure SSH on REMOTE Server

Now that we have the private key on our LOCAL machine and the public key on our REMOTE server (everything in the right directories, with all permissions properly set) we can configure ssh.

It might be a good idea to copy the REMOTE ssh configuration file...just in case.  It is often a good idea to do this when you will be changing any configuration files...again, just in case:

sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config_original

Open the ssh configuration file.

sudo nano /etc/ssh/sshd_config

The things  we need to check, set, or add within the sshd_config file are below:

Protocol 2
PermitRootLogin no
PasswordAuthentication no
UseDNS no
AllowUsers <login-user>

When you're done, restart ssh:


service ssh restart

Note that this is a very “strict” configuration.  You will now ONLY be allowed to log-in to your REMOTE server from your current LOCAL machine.  To be able to log-in from a different LOCAL machine you would need to copy the private ssh key from your LOCAL machine onto the other LOCAL machine.  (You might want to keep the private key on an encrypted usb flash drive for such purposes.)  If that other LOCAL machine were not also owned by you, then you would want to delete the private key from it after you were done using it.

If you were willing to compromise just a bit on security you could leave PasswordAuthentication set to yes; it would be better if you could avoid doing this, however, in the event someone guessed or otherwise found out login-user's password.

You should now try to log-out as root and then ssh log-in as <login-user>:

ssh <login-user>@<>

If you can successfully log-in at this point, then you can continue on to the “Configuring Ports” section below.  If you cannot log-in, then you can try to go back and fix any problems by logging-in through a web-based console provided by your cloud-server's host.  If you just can't get it working no matter what, you may have to start again, rebuilding the server from scratch.  (Just know that it's happened to the best of us, sometimes more than once.)


2(f)  Configuring Ports

If you are here, then ssh is properly set-up and you are able to log-in as <login-user> (or you simply set up SUPREMELY secure passwords as described at the end of step ).  Now we just need to properly configure the ports on our server.  This is typically done through iptables...and is typically a bit complicated and prone to error.  Instead we will be using the built-in “UFW” (“Unomplicated FireWall”) tool which comes pre-installed on Ubuntu.  It is simple and effective...'nuf said.

UFW comes disabled by default so first we must enable it, and then disable all connections, incoming and outgoing, by default.  We will then explicitly open any ports we need.  

Since we should be logged-in as <login-user>, and <login-user> does not have root permissions, we will need to switch to our <general-user>:

su <general-user>

Deny all incoming and allow all outgoing connections by default:

sudo ufw default deny incoming
sudo ufw default allow outgoing


For security, you will want to change ssh-port-number for tcp connections, and open that port.  (We will refer to this as <ssh-port-number>.)

sudo ufw allow <ssh-port-number>/tcp

We will now open a number of commonly used ports. 


You may know that you do not need some of these ports, or be unsure as to which you do or do not need.  For most configurations, opening the ports shown below should be safe.  If you are sure that you do not need to open some port, feel free to skip that step.  Also if you wanted to close a port later on, you could to this by simply issuing the command:


sudo ufw deny <port>/<optional: protocol>


For example, to close port 53 for everything...


sudo ufw deny 53


...or just to deny incoming tcp packets to port 53...


sudo ufw deny 53/tcp


...or just to deny incoming udp packets to port 53.


sudo ufw deny 53/udp


In any event, here are commands to open commonly used ports/protocols.

SMTP - Simple Mail Tranfer Protocol Transmission
sudo ufw allow 25/tcp

DNS -    Dynamic Name Server (use both lines)
sudo ufw allow 53/tcp
sudo ufw allow 53/udp

HTTP - Hyper-Text Transfer Protocol
sudo ufw allow 80/tcp

POP3 - Post Office Protocol
sudo ufw allow 110/tcp

IMAP - Internet Mail Access Protocol
sudo ufw allow 143/tcp

HTTPS - Hyper-text Tranfer Protocol Secure
sudo ufw allow 443/tcp

SMTPS - Simple Mail Tranfer Protocol Secure
sudo ufw allow 465/tcp

SMTP - Simple Mail Tranfer Protocol Submission
sudo ufw allow 587/tcp

P2Pool-drk Connection Ports (Needed if you are running a Darkcoin P2Pool.)

sudo ufw allow 7903


Darkcoin Port 9999:mainnet (Needed if you are running Darkcoin on the standard main network.)
sudo ufw allow 9999/tcp
sudo ufw allow 9999/udp


Darkcoin Port 19999:testnet (Needed if you are running Darkcoin on the testing network.)
sudo ufw allow 19999/tcp
sudo ufw allow 19999/udp

Edit the sh configuration file again, just to change the Port to the <ssh-port-number> you chose above:

sudo nano /etc/ssh/sshd_config

And just change the one line:

Port <ssh-port-number>

Now simply enable UFW...

sudo ufw enable

...and check its status (you can omit the word “numbered,” but it provides more information):

sudo ufw status numbered

That's it! Now we can reboot the server, and should be able to log back in using our ssh private key and ssh passphrase, now also including the new <ssh-port-number> in the login.  So:

sudo reboot

(You may have to wait a very short time, about a minute or so, for it to boot up before you can login.)

ssh -p <ssh-port-number> <login-user>@<>

If it works, continue to the next section, “Update and Upgrade and Install General-Dependencies.”  If it does not work, you may have to rebuild from scratch, unless you can log-in via a web-console provided by your cloudserver host to try to fix the problem.

3  Update, Upgrade, and Install General Dependencies

In this section we are just going to be doing some fairly simple updates, upgrades and installations.

Switch to general-user, and general-user's home directory

su <general-user>
cd ~

Update the package list

sudo apt-get update
sudo apt-get upgrade
sudo apt-get dist-upgrade

Install general dependencies/packages we will be needing for our server.  Other dependencies will be added when they are needed.

sudo aptitude install git build-essential screen curl mailutils

Just to be sure that no obvious problems have arisen as a result of our upgrades and installations, let's reboot, and log-in.
sudo reboot  (As before, you may have to wait a very short time for it to boot up before you can login.)

ssh -p <ssh-port-number> <login-user>@<>

If you're able to log-in, then all is good.  Switch to your general-user, and go to the general-user's directory.

su <general-user>
cd ~


You're done setting up your secure, "hardened" Linux server!


(If you have any comments or questions about this guide, please let me know in this thread on

Donations to Planet Crypton may be sent to any of the addresses below:
Bitcoin   BTC   1DX7CwPpTVRtYDNdJmAgu6YiGNiBbCy8TK
Cryptogenic   CGB   5ZayDGUUNYvu9NPrzVtqHdgp84yZ4V715Y
Darkcoin   DRK   XhwsyqCT5pXmfbMCvjkVefcqTAzsUd1y2z
Datacoin   DTC   DKPxTR42T6PtGzfypyUmZx4SNoF1EV1FVK
Devcoin   DVC   1NoNpadN8SmYv8CvjzeD5BPoct52WdYa2T
Digitalcoin   DGC   DKnA78uyScD7a5ZVmr7tYLxwQxX4731Ad3
Dogecoin   DOGE   DCQnicGvMgghUTtGfJgvx2XjzdS8rqmJK8
Feathercoin   FTC   6e1gquKd4yMFKcnJqBZZb9gnTT19FxnPWX
Infinitecoin   IFC   i9gdFXagtpzeQjgtTr6mQThCqpWLgsFR5n
Ixcoin   IXC   xmd2TwspuvVHuW2VuLnVzoFSwVAoiAkqez
Litecoin   LTC   LMrKrZRayv4Cj8qoXhnmjSACNGHCG3d48t
Memorycoin   MMC   MLjbQa2CEwh6rXiCUYFYkwXq1ByBmytzXt
Namecoin   NMC   N7yPYNXxVar8wWz2JpCskSHWJuE4Jmd77k
Novacoin   NVC   4YFx3yoCVsRtv3sLK1XSgAY818AvM3ic25
Peercoin   PPC   PL7rUo6QwZskuY4h4JseyoiqwH3Zsk7fAz
Primecoin   XPM   ARLG4MD6zbU9yENDAKxGvZYixVQNxZE35R
Protoshares   PTS   PbgsjytSatjxAUPhx13Miq6Q9QjcDwq9Vo
Quarkcoin   QRK   QP8ogwaK63nqkgiEUDyw4pZSCSWFp56tsT
Terracoin   TRC   16m2hwePmsQyWE8qEamoiWBZoaG9oRqGZM
Testnet   TEST   mjKJfi4CZ7yrWofuDtF9SjyuoqCkorhek8
Vertcoin   VTC   VscmvCqXHJszXEJ7aUP8FA1AhXanU6BNeE
Worldcoin   WDC   WT5Mj26e2w5XtyvnkyFKvr3muwBYcbd99h
Zetacoin   ZET   ZQMfBXnju9nCVWV8pH8oja6u7Ujm725pWg


Powered by AlienEngine. Get yours now!