How to Remotely Access the Initial Ramdisk of an Encrypted Linux System

If you use cryptsetup to encrypt your Linux root file system, the default setup requires console access to enter the password and boot up the system. If your system is remote or doesn’t have console access, you will need to find a way to get remote access to the console.

If you cannot install a remote console or if your system doesn’t allow one, for example, instances in Amazon Web Services (AWS), you can still obtain remote access to enter the password by installing an ssh server in the initial ramdisk. Once you can login by ssh into the initrd, you can then supply the password to decrypt and boot up the system.

Below is a step-by-step guide on how to install an ssh server in the initial ramdisk, login to it, and enter the password to boot up your encrypted Linux system. The guide is created for Ubuntu and Debian systems and using DHCP to establish network access. The idea can be easily applied to other distributions like CentOS or RHEL.

The guide shows both a manual process and a script to automate the steps. It is recommended to try the manual steps first so that you will have an understanding of the underlying process. This can help in troubleshooting the script in case you encounter problems.

You will need access to GitHub to download the scripts.

Install dropbear

apt-get install dropbear

Get your public ssh-key and copy it to this file on your remote system:

/etc/initramfs-tools/root/.ssh/authorized_keys

If you don’t have an ssh-key pair, you can create one using the ssh-keygen command

ssh-keygen

This command will generate two files:

~/.ssh/id_rsa
~/.ssh/id_rsa.pub

The id_rsa.pub file is the public key where you will need to copy to the remote system as described in #2 above.

The id_rsa file is the private key where you will need to copy to the client that will login by ssh.

If you are using an AWS instance, copy the public-key of your instance into this authorized_keys file.

Update the initial ramdisk image

Run this command to update the initial ramdisk file:

update-initramfs -u

Boot up the system

When the system boots up, connect to the system using ssh and the private key you created above.

ssh -i ~/.ssh/id_rsa root@ip-address

You don’t actually need to supply the -i option for that key-file since that is the default. This is just to illustrate that you need to use the matching key-file to login by ssh.

Enter password remotely

Once you gained access to the system by ssh, execute the following steps in sequence:

  1. Kill the cryptroot process.Sample run:
    # pidof cryptroot
    161
    
    # kill -9 161
    
  2. For Ubuntu systems, wait for the cryptsetup process to terminate. You can monitor this process by running this command:
    # pidof cryptsetup
    

    This could take about a minute to complete.

  3. For Debian systems, wait for the /bin/sh -i process to come up. This is also applicable for Ubuntu.
    Example:

    # ps | grep '/bin/sh -i' | grep -v grep
      214 root      4620 S    /bin/sh -i
    

    This could take about a minute to complete. Take note of the ID of this process when it comes up.

  4. Once cryptsetup has terminated (for Ubuntu only) or the /bin/sh -i process has come up, run the cryptroot command:
    /scripts/local-top/cryptroot
    

    This command will prompt for the password to decrypt the system.

    Sample run:

    # /scripts/local-top/cryptroot
    
    /scripts/local-top/cryptroot: line 1: modprobe: not found
    Unlocking the disk /dev/disk/by-uuid/b1aa9e88-c344-4922-a0a6-d3f7c52f947a (sda5_crypt)
    Enter passphrase:
    
       Reading all physical volumes.  This may take a while...
      Found volume group "ubuntu-vg" using metadata type lvm2
      2 logical volume(s) in volume group "ubuntu-vg" now active
    cryptsetup: sda5_crypt set up successfully
    
  5. After entering the password, kill the process-id of the /bin/sh -i you saw earlier.Important Note: At this point, your terminal is kind of screwed up. You won’t be able to see what you are typing. So carefully, type the kill command using the /bin/sh -i process-id you got earlier and hit the enter key.
    # kill -9 214
    
  6. Type ctrl-d to disconnect from your ssh access. At this point, the system should be on the way up booting the system. If you have access to the console, you can observe how long it takes for your system to boot up. You can use this to estimate the time it takes for your system to fully come up after you enter the password remotely and start accessing the system.

