Two directories that look similar in a tutorial do completely different jobs. One holds the certificate authority: its private key, its serial counter and the record of everything it has signed. The other holds what the daemon needs to start and serve clients. Putting both on the same host under the same account is convenient for an afternoon and expensive for the rest of the deployment's life, because the daemon then runs beside the one key that can mint any identity it wants.

What the CA workspace contains

A PKI directory is issuer state, not configuration. It carries the CA private key and certificate, a serial file, an index of issued certificates, and the per-identity material that has been produced from them.

Signing a request changes that state, which is why the workspace belongs to an administrator-controlled account on a host where the VPN service does not run. Anyone who can read the CA private key can issue a certificate the server will trust, so the key's protection is the whole trust model in one file. Copying it to a second location to save a step creates a second thing to protect and a second thing to forget. Every signature also increments the serial and appends an entry to the index, which is why the workspace is one copy of state rather than a folder of files.

The public CA certificate is different. It is meant to be distributed, and it is what clients and servers use to verify each other.

What the daemon reads when it starts

A running server consumes a small set: its own certificate, its own private key, the CA certificate for verifying peers, and whatever keying material its chosen mode requires. It reads those paths at startup and again on reload.

Ownership has to be evaluated against the unit that actually launches, not against an interactive root shell. Declared sandboxing can make part of the filesystem read-only or invisible even when a manual test as root succeeds.

systemctl show -p User -p Group -p ReadOnlyPaths [email protected]
stat -c '%a %U:%G' /etc/openvpn/server/server.key
runuser -u openvpn -- test -r /etc/openvpn/server/server.key; echo $?

That third line is the one people skip. It asks the daemon's own account whether it can read the key, which is the only version of the question that matters once privilege has been dropped. A zero exit with root tells you nothing about what happens after the drop.

The two fault paths are worth separating before you change any permission. A signing failure points at the PKI directory, the search permission on its parent directories and the account running the issuer. A startup failure points at the unit, its working directory and the paths named in the server configuration. Making the whole tree world-readable fixes neither of them, and it removes the boundary both depend on.

Why copying the CA key to the server fails later

The copy usually starts as a debugging move: someone wants to renew a client on the VPN host, so the CA key lands in /etc/openvpn and the renewal works. The immediate task succeeds, and the boundary is gone.

Then the server gets backed up, and the signing authority joins the backups. A snapshot, a support bundle or a copy of the configuration directory now carries the ability to issue trusted identities for as long as the CA is valid. Whoever holds that copy can mint a certificate for any name the server accepts, including names that were never issued. The only record of that issuance is the one they choose to keep.

Recovering from that state is not a matter of deleting a file. You have to decide whether the key was exposed, rotate the CA if it was, and redistribute trust to every peer. A separate workspace avoids the whole conversation.

Accounts, directories, backups

Give the issuer its own account and home directory, kept off the VPN host where that is practical. Give the daemon a different account, with read access to the deployed material and write access to nothing that issues certificates. Deploy by copying public certificates outward and never by pulling private issuer state inward. Back up the two roles separately, because their sensitivity and their restore stories differ.

After a revocation, update the CRL file that the server configuration names, then reload the service so new connections read it. The Easy-RSA documentation covers the workspace layout and signing workflow; the ownership rules around it remain a decision about your host. Confirm what the service loaded with openssl crl -in /etc/openvpn/crl.pem -noout -lastupdate -nextupdate instead of assuming the reload picked it up.

A test that proves the split

Check the negative case, not just the working one. Sign a certificate from the issuer account as designed, then confirm the same account cannot start the service or read the server's private key. Then confirm the daemon's account cannot read the CA private key.

Those three checks take a few minutes and survive staff changes, because they are statements about permissions rather than about habit. Write the result down with the paths and accounts it covered, plus the date you ran them. The next person inheriting this deployment will otherwise re-derive the boundary from a tutorial that never had one. A dated record is also what makes the next review take minutes instead of an afternoon.

সম্পৰ্কিত প্ৰবন্ধ