How to add an SSH Key as a Kubernetes Secret

by Jannik Arndt

Adding an ssh-file as a secret sounds easy, but there are pitfalls.

Step 1: Add secret to kubernetes

First, add the key as a secret, for example with terraform

resource "kubernetes_secret" "ssh_key_verstehensystem_csv_ingest_bwh" {
  metadata {
    name      = "my-ssh-key"

  data {
    "id_rsa" = "${file("id_rsa")}"

  type = "Opaque"

(see Docs) or with kubectl:

$ kubectl create secret generic my-ssh-key --from-file=id_rsa=/path/to/local-ssh-keys

(see Docs). Note that this command renames the file: --from-file=<name on the cluster>=<local file>.

Step 2: Mount the secret

Now, in your pod, mount the secret as a volume:

kind: Pod
apiVersion: v1
  name: ...
  - name: ...
    image: ...
    - name: ssh-key-volume
      mountPath: "/etc/ssh-key"
  - name: ssh-key-volume
      secretName: my-ssh-key
      defaultMode: 256

Step 3: Do’s and Dont’s

Mount to ~/.ssh/

Remember that mounting to an existing directory will overwrite it. Even if .ssh does not exist, it will be replaced by a read-only mount, so ssh will fail when it creates the known_hosts file.

Besides, writing ~ in your yaml will most likely create a folder called '~'. You need absolute paths!

Forget the defaultMode

ssh checks the key’s file permissions and will fail if they are too broad. Since the volume is read-only, you cannot simply chmod after the fact, you need to set the permissions in your yaml. But beware…

Write POSIX in defaultMode

The docs state:

Note that the JSON spec doesn’t support octal notation, so use the value 256 for 0400 permissions. If you use yaml instead of json for the pod, you can use octal notation to specify permissions in a more natural way.

In my experience, the yaml spec also does not support octal notation, so you need to convert:

400 = (4 * 8^2) + (4 * 8^1) + (4 * 8^0) = (4 * 64) + (0 * 8) + (0 * 1) = 256 + 0 + 0 = 256


I recently created a wonderful bug.

This is a basic example how to implement oAuth2 using Akka HTTP and Scala. It provides three endpoints. From the clients point of view:

  • / — publicly accessible, returns “Welcome!”,
  • /auth — provide your username and password, receive an access_token in return,
  • /api — secured by oAuth, send the access_token in a header to gain access.

From the server’s point of view:

  • / — publicly accessible, do nothing,
  • /auth — receive basic auth credentials, verify they’re in the list of known credentials, create an access_token, return it,
  • /api — receive authorization header, check if access_token is in list of valid tokens.

Since oAuth tokens are short lived, the server also has to invalidate expired tokens.

Getting a Akka HTTP-based backend up and running on Heroku for free can be done in less then 30 minutes — if you know the tricks.