Automating the remote password process

The remote password process above seems to be a lot of work just to enter the password and boot up the system. If this doesn’t sound fun to you, I wrote a couple of scripts to automate the steps.

  1. Download these two scripts from GitHub:
  2. Save the files at this location:
    /root/cryptroot.sh
    /etc/initramfs-tools/hooks/my_initrd_hook
    

    Make them executable:

    chmod +x /root/cryptroot.sh
    chmod +x /etc/initramfs-tools/hooks/my_initrd_hook
    
  3. Update the initial ramdisk image
    update-initramfs -u
    
  4. Boot up the system and login remotely by ssh
  5. At the shell prompt, run this command and enter the password when you get the prompt:
     /root/cryptroot.sh
    

    Sample run:

    # /root/cryptroot.sh
    
    cryptroot has terminated.
    Waiting for /bin/sh -i to start...
      277 root      4620 S    /bin/sh -i
    sh -i has started.
    
    Unlocking the disk /dev/disk/by-uuid/b1aa9e88-c344-4922-a0a6-d3f7c52f947a (sda5_crypt)
    Enter passphrase:   
    
    Reading all physical volumes.  This may take a while...
      Found volume group "ubuntu-vg" using metadata type lvm2
      2 logical volume(s) in volume group "ubuntu-vg" now active
    cryptsetup: sda5_crypt set up successfully
    Terminating sh -i process...
    Press ctrl-d or type exit to disconnect from initrd dropbear.
    
    #
    

Show the History of CVS Commits Similar to Git or SVN

I wrote a simple script that will display the history of CVS commits similar to the way Git or SVN do. You can download the script from Github: https://github.com/alvinabad/cvs-utils/blob/master/cvs-history.py

Basic usage

cvs-history.py [-b BRANCH] module or files

For more options, see: https://github.com/alvinabad/cvs-utils#cvs-historypy

Background

If you use the “cvs history” command to display the history of commits in CVS, you will get an output that is not sorted chronologically.

Here’s a sample run:

$ cvs history -a -c hello_cvs/
M 2015-02-28 23:52 +0000 alice 1.6     hello1.py hello_cvs == ~/main/hello_cvs
M 2015-02-28 23:48 +0000 alice 1.3     hello2.py hello_cvs == ~/main/hello_cvs
M 2015-03-01 17:05 +0000 alice 1.3.2.1 hello2.py hello_cvs == ~/workspace/hello_cvs
A 2015-03-01 00:38 +0000 alice 1.1.2.1 hello3.py hello_cvs == ~/feature_branch/hello_cvs
M 2015-03-01 00:42 +0000 alice 1.1.2.2 hello3.py hello_cvs == ~/workspace/hello_cvs
M 2015-02-28 23:10 +0000 alvin 1.2     hello1.py hello_cvs == ~/src/hello_cvs
M 2015-02-28 23:13 +0000 alvin 1.3     hello1.py hello_cvs == ~/src/hello_cvs
M 2015-02-28 23:18 +0000 alvin 1.4     hello1.py hello_cvs == ~/src/hello_cvs
M 2015-02-28 23:23 +0000 alvin 1.5     hello1.py hello_cvs == ~/src/hello_cvs
M 2015-03-01 00:37 +0000 alvin 1.7     hello1.py hello_cvs == ~/src/hello_cvs
A 2015-02-28 23:20 +0000 alvin 1.1     hello2.py hello_cvs == ~/src/hello_cvs
M 2015-02-28 23:23 +0000 alvin 1.2     hello2.py hello_cvs == ~/src/hello_cvs
M 2015-03-01 00:44 +0000 alvin 1.4     hello2.py hello_cvs == ~/src/hello_cvs

As you can see from the output above, it is hard to figure out the order when the changes happened. The output gets worse if you have many branches. The output displays all the history of commits in all branches and mixed altogether.