Skip to main content
RunBook Academy

Proxmox VEVIII · CephCeph security

Ceph authentication: cephx, keyrings and capabilities

Advanced⏱ ~26 mincephrbd

What you'll learn

  • Explain what cephx authenticates, and what it deliberately does not protect
  • Read a capability string and predict what a client holding it can do
  • Create a least-privilege client for one pool and verify the restriction actually holds
  • Recover from a capability edit that locked a client out

Prerequisites

Verified against Proxmox VE 9.2.4 · Proxmox Backup Server 4.2.5 · Ceph Squid / Tentacle · Debian 13 (Trixie) · Linux kernel 7.0 (PVE 9.2 default) · 2026-08-12

Not yet marked complete on this device.

pveceph init turns cephx on. It has been on in every Proxmox cluster you have ever built, and unless you went looking, every one of those clusters authenticates every client as client.admin — a user whose capability string is allow * on the monitors, the OSDs and the managers.

That is not a misconfiguration. It is the default, and for a hyper-converged cluster where the only clients are the Proxmox nodes themselves it is a defensible one. It stops being defensible the moment something that is not a Proxmox node needs a pool: a Kubernetes CSI driver, a second cluster, a backup appliance, a colleague who wants to mount CephFS from a workstation. At that point the question “what exactly can this key do” has an answer, and the answer is usually “everything”.

This lesson makes that question answerable.

What cephx is, and the thing it is not

cephx is mutual authentication using shared secrets. Every entity — each daemon and each client — has a name (client.admin, osd.4, mgr.pve1) and a secret key. The monitors hold a copy of every key. A client proves it knows its key, receives a time-limited ticket, and presents that ticket to the OSDs it wants to talk to.

Three settings control whether any of this is required, and all three default to cephx:

SettingDefaultWhat it requires
auth_cluster_requiredcephxDaemons authenticate to each other
auth_service_requiredcephxClients authenticate to the cluster
auth_client_requiredcephxThe cluster authenticates to the client

The alternative value is none, and the third row is the one people forget: cephx is mutual, so a client can also detect that it is talking to an impostor cluster.

Reading a capability string

A cephx user is a name plus a set of capabilities, one per daemon type. The grammar is small enough to learn in one sitting, and learning it is what turns allow rwx pool=vmdata from noise into a sentence.

TokenGrants
rRead
wWrite to objects
xExecute class methods, and use auth operations
* (or all)Read, write, execute, plus administrative commands
class-readRead-only class methods (a subset of x)
class-writeWrite-only class methods (a subset of x)

Two restrictions narrow the scope: pool=<name> limits a capability to one pool, and namespace=<name> limits it further to one namespace inside a pool. Written as shell, that is pool=vmdata — a literal, not a placeholder.

On top of the letters, Ceph ships profiles: named bundles that express an intent rather than a permission set. profile rbd is the right capability for an RBD client and is far harder to get subtly wrong than assembling class-read object_prefix rbd_children, rwx by hand. profile rbd-read-only is its read-only counterpart, and profile rbd-mirror is what the mirroring daemon needs.

Read-only / Saferead every user and capability in the cluster
ceph auth ls
Read-only / Safe
$ ceph auth get client.admin
[client.admin]
key = REDACTED
caps mds = "allow *"
caps mgr = "allow *"
caps mon = "allow *"
caps osd = "allow *"

Illustrative output

Read that as: this key can create and destroy pools, read and write every object in all of them, remove OSDs from the CRUSH map, and edit the authentication database — including its own capabilities. There is no Ceph operation it cannot perform.

The least-privilege client, end to end

Suppose an application team wants RBD images in a pool of their own, from hosts that are not Proxmox nodes. The whole exchange is four commands.

Configuration changecreate a pool-scoped RBD client
POOL=app-images
CLIENT=app-team

pveceph pool create "$POOL" --size 3 --min_size 2 --application rbd

ceph auth get-or-create "client.$CLIENT" \
mon "profile rbd" \
osd "profile rbd pool=$POOL" \
mgr "profile rbd pool=$POOL"
Read-only / Safe
$ ceph auth get-or-create client.app-team mon 'profile rbd' osd 'profile rbd pool=app-images'
[client.app-team]
key = REDACTED

Illustrative output

Then hand it over — and hand over only the key, not ceph auth ls:

Read-only / Safeexport just this client's keyring
CLIENT=app-team
ceph auth get "client.$CLIENT" -o "/root/ceph.client.$CLIENT.keyring"

# just the secret, for tooling that wants the bare string
ceph auth print-key "client.$CLIENT"

Verification that can fail

This is the part people skip, and it is the only part that proves anything. A capability string that looks restrictive and is not is worse than no restriction, because it is documented as a control.

Read-only / Safeprove the restriction holds
POOL=app-images
OTHER=vmdata
CLIENT=app-team
KEYRING="/root/ceph.client.$CLIENT.keyring"

