diff --git a/src/api/encryption_add.c b/src/api/encryption_add.c
index 554300d31de5871506d3b5d953a4c75e61c9f71b..44faf35fdd5138511659070843a46e3b0422746b 100644
--- a/src/api/encryption_add.c
+++ b/src/api/encryption_add.c
@@ -1,25 +1,36 @@
 /**
  * Callback function for encrypting an unencrypted device.
  * It proceeds as follows:
- * 1. check if the device isn't already encrypted;
- * 2. mount the unencrypted device;
- * 3. determine the total size of the files on the device, and guess if they
- *    will fit into memory;
- * 4. rsync all files from the unencrypted device to memory;
- * 5. unmount the unencrypted device;
- * 6. initialise a new encrypted container on the same device, replacing the
-      unencrypted contents, and unlock it for use;
- * 7. create a new filesystem inside the new container, and mount it;
- * 8. rsync all files back from memory to this newly encrypted device;
- * 9. unmount the new filesystem, and lock the encrypted container.
+ * 1.  check if the device isn't already encrypted;
+ * 2.  mount the unencrypted device;
+ * 3.  determine the total size of the files on the device, and guess if they
+ *     will fit into memory;
+ * 4.  rsync all files from the unencrypted device to memory;
+ * 5.  check if an authorized_keys file can be found on the root device;
+ * 6.  unmount the unencrypted device;
+ * 7.  repartition the device:
+ *     . an info partition to hold unencrypted data for use from the initrd,
+ *       like the dropbear ssh host keys and user's ssh public keys;
+ *     . a data partition for the actual encrypted root device;
+ * 8.  create a filesystem on the info partition;
+ * 9.  copy ssh host keys and the authorized_keys file from the initrd
+ *     to the info partition;
+ * 10. initialise a new encrypted container on the data partition, and unlock it
+ *     for use;
+ * 11. create a new filesystem on this new encrypted data partition,
+ *     and mount it;
+ * 12. rsync all files back from memory to the encrypted data partition;
+ * 13. unmount the new filesystem, and lock the encrypted container;
+ * 14. reboot.
  * @param[in]   request   incoming HTTP request
  * @param[out]  response  HTTP response to the request
- * @param[in]   user_data extra data to pass between main thread and callbacks
+ * @param[in]   user_data extra data to pass between handler and main thread
  * @return                internal status code
  */
 int callback_encryption_add(const struct _u_request * request,
     struct _u_response * response, void * user_data)
 {
+    bool * reboot = (bool *)user_data;
     int r;
 
     // Read the encryption password from the request body.
@@ -32,7 +43,7 @@ int callback_encryption_add(const struct _u_request * request,
     }
  
     // Check if the device isn't already encrypted.
-    if (is_encrypted_device(CONTAINER_DEVICE))
+    if (is_encrypted_device(ROOT_DEVICE))
     {
         // The device is already encrypted; we don't want to encrypt it again.
         return send_simple_response(response, 500, "error",
@@ -40,13 +51,13 @@ int callback_encryption_add(const struct _u_request * request,
     }
 
     // Mount the filesystem on the unencrypted device.
-    r = temporary_mount(CONTAINER_DEVICE, UNENCRYPTED_MOUNTPOINT,
+    r = temporary_mount(ROOT_DEVICE, UNENCRYPTED_MOUNTPOINT,
         FILESYSTEM_TYPE);
     if (r != 0)
     {
-        printf("mounting root disk failed: return code %d", r);
+        printf("mounting root device failed: return code %d\n", r);
         return send_simple_response(response, 500, "error",
-           "mounting root disk failed");
+           "mounting root device failed");
     }
 
     // Determine the filesystem usage of the device to be encrypted.
@@ -54,11 +65,11 @@ int callback_encryption_add(const struct _u_request * request,
     if (size < 0)
     {
         // Something went wrong in determining the filesystem usage.
-        printf("determining filesystem usage failed: return code %lu", size);
+        printf("determining filesystem usage failed: return code %lu\n", size);
         return send_simple_response(response, 500, "error",
            "determining filesystem usage failed");
     }
-    printf("root disk usage: %lu bytes\n", size);
+    printf("root device usage: %lu bytes\n", size);
 
     // Determine the available memory.
     unsigned long memory = available_memory();
@@ -73,16 +84,16 @@ int callback_encryption_add(const struct _u_request * request,
     }
 
     // Copy device contents to temporary filesystem.
-    printf("copying existing root disk contents to memory\n");
+    printf("copying existing root device contents to memory\n");
     char * command = NULL;
     asprintf(&command, "rsync -a %s/ %s", UNENCRYPTED_MOUNTPOINT, TMP_LOCATION);
     r = system(command);
     if(r != 0)
     {
-        printf("copying rootdisk contents into memory failed: return code %d",
-            r);
+        printf("copying root device contents into memory failed"
+            ": return code %d\n", r);
         return send_simple_response(response, 500, "error",
-            "copying rootdisk contents into memory failed");
+            "copying root device contents into memory failed");
     }
 
     // Unmount unencrypted device.
@@ -90,27 +101,144 @@ int callback_encryption_add(const struct _u_request * request,
     r = umount(UNENCRYPTED_MOUNTPOINT);
     if (r != 0)
     {
-        printf("unmounting encrypted device failed: return code %d", r);
+        printf("unmounting encrypted device failed: return code %d\n", r);
         return send_simple_response(response, 500, "error",
-           "unmounting unencrypted disk failed");
+           "unmounting unencrypted device failed");
     }
 
-    // Initialise encrypted container, overwriting existing device.
-    printf("creating encrypted container at %s\n", CONTAINER_DEVICE);
-    r = create_encrypted_device(CONTAINER_DEVICE, password);
-    if(r != 0)
+    // Check whether the authorized_keys file exists on root device.
+    char * authorized_keys_path = NULL;
+    asprintf(&authorized_keys_path, "%s%s",
+        TMP_LOCATION, AUTHORIZED_KEYS_PATH);
+    struct stat st = {0};
+    if (stat(authorized_keys_path, &st) == -1)
+    {
+        printf("authorized_keys not found on root device at %s\n",
+            authorized_keys_path);
+        return send_simple_response(response, 500, "error",
+           "authorized_keys not found on root device");
+    }
+
+    // Re-partition device.
+    printf("repartitioning device %s\n", ROOT_DEVICE);
+    command = NULL;
+    asprintf(&command, "sgdisk -a 8192 -n 1:0:48M -N 2 %s", ROOT_DEVICE);
+    r = system(command);
+    if (r != 0)
+    {
+        printf("partitioning root device failed: return code %d\n", r);
+        return send_simple_response(response, 500, "error",
+           "partitioning root device failed");
+    }
+
+    // Inform kernel of partitioning changes.
+    printf("running partprobe\n");
+    command = NULL;
+    asprintf(&command, "partprobe");
+    r = system(command);
+    if (r != 0)
     {
-        printf("creating encrypted container failed: return code %d", r);
+        printf("partprobe: return code %d\n", r);
+        return send_simple_response(response, 500, "error",
+           "partprobe failed");
+    }
+    // Sleep for a little while.
+    // This seems necessary for the newly created partitions to appear as
+    // devices.
+    printf("waiting a bit...\n");
+    sleep(2);
+
+    // Create filesystem on the info partition.
+    printf("creating filesystem on info partition\n");
+    command = NULL;
+    asprintf(&command, "mkfs -t %s %s", FILESYSTEM_TYPE,
+        INFO_PARTITION_DEVICE);
+    printf("command: %s\n", command);
+    r = system(command);
+    if (r != 0)
+    {
+        printf("creating filesystem failed: return code %d\n", r);
+        return send_simple_response(response, 500, "error",
+           "creating filesystem inside encrypted container failed");
+    }
+
+    // Mount the info partition.
+    printf("mounting info partition\n");
+    r = temporary_mount(INFO_PARTITION_DEVICE, INFO_MOUNTPOINT,
+        FILESYSTEM_TYPE);
+    if (r != 0)
+    {
+        printf("mounting encrypted device failed: return code %d\n", r);
+        return send_simple_response(response, 500, "error",
+           "mounting encrypted root device failed");
+    }
+
+    // Create some directories in the info partition.
+    printf("creating directories in info partition\n");
+    command = NULL;
+    asprintf(&command, "mkdir -p %s%s %s%s", INFO_MOUNTPOINT,
+        AUTHORIZED_KEYS_DIR, INFO_MOUNTPOINT, SSH_HOST_KEY_DIR);
+    r = system(command);
+    if (r != 0)
+    {
+        printf("creating directories failed: return code %d\n", r);
+        return send_simple_response(response, 500, "error",
+           "creating directories in info partition failed");
+    }
+
+    // Copy authorized_keys file to the info partition.
+    printf("copying authorized_keys to info partition\n");
+    command = NULL;
+    asprintf(&command, "cp %s %s%s",
+        AUTHORIZED_KEYS_PATH, INFO_MOUNTPOINT, AUTHORIZED_KEYS_PATH);
+    r = system(command);
+    if (r != 0)
+    {
+        printf("copying authorized_keys failed: return code %d\n", r);
+        return send_simple_response(response, 500, "error",
+           "copying authorized_keys failed");
+    }
+
+    // Copy dropbear ssh host keys from the initrd to the info partition.
+    printf("copying dropbear ssh host keys\n");
+    command = NULL;
+    asprintf(&command, "cp /etc/dropbear/* %s%s/", INFO_MOUNTPOINT,
+        SSH_HOST_KEY_DIR);
+    r = system(command);
+    if (r != 0)
+    {
+        printf("copying dropbear ssh host keys failed: return code %d\n", r);
+        return send_simple_response(response, 500, "error",
+           "copying dropbear ssh host keys failed");
+    }
+
+    // Unmount info partition.
+    printf("unmounting info partition at %s\n", INFO_MOUNTPOINT);
+    r = umount(INFO_MOUNTPOINT);
+    if (r != 0)
+    {
+        printf("unmounting failed: return code %d\n", r);
+        return send_simple_response(response, 500, "error",
+           "unmounting configuration partition failed");
+    }
+
+    // Initialise encrypted container on data partition.
+    printf("creating encrypted container at %s\n", DATA_PARTITION_DEVICE);
+    r = create_encrypted_device(DATA_PARTITION_DEVICE, password);
+    if (r != 0)
+    {
+        printf("creating encrypted container failed: return code %d\n", r);
         return send_simple_response(response, 500, "error",
            "creating encryption container failed");
     }
 
     // Unlock the new container.
     printf("unlocking encrypted device\n");
-    r = encryption_unlock(CONTAINER_DEVICE, MAPPED_DEVICE_NAME, password);
-    if(r != 0)
+    r = encryption_unlock(DATA_PARTITION_DEVICE, MAPPED_DEVICE_NAME,
+        password);
+    if (r != 0)
     {
-        printf("unlocking encrypted container failed: return code %d", r);
+        printf("unlocking encrypted container failed: return code %d\n", r);
         return send_simple_response(response, 500, "error",
            "unlocking new encryption container failed");
     }
@@ -120,56 +248,61 @@ int callback_encryption_add(const struct _u_request * request,
     command = NULL;
     asprintf(&command, "mkfs -t %s %s", FILESYSTEM_TYPE, MAPPED_DEVICE_PATH);
     r = system(command);
-    if(r != 0)
+    if (r != 0)
     {
-        printf("creating filesystem failed: return code %d", r);
+        printf("creating filesystem failed: return code %d\n", r);
         return send_simple_response(response, 500, "error",
            "creating filesystem inside encrypted container failed");
     }
 
     // Mount the unlocked container.
     printf("mounting new filesystem\n");
-    r = temporary_mount(MAPPED_DEVICE_PATH, ENCRYPTED_MOUNTPOINT,
+    r = temporary_mount(MAPPED_DEVICE_PATH, DATA_MOUNTPOINT,
         FILESYSTEM_TYPE);
     if (r != 0)
     {
-        printf("mounting encrypted disk failed: return code %d", r);
+        printf("mounting encrypted device failed: return code %d\n", r);
         return send_simple_response(response, 500, "error",
-           "mounting encrypted root disk failed");
+           "mounting encrypted root device failed");
     }
 
     // Copy device contents from temporary filesystem to encrypted container.
-    printf("copying root disk contents from memory\n");
+    printf("copying root device contents from memory\n");
     command = NULL;
-    asprintf(&command, "rsync -a %s/ %s", TMP_LOCATION, ENCRYPTED_MOUNTPOINT);
+    asprintf(&command, "rsync -a %s/ %s", TMP_LOCATION, DATA_MOUNTPOINT);
     r = system(command);
-    if(r != 0)
+    if (r != 0)
     {
-        printf("copying from memory to encrypted disk failed: return code %d",
-            r);
+        printf("copying from memory to encrypted device failed:"
+            " return code %d\n", r);
         return send_simple_response(response, 500, "error",
-           "copying rootdisk contents from memory failed");
+           "copying root device contents from memory failed");
     }
 
-    // Unmount encrypted device.
-    printf("unmounting encrypted device at %s\n", ENCRYPTED_MOUNTPOINT);
-    r = umount(ENCRYPTED_MOUNTPOINT);
+    // Unmount filesystem on encrypted data partition.
+    printf("unmounting encrypted device at %s\n", DATA_MOUNTPOINT);
+    r = umount(DATA_MOUNTPOINT);
     if (r != 0)
     {
-        printf("unmounting encrypted disk failed: return code %d", r);
+        printf("unmounting encrypted device failed: return code %d\n", r);
         return send_simple_response(response, 500, "error",
-           "unmounting encrypted disk failed");
+           "unmounting encrypted device failed");
     }
 
     // Lock the container.
     printf("locking encrypted device\n");
     r = encryption_lock(MAPPED_DEVICE_NAME);
-    if(r != 0)
+    if (r != 0)
     {
-        printf("locking encrypted container failed: return code %d", r);
+        printf("locking encrypted container failed: return code %d\n", r);
         return send_simple_response(response, 500, "error",
            "locking container failed");
     }
 
-    return send_simple_response(response, 200, "status", "ok");
+    // Record that we want to reboot the machine.
+    *reboot = true;
+
+    r = send_simple_response(response, 200, "status", "ok");
+    stop_server();
+    return r;
 }
diff --git a/src/api/encryption_unlock.c b/src/api/encryption_unlock.c
index fbc7f790b229ae07c4c13877408bed34639a3025..fd20287806e66b2579528fae256760feaf02681d 100644
--- a/src/api/encryption_unlock.c
+++ b/src/api/encryption_unlock.c
@@ -18,8 +18,8 @@ int callback_encryption_unlock(const struct _u_request * request,
         return send_simple_response(response, 400, "error", "missing password");
     }
   
-    int unlock_status = encryption_unlock(CONTAINER_DEVICE, MAPPED_DEVICE_NAME,
-        password);
+    int unlock_status = encryption_unlock(DATA_PARTITION_DEVICE,
+        MAPPED_DEVICE_NAME, password);
   
     if (unlock_status == -1)
     {
diff --git a/src/auxiliary.c b/src/auxiliary.c
index fcbcde6bf3a2d194558401224ccd308d175660e8..6226e2a62e7e782c4c5c97c30be2d4c2d35635f6 100644
--- a/src/auxiliary.c
+++ b/src/auxiliary.c
@@ -131,3 +131,21 @@ int temporary_mount(char * device_path, char * mount_path,
         mount_flags, "");
     return r;
 }
+
+/**
+ * Reboot the system. We cannot simply use the `reboot` command because
+ * we're running as init (pid 0).
+ */
+void reboot_initrd()
+{
+    pid_t pid;
+    pid = vfork();
+    if (pid == 0)
+    {
+        // Child.
+        reboot(RB_AUTOBOOT);
+        _exit(EXIT_SUCCESS);
+    }
+    // Parent (init) waits.
+    while (1);
+}
diff --git a/src/cryptops-api.c b/src/cryptops-api.c
index ba0711d451b05c2beee495b4c3a8c39615009ec1..bd168686abfafefb94f0cd7a760803e5a7170f09 100644
--- a/src/cryptops-api.c
+++ b/src/cryptops-api.c
@@ -28,8 +28,9 @@ int main(int argc, char ** argv)
     instance.max_post_body_size = 1024;
 
     // Add api endpoints.
+    bool reboot = false;
     ulfius_add_endpoint_by_val(&instance, "POST", PREFIX, "/encryption/add",
-        0, &callback_encryption_add, NULL);
+        0, &callback_encryption_add, &reboot);
     ulfius_add_endpoint_by_val(&instance, "POST", PREFIX, "/encryption/unlock",
         0, &callback_encryption_unlock, NULL);
     ulfius_add_endpoint_by_val(&instance, "GET" , PREFIX, "/ssh/keys",
@@ -83,6 +84,13 @@ int main(int argc, char ** argv)
     
     ulfius_stop_framework(&instance);
     ulfius_clean_instance(&instance);
-    
+
+    // Check if the encryption/add said that we should reboot.
+    if (reboot)
+    {
+        printf("rebooting...");
+        reboot_initrd();
+    }
+
     return 0;
 }
