Kubernetes
SSH
Secrets
Key Management
DevOps

Creating ssh secrets key file in kubernetes

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

If a pod needs an SSH private key, the clean Kubernetes approach is to store that key in a Secret and mount it as a file. The built-in secret type kubernetes.io/ssh-auth exists specifically for this use case and gives the key a conventional field name.

Use the SSH Secret Type

Kubernetes supports a dedicated secret type for SSH credentials:

yaml
1apiVersion: v1
2kind: Secret
3metadata:
4  name: git-ssh-key
5type: kubernetes.io/ssh-auth
6stringData:
7  ssh-privatekey: |
8    -----BEGIN OPENSSH PRIVATE KEY-----
9    ...
10    -----END OPENSSH PRIVATE KEY-----

Two details matter here:

  • the type is kubernetes.io/ssh-auth
  • the data key is ssh-privatekey

Using stringData is convenient because Kubernetes handles the base64 encoding for you.

Mount the Secret as a File

Most SSH tools expect a real file, not an environment variable. Mount the secret into the container:

yaml
1apiVersion: v1
2kind: Pod
3metadata:
4  name: ssh-client
5spec:
6  containers:
7    - name: app
8      image: alpine:3.20
9      command: ["sleep", "3600"]
10      volumeMounts:
11        - name: ssh-key
12          mountPath: /root/.ssh
13          readOnly: true
14  volumes:
15    - name: ssh-key
16      secret:
17        secretName: git-ssh-key
18        defaultMode: 0400

That gives the container a file at /root/.ssh/ssh-privatekey.

If the container does not run as root, adjust the mount path to the actual home directory of the application user. The important part is not the exact path but that the SSH client can read the key file with suitably strict permissions.

If your tool expects a specific filename such as id_rsa, use items:

yaml
1volumes:
2  - name: ssh-key
3    secret:
4      secretName: git-ssh-key
5      defaultMode: 0400
6      items:
7        - key: ssh-privatekey
8          path: id_rsa

known_hosts Is a Separate Concern

The private key is only part of SSH trust. You should also provide known_hosts so the container can verify the server it connects to.

Example:

yaml
1apiVersion: v1
2kind: ConfigMap
3metadata:
4  name: ssh-known-hosts
5data:
6  known_hosts: |
7    github.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAI...

Then mount it into /root/.ssh/known_hosts or the equivalent path for the running user.

Without known_hosts, people often disable host checking. That works, but it weakens SSH security in exactly the place it is supposed to protect.

In production, that shortcut is hard to justify. A pinned known_hosts entry is usually a better operational tradeoff than turning off host verification.

Command-Line Creation

If you already have a private key file, kubectl can create the secret directly:

bash
kubectl create secret generic git-ssh-key \
  --type=kubernetes.io/ssh-auth \
  --from-file=ssh-privatekey=$HOME/.ssh/id_rsa

This is convenient for manual setup, though manifest-based configuration is usually easier to review and reproduce in GitOps workflows.

Security Notes

Secrets are safer than hardcoding keys in images, but they are not magical. Kubernetes documentation explicitly warns that secrets are not encrypted in etcd by default unless cluster encryption at rest is configured.

That means you still need:

  • RBAC controls
  • namespace hygiene
  • secret rotation
  • minimal pod access

If a pod can read the secret, treat that pod as trusted.

Common Pitfalls

The most common mistake is using a generic Opaque secret with ad hoc keys when the built-in SSH type already exists. The built-in type makes the intent clearer.

Another mistake is mounting the key with permissive file modes. SSH clients may reject keys that are too open.

A third issue is forgetting known_hosts and then disabling host verification as a quick workaround.

Summary

  • Use type: kubernetes.io/ssh-auth with the ssh-privatekey field for SSH credentials.
  • Mount the secret as a file, not as an environment variable.
  • Set restrictive permissions such as 0400.
  • Provide known_hosts separately so SSH can verify the remote host.
  • Remember that Kubernetes Secrets still need RBAC and cluster-level security controls.

Course illustration
Course illustration

All Rights Reserved.