diff --git a/src/api/encryption_init_post.c b/src/api/encryption_init_post.c
index aeef25d1a835ff05c8e3cda53527521707ff8073..0b95fafc30f25e889a41a58f263bd334909ace32 100644
--- a/src/api/encryption_init_post.c
+++ b/src/api/encryption_init_post.c
@@ -78,7 +78,7 @@ int callback_encryption_init_post(const struct _u_request * request,
     asprintf(&command, "rsync -a %s/ %s", UNENCRYPTED_TMP_MOUNTPOINT,
         TMP_LOCATION);
     r = system(command);
-    if(r != 0)
+    if (r != 0)
     {
         printf("copying root device contents into memory failed"
             ": return code %d\n", r);
diff --git a/src/api/ssh_keys_post.c b/src/api/ssh_keys_post.c
new file mode 100644
index 0000000000000000000000000000000000000000..08fd28f2628463ca8530e238beb4f3f434974e24
--- /dev/null
+++ b/src/api/ssh_keys_post.c
@@ -0,0 +1,55 @@
+/**
+ * Callback function that appends an SSH key tot the list of keys authorised for
+ * access to the initrd.
+ *
+ * Example output:
+ * {"ssh-keys":{"1":"ssh-rsa AAAAB3... example@example.com",
+ * "2":"ssh-rsa AAAAB3...","5":"command=\"/usr/bin/cryptops-client\" ssh-rsa
+ *  AAAAB3... cryptops-test@greenhost"}}
+ *
+ * The indices correspond to line numbers of the authorized_keys file.
+ * Missing indices (like 3 and 4 in the example) arise from empty lines in the
+ * file; those are creted when keys are deleted.
+ *
+ * @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
+ * @return                internal status code
+ */
+int callback_ssh_keys_post(const struct _u_request * request,
+    struct _u_response * response, void * user_data)
+{
+    // Open file with append mode
+    FILE * authorized_keys = fopen(AUTHORIZED_KEYS_PATH, "a");
+
+    // Check if that succeeded.
+    if (authorized_keys == NULL)
+    {
+        printf("Could not open authorized_keys file for writing\n");
+        return send_simple_response(response, 500, "error",
+            "error opening authorized_keys");
+    }
+
+    // Read in json request body.
+    json_t * json_input = ulfius_get_json_body_request(request, NULL);
+
+    // Read SSH key from request.
+    const char * ssh_key;
+    ssh_key = json_string_value(json_object_get(json_input, "ssh-key"));
+    if (ssh_key == NULL)
+    {
+        return send_simple_response(response, 400, "error", "missing ssh-key");
+    }
+
+    char * ssh_key_with_command;
+
+    add_ssh_command(&ssh_key_with_command, ssh_key);
+
+    asprintf(&ssh_key_with_command, "%s\n", ssh_key_with_command);
+
+    // Write SSH key to file
+    fprintf(authorized_keys, ssh_key_with_command);
+    fclose(authorized_keys);
+
+    return send_simple_response(response, 200, "status", "ok");
+}
diff --git a/src/auxiliary.c b/src/auxiliary.c
index afa4ff6001f7ebc62e28161883fd667af7cdd0c0..db1f7af3102e10c382acff61258b17dc3a222ad8 100644
--- a/src/auxiliary.c
+++ b/src/auxiliary.c
@@ -12,36 +12,56 @@ void stop_server()
 }
 
 /**
- * Read a file completely into a string.
- * @param  filename Path to the file to read.
- * @return          Contents of the file.
+ * Read the contents of an already opened file into a string
+ * @param   file    The file as opened by fopen with "rb"
+ * @return          Contents of the file
  */
-char * read_file(const char * filename)
+char * read_from_file(FILE * file)
 {
-    char * buffer = NULL;
-    long length;
-    FILE * file = fopen(filename, "rb");
-    if (filename != NULL)
+    char buf[100];
+    char * str = NULL;
+    char * temp = NULL;
+    // start with size of 1 to make room for null terminator
+    unsigned int size = 1;
+    unsigned int strlength;
+    if (file)
     {
-        if (file)
+        while (fgets(buf, sizeof(buf), file) != NULL)
         {
-            fseek(file, 0, SEEK_END);
-            length = ftell(file);
-            fseek(file, 0, SEEK_SET);
-            buffer = o_malloc(length + 1);
-            if (buffer)
+            strlength = strlen(buf);
+            // allocate room for the buf that gets appended
+            temp = realloc(str, size + strlength);
+            if (temp == NULL)
+            {
+                printf("Could not allocate memory for file reading\n");
+                return NULL;
+            }
+            else
             {
-                fread(buffer, 1, length, file);
+                str = temp;
             }
-            buffer[length] = '\0';
-            fclose (file);
+            // append buffer to str
+            strcpy(str + size - 1, buf);
+            size += strlength;
         }
-        return buffer;
+        pclose(file);
     }
-    else
+    return str;
+}
+
+/**
+ * Read a file completely into a string.
+ * @param  filename Path to the file to read.
+ * @return          Contents of the file.
+ */
+char * read_file(const char * filename)
+{
+    if (filename != NULL)
     {
-        return NULL;
+        FILE * file = fopen(filename, "rb");
+        return read_from_file(file);
     }
+    return NULL;
 }
 
 /**
@@ -201,6 +221,21 @@ int parse_int(const char * input, int * result)
 }
 
 /**
+ * Add the SSH_COMMAND string in front of ssh_key unless it's already there
+ * because people have seen it being used in ssh_keys_list.
+ * @param[out]  ssh_key_with_command    the ssh_key with the command prepended
+ *                                      if needed
+ * @param[in]   ssh_key                 a valid ssh key string
+ */
+int add_ssh_command(char ** ssh_key_with_command, const char * ssh_key)
+{
+    if (strncmp(SSH_COMMAND, ssh_key, strlen(SSH_COMMAND)) != 0)
+        return asprintf(ssh_key_with_command, "%s %s", SSH_COMMAND, ssh_key);
+    else
+        return asprintf(ssh_key_with_command, "%s", ssh_key);
+}
+
+/*
  * Check if the given path already exists (as a (special) file or directory).
  * @param  path  Path to test.
  * @return       `true` if path exists, `false` otherwise.
diff --git a/src/cryptops-api.c b/src/cryptops-api.c
index 114850423a3f74cb710a1a3edb661e0f6160b9d7..ffbc915b82a7fb604da6d7c1c47c87a2187ce497 100644
--- a/src/cryptops-api.c
+++ b/src/cryptops-api.c
@@ -12,6 +12,7 @@
 #include <api/encryption_unlock_post.c>
 #include <api/encryption_keys_put.c>
 #include <api/ssh_keys_get.c>
+#include <api/ssh_keys_post.c>
 
 int main(int argc, char ** argv)
 {
@@ -57,6 +58,9 @@ int main(int argc, char ** argv)
     ulfius_add_endpoint_by_val(&instance, "GET" , PREFIX,
         "/ssh/keys",
         0, &callback_ssh_keys_get, NULL);
+    ulfius_add_endpoint_by_val(&instance, "POST" , PREFIX,
+        "/ssh/keys",
+        0, &callback_ssh_keys_post, NULL);
 
     // Add default endpoint.
     ulfius_set_default_endpoint(&instance, &callback_default, NULL);
@@ -84,7 +88,7 @@ int main(int argc, char ** argv)
         y_log_message(Y_LOG_LEVEL_DEBUG, "Start %sframework on port %d",
             ((argc == 4 && strcmp("-secure", argv[1]) == 0) ? "secure " : ""),
             instance.port);
-        
+
         // Wait for signal from fifo to quit.
         y_init_logs("cryptops-api", Y_LOG_MODE_CONSOLE, Y_LOG_LEVEL_DEBUG,
             NULL, "Waiting for fifo signal to quit");
@@ -107,7 +111,7 @@ int main(int argc, char ** argv)
     sleep(1);
     
     y_close_logs();
-    
+
     ulfius_stop_framework(&instance);
     ulfius_clean_instance(&instance);
 
diff --git a/src/includes/settings.h b/src/includes/settings.h
index 8035b1024dfa8b91d5fb4c76c4f878f682ad9266..83ae0fab0d5650a1ad746db0d0288b18ae4a6407 100644
--- a/src/includes/settings.h
+++ b/src/includes/settings.h
@@ -29,3 +29,7 @@
 #define AUTHORIZED_KEYS_DIR "/root/.ssh"
 #define AUTHORIZED_KEYS_PATH AUTHORIZED_KEYS_DIR "/authorized_keys"
 #define SSH_HOST_KEY_DIR "/dropbear"
+
+// Ssh authorized_keys settings.
+// This string is prepended to new and converted authorized_keys.
+#define SSH_COMMAND "command=\"cd / && /usr/bin/cryptops-client\""