diff --git a/src/encryption_functions.c b/src/encryption_functions.c
index 7f1f842a9d1c59490166850737a86e63c4fc135c..2a47b409af7e6f9903f6b6d546ed27fcc1fc5895 100644
--- a/src/encryption_functions.c
+++ b/src/encryption_functions.c
@@ -10,6 +10,14 @@
 static int container_initialise(struct crypt_device ** cd, const char * path,
      const bool debug)
 {
+    // Check if the device exists.
+    struct stat st = {0};
+    if (stat(path, &st) == -1)
+    {
+        printf("device does not exist: %s.\n", path);
+        return 1;
+    }
+
     // Let LUKS initialise the encrypted device.
     int r = crypt_init(cd, path);
     if (r < 0)
@@ -65,9 +73,10 @@ static int encryption_unlock(const char * path, const char * device_name,
     int r = container_initialise(&cd, path, true);
     if (r < 0)
     {
-        printf("crypt_load() failed on device %s.\n",
-            crypt_get_device_name(cd));
         crypt_free(cd);
+    }
+    if (r != 0)
+    {
         return r;
     }
 
diff --git a/src/includes/common-includes.h b/src/includes/common-includes.h
index b54967d00ee393e07612081f88f765adb3291033..262645452885db4ec261cd19aaa0130f5061653b 100644
--- a/src/includes/common-includes.h
+++ b/src/includes/common-includes.h
@@ -7,6 +7,8 @@
 #include <sys/statvfs.h>
 #include <linux/fs.h>
 #include <fcntl.h>
+#include <unistd.h>
+#include <sys/reboot.h>
 
 #define U_DISABLE_CURL
 #define U_DISABLE_WEBSOCKET
diff --git a/src/includes/settings.h b/src/includes/settings.h
index 12ee0fe6d87e515ba294728e08e9e7bc885a2d29..b9152495e10ec082612699939b1ed435b38383d5 100644
--- a/src/includes/settings.h
+++ b/src/includes/settings.h
@@ -1,12 +1,16 @@
 #define PREFIX "/cryptops/v0"
 #define PORT 8000
-#define CONTAINER_DEVICE "/dev/xvda1"
+#define ROOT_DEVICE "/dev/xvda"
+#define INFO_PARTITION_DEVICE ROOT_DEVICE "1"
+#define DATA_PARTITION_DEVICE ROOT_DEVICE "2"
 #define MAPPED_DEVICE_NAME "xvda1_crypt"
 #define MAPPED_DEVICE_PATH "/dev/mapper/" MAPPED_DEVICE_NAME
 #define FILESYSTEM_TYPE "xfs"
-#define MEMORY_USAGE 0.8
+#define MEMORY_USAGE 0.9
 #define UNENCRYPTED_MOUNTPOINT "/tmp/mnt-plain"
-#define ENCRYPTED_MOUNTPOINT "/tmp/mnt-encrypted"
+#define INFO_MOUNTPOINT "/tmp/mnt-info"
+#define DATA_MOUNTPOINT "/tmp/mnt-data"
 #define TMP_LOCATION "/tmp/" MAPPED_DEVICE_NAME
 #define AUTHORIZED_KEYS_DIR "/root/.ssh"
 #define AUTHORIZED_KEYS_PATH AUTHORIZED_KEYS_DIR "/authorized_keys"
+#define SSH_HOST_KEY_DIR "/dropbear"
\ No newline at end of file