This article covers a version of Ubuntu that is no longer supported. If you are currently operate a server running Ubuntu 12.04, we highly recommend upgrading or migrating to a supported version of Ubuntu:
Reason: Ubuntu 12.04 reached end of life (EOL) on April 28, 2017 and no longer receives security patches or updates. This guide is no longer maintained.
See Instead: This guide might still be useful as a reference, but may not work on other Ubuntu releases. If available, we strongly recommend using a guide written for the version of Ubuntu you are using. You can use the search functionality at the top of the page to find a more recent version.
Security should be a primary concern for any kind of data that stored on an internet accessible computer. While every storage provider should take care to secure data from their end, this only goes so far as unauthorized access can happen through software flaws of services on your server, social engineering, and many other avenues. In short, you should take ownership of the encryption and security of any data that you cannot afford to fall into the wrong hands.
There are many ways to encrypt content on a Linux system. Many of these options rely on encrypting separate partitions, devices, or filesystems. This may not be an option if you are dealing with a system like a VPS. However, there are other options, such as creating a file that operates as a device in order to store encrypted data.
In this guide, we will use the
dm-crypt tools to create a large encrypted file that can be used to store our sensitive data. We can then mount this file as if it were a regular partition. We will be demonstrating this on an Ubuntu 12.04 VPS instance, but similar procedures should work for other distributions.
dm-crypt is a kernel-level encryption mechanism which offers transparent disk encryption. This means that the files are immediately available without any additional interaction after mounting.
While most encryption schemes rely on encrypting things at the partition level, we can get around this by using a file that we mount as a device mapping target. We do this by mounting the file as a loop device. We can then store data on this mounted “device” just like we would with any other partition or device.
When considering implementing any kind of encryption, you need to weigh some pros and cons. First of all, there is always a performance overhead involved with encryption. This may or may not be significant, and we recommend that you create a small file first to run tests against before implementing this on a larger scale.
Another consideration is recovery. Encryption, by virtue of its primary function, makes recovery more difficult. If you forget your password, your data is effectively lost forever. If your LUKS header is overwritten or damaged, your data is also lost forever. If your system is not booting and you need to access information in your encrypted file, you will have to go through a more complex process to gain access.
When making a decision to encrypt data, you need to be aware of the possibility of losing that data if something goes wrong. You should definitely backup any of the data, and dm-crypt provides a lot of information about how to do that here.
While the kernel-level functionality should be available in your distribution, the actual front-end tools probably are not installed by default. All of the commands in this guide will be performed as root.
We can get the necessary tools by updating our local package index and installing the
apt-get update apt-get install cryptsetup
This will pull in all of the required dependencies and helper utilities needed to work with a
To store our encrypted data, we need to create a file which will act as our storage device.
We want to create an empty file, but we can’t have that be a sparse file, which doesn’t actually allocate the full file size when it is created. We can do this in a variety of ways.
The easiest and the quickest way of going about this operation is with the
fallocate command. This instantly allocates the amount of disk you would like for a file and assigns it the filename you give it.
For instance, to create a 512MB file on in our root user’s home directory, we can type:
fallocate -l 512M /root/test1
This is incredibly fast, but it does have a disadvantage that it will not overwrite whatever old, deleted data that used to be used by those blocks with zeros or random data. This probably will not be desirable for your purposes because we don’t want people to be able to tell which portion of the file has encrypted data written to it.
Another alternative is using the ubiquitous
dd command. We can write zeroes to the entire area that we are provisioning to our file by using the
/dev/zero pseudo-device. We could create a similar file to the one above by typing something like:
dd if=/dev/zero of=/root/test2 bs=1M count=512
If instead, you would like to write random data, which should mimic the encrypted data that will actually be written to it, you can use one of the random pseudo-devices instead. This will take quite a lot longer, especially if you are allocating a large file, but using the random devices is probably is the best way to provision a file for this purpose:
dd if=/dev/urandom of=/root/test3 bs=1M count=512
/dev/random pseudo-device is an even more secure way of doing this, again at the expense of time:
dd if=/dev/random of=/root/test4 bs=1M count=512
Before we format the file that we just created, we should create a LUKS partition within the file. LUKS, or Linux Unified Key Setup, is a standard for disk encryption. This is the basic layer that all of our other data will sit on top of.
dm-crypt tools provide a very easy way to create this layer. We can create the container with this command.
cryptsetup -y luksFormat /root/test1
You will need to confirm that you wish to overwrite the contents of the file. Double check the file you are referencing so that you do not accidentally overwrite the wrong file. When you have confirmed, type “YES” to continue.
You will then be asked to set a password that will be needed to decrypt the data. Remember: if you lose this password, any data saved into the filesystem that we will create will be lost. Securely store this password somewhere where it will not be lost or be sure to remember it. The
-y option will allow us to verify the password to make sure that we haven’t made any mistakes.
If we check out the file now, we can see that it is now known as a LUKS encrypted file:
test1: LUKS encrypted file, ver 1 [aes, cbc-essiv:sha256, sha1] UUID: 1851db36-3223-4ee1-8e3e-cc65c49e05f3
Now that we have the container built on top of our file, we can open the container like this:
<pre> cryptsetup luksOpen <span class=“highlight”>/path/to/LUKS/file</span> <span class=“highlight”>mapping_name</span> </pre>
In our case, we will use our
/root/test1 file and name it
cryptsetup luksOpen /root/test1 volume1
You will have to supply the password you set for the file, which is needed to decrypt it.
This opens the LUKS device, and maps it to a name that we supply, in our case creating a file at
/dev/mapper/volume1. This basically opens the file as a local loopback device so that the rest of the system can now handle the file as if it were a real device.
Now that we have a LUKS container created and it is opened as a regular device in our system, we can begin doing regular device operations on it.
First, we need to format and create a filesystem on our device. You can choose whatever filesystem you’d like. We will use a standard Ext4 filesystem, but you can use any filesystem that your server is configured to handle normally.
For our purposes, the command we want to use is:
mkfs.ext4 -j /dev/mapper/volume1
We now have a filesystem written on top of our LUKS container that is contained in our file. Since it is being handled like a device, our next step is logically to mount the device.
Let’s create a mount location that will make sense:
Now, we just need to mount our filesystem:
mount /dev/mapper/volume1 /mnt/files
You can now see our file as part of our available filesystems:
Filesystem Size Used Avail Use% Mounted on /dev/vda 59G 2.7G 54G 5% / udev 2.0G 12K 2.0G 1% /dev tmpfs 791M 216K 791M 1% /run none 5.0M 0 5.0M 0% /run/lock none 2.0G 0 2.0G 0% /run/shm /dev/mapper/volume1 486M 2.3M 459M 1% /mnt/files
You can see that some of the available space in our file has been taken up by the encryption overhead and the filesystem overhead. We still have most of our space though.
If we check out the location that we’ve mounted our file, we can see that it’s been provisioned exactly like any other Ext4 filesystem:
cd /mnt/files ls
lost+found recovery directory has been created. We can now write data to this location, and it will be placed, encrypted, in our file. For example, we can just take our
/etc directory and copy it into the mount location:
cp -r /etc/* /mnt/files
When we are finished writing or reading our data, we unmount the filesystem using the normal methods:
cd umount /mnt/files
This will detached the
/dev/mapper/volume1 location from our mount point at
Filesystem Size Used Avail Use% Mounted on /dev/vda 59G 2.7G 54G 5% / udev 2.0G 12K 2.0G 1% /dev tmpfs 791M 216K 791M 1% /run none 5.0M 0 5.0M 0% /run/lock none 2.0G 0 2.0G 0% /run/shm
However, our file is still open and available to the system as
control device is a device that is used to create other mapped devices. We can safely ignore this, as it is supposed to be here.
To close the
volume1 file and secure its contents, we have to close the file, basically removing the device mapping from the file. This means that you will no longer be able to access the content of the file until you supply the password again:
cryptsetup luksClose volume1
If we check our device mapping directory, we will see that our
volume1 device has been removed:
Our volume is now unmounted, the LUKS container is closed, and our data is completely encrypted and secured behind our password.
To separate the initial creation procedures from the daily usage, we’ll quickly run through the process that you’d need to take to use the file.
Now that you have the LUKS file, when you want to use it, you can simply open the LUKS file:
cryptsetup luksOpen /root/test1 volume1
You can choose a different name here than you used the first time, it will only matter as long as the file is open. Enter the password for the volume.
Afterwards, mount the device that has been mapped:
mount /dev/mapper/volume1 /mnt/files
You can now access and read or write to the contents of the file.
When you are finished, you’ll have to unmount the device again:
Once the device is unmounted, you can close the LUKS file again to encrypt the data:
cryptsetup luksClose volume1
You should now have the ability to create an encrypted file to store your sensitive data. Remember that there is often a trade off between performance and ease-of-use and security. Also, keep in mind that you must never lose the password you set, because there is absolutely no way of recovering it.
While this is not the only consideration necessary to protect your data, hopefully you can add this to your toolbox in order to tighten up security on your Linux servers.
<div class=“author”>By Justin Ellingwood</div>
Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.
Join our DigitalOcean community of over a million developers for free! Get help and share knowledge in our Questions & Answers section, find tutorials and tools that will help you grow as a developer and scale your project or business, and subscribe to topics of interest.Sign up now
This textbox defaults to using Markdown to format your answer.
You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!
Hi Justin, thanks for great article.
Can you please explain, why did we use ‘-j’ switch in following line ?
Hi, if I want to share the encrypted LUKS container with another host, what are the steps which I should follow at the other host to use the encrypted container?
Good article to refer. Need to know details where the password for encryption decryption is stored.
Great and easy to understand tutorial
Thanks for the great article! But I think as long as the encryption keys will be in RAM, the security of this approach is limited. A solution could be not to store these keys in RAM at all:
I really wonder, why this patch has not found its way into the mainline kernel. What are you guys from DO thinking about it?
Details on Page 10 - Memory attacks: https://www1.informatik.uni-erlangen.de/filepool/projects/tresor/tresor.pdf
Anyone know how to go about enlarging an encypted volume?
Works perfectly on CentOS 7
If you are thinking of automounting the encrypted file system, you want to proceed as described in step four here:
This works perfectly on my Fedora Core 20 server. Thank you for a good guide.
I have a question as an example : I copied file1 and file2 into the encrypted container. However, let us suppose that the computer was shuted down by power cut, while I was copying file3 into the encrypted container. In this case, obviously, the (piece of) file3 would be damaged. But how about file1 and file2? Could I get the file1 and file2 clearly from the encrypted container after rebooting the computer?
I spent 15-20 minutes looking for instructions on how to set up a dm-crypt file container. Yours was, by far, the easiest to follow.
What would you suggest if I needed to send servers to remote locations, and I had code on there that I would like not to be stolen, safe to assume that they can get console access, but I want to prevent them from being able to remove the drive and mount it to another system… and still need this code to run at boot, and still access everything via a SSH or RSSH connection.