# must succeed
rbd --id "$CLIENT" --keyring "$KEYRING" ls "$POOL"

# must fail: operation not permitted
rbd --id "$CLIENT" --keyring "$KEYRING" ls "$OTHER"

# must fail: no administrative capability
ceph --id "$CLIENT" --keyring "$KEYRING" osd pool ls
Read-only / Safe
$ rbd --id app-team --keyring /root/ceph.client.app-team.keyring ls vmdata
rbd: error opening pool 'vmdata': (1) Operation not permitted

Illustrative output

Note the shape of the error. Ceph reports a scope violation as (1) Operation not permitted, not as “pool not found” — so a capability that is too narrow and a pool name that is misspelled produce different errors. That distinction saves ten minutes every time.

Where Proxmox keeps the keys

pveceph init writes the cluster configuration to /etc/pve/ceph.conf and, in the documentation’s words, “also creates a symbolic link at /etc/ceph/ceph.conf, which points to that file”. The consequence is worth stating: the Ceph configuration is in pmxcfs, so it is cluster-replicated, and it stops being writable when the cluster loses quorum.

The keyrings follow the same pattern. On a pveceph-managed cluster the admin keyring lives under /etc/pve/priv/, and each storage entry that talks to a Ceph cluster Proxmox does not manage gets its own keyring at /etc/pve/priv/ceph/<STORAGE_ID>.keyring. That file name is the storage ID from /etc/pve/storage.cfg, not the Ceph user name — a detail that makes external-cluster storage fail in a confusing way when somebody renames the storage.

Read-only / Safefind every Ceph credential on a node
ls -l /etc/ceph/
ls -l /etc/pve/priv/ 2>/dev/null | grep -i ceph
ls -l /etc/pve/priv/ceph/ 2>/dev/null

Turning cephx off is not a troubleshooting step

pveceph init accepts --disable_cephx, and it exists for closed lab networks. It is the wrong response to an authentication problem, for three reasons worth being specific about.

It is not a per-client switch. Authentication is a cluster property. Turning it off removes authentication for every client, every daemon and every pool at once.

Everything on the storage network becomes trusted. Without cephx, any host that can route to the monitors can read and write every pool. There is no second control behind it — Ceph has no pool-level ACL that survives the loss of authentication.

It is not a clean toggle on a running cluster. Flipping the auth_* settings needs a restart of every daemon, and the window in between has daemons on both sides of the change failing to talk to each other. A cluster that was struggling is now down.

If the authentication is genuinely broken, the fix is in the keyring or the clock. Both are in the diagnostic order above.

Common mistakes

  • Handing out client.admin because it is what is already in /etc/pve/priv. It is the easiest key to copy and the worst one to give away. Five seconds of ceph auth get-or-create produces a scoped one.
  • Assuming cephx encrypts. It authenticates. Encryption is msgr2 secure mode, and the default negotiation prefers the unencrypted crc mode.
  • Using ceph auth caps to add a capability. It replaces the whole set. Read the current caps first, edit, then apply all of them.
  • Building the capability by hand when a profile exists. profile rbd is maintained upstream and changes when RBD needs new object prefixes. A hand-built equivalent silently stops working after an upgrade.
  • Scoping the osd capability to a pool and leaving mon at allow *. The data is protected and the cluster is not. Both lines need scoping.
  • Never testing the restriction. A capability is a claim until a denied command proves it.
  • Leaving a delivered keyring in /etc/pve/priv. It replicates to every node and lands in every configuration backup.

Key takeaways

  • cephx is on by default in Proxmox and authenticates every client; the default client is client.admin with allow * everywhere.
  • cephx does not encrypt. msgr2 secure mode does, and the default crc secure ordering means a stock cluster is unencrypted on the wire.
  • Capabilities are per daemon type. Use profile rbd and scope it with pool=; scope the mon capability too, not just osd.
  • ceph auth caps overwrites. Back up the existing caps before you run it, and keep a break-glass admin off the cluster.
  • Proxmox keeps per-storage keyrings at /etc/pve/priv/ceph/<STORAGE_ID>.keyring, named after the storage ID.
  • Prove a restriction with a command that must be denied. Untested least privilege is a comment, not a control.

Knowledge check

Knowledge check · 4 questions

  1. Q1. A security review asks whether Ceph replication traffic between OSDs is protected from an attacker with a span port on the storage switch. The cluster is a default pveceph install with cephx enabled. What is the accurate answer?

  2. Q2. You run: ceph auth caps client.backup osd "profile rbd pool=backups". The user previously had both a mon and an osd capability and worked correctly. It now cannot connect at all. Why?

  3. Q3. You have created client.app-team with mon "profile rbd" and osd "profile rbd pool=app-images". Which checks would actually demonstrate that the restriction holds? Select all that apply.

  4. Q4. When authentication starts failing for clients on one node while the rest of the cluster is healthy, the keyring is the first thing to check.

Passing score: 75%. Answers are checked in this browser.