Certificates can sit in the correct directory with a readable mode and root ownership, and the service can still report that it cannot open the file. On an SELinux system that combination points at one specific mechanism rather than at permissions. The label travelled with the file, because a rename does not create a new object. The inode kept the security context it had at the old path, and the policy for the new path never got a chance to assign its own.

What a rename actually does to a label

A file carries its SELinux context as attribute data attached to the inode. Renaming inside one filesystem changes the directory entry and nothing else, which is fast, atomic, and the reason the context survives the move. No policy is consulted, no default is applied, and no warning is printed.

Copying behaves differently. A copy creates a new inode in the destination directory, and the policy assigns a context from that directory's type, so a copied certificate usually ends up correctly labelled while a moved one stays wrong. That single difference explains most of the confusion in this class of ticket.

Cross-filesystem moves fall back to copy semantics, so the same command can behave differently on two machines depending on whether /etc lives on its own volume. Check that before you conclude the tool is unreliable. One look at the mount table tells you which kind of move you performed.

Read the current label against the expected one

Three read-only commands answer the question without changing anything. The first shows what the file has now, the second reports what policy expects for that exact path, and the third lists every file under the directory whose label differs.

ls -lZ /etc/openvpn/client/office-ca.crt
matchpathcon /etc/openvpn/client/office-ca.crt
restorecon -Rn -v /etc/openvpn/client

The dry run is the one to trust, because it names each file whose context departs from policy and still leaves the system untouched. If the certificate appears in that list, you have found the discrepancy between what the path means and what the file claims. If it does not appear, the label is already what policy wants and your time belongs somewhere else.

Then correlate the difference with an actual denial. A mismatch is evidence of a mislabel, not proof that the service failed because of it, and a fix applied without a corresponding denial in the log is a guess with extra steps.

Restore the mapping instead of inventing an exception

For a standard location the policy already maps the path, so restorecon applies it and the work is done. Keep the scope to the directory you are repairing; relabelling the whole filesystem is slow, disruptive, and it buries the original mistake under a very large change.

For a custom directory the order matters, and reversing it produces a command that reports success while changing nothing. The mapping belongs in policy, the relabel belongs at the end, and the dry run belongs before both. Skipping that last part is how a path that was never wrong gets relabelled anyway.

semanage fcontext -a -t openvpn_etc_t '/etc/openvpn/custom(/.*)?'
restorecon -Rv /etc/openvpn/custom

restorecon applies a mapping; it cannot invent one. If no rule describes the path, there is nothing to restore from, which is why the persistent mapping has to exist before the relabel. Record which configuration owns that mapping, because a later move, a package update or a relabel otherwise recreates the fault and the next person starts from zero.

Why chcon is not the fix

chcon writes a context directly onto the file. It takes effect immediately and it is the least durable option available, because a filesystem relabel reapplies policy and discards manual changes without asking. The file looks repaired and the repair has an expiry date nobody wrote down. What you want instead is a rule describing the path, so every file that arrives there gets the same treatment automatically.

Worse, it teaches the wrong lesson: the underlying mapping is still missing, so the failure returns weeks later with no obvious trigger and no memory of the workaround. Use chcon only as a temporary experiment to confirm a hypothesis, then replace it with a mapping that survives the next relabel, and check that the replacement is actually in place.

When the label is right and access still fails

Start with the parent directories. Traversal permission is checked on every component of the path, so a correctly labelled certificate inside a directory the service cannot enter is still unreadable. SELinux and ordinary permission both have to allow each step, and fixing one does not fix the other.

Then check process identity and the service's own sandboxing. A unit with a restrictive sandbox can deny access to a file that the policy would happily allow, and from the log line the two causes look identical. Confirm which process is actually asking, not which one you assume is asking.

Remember that dontaudit rules can suppress denial messages, so an empty audit log is weak evidence rather than proof. If policy looks right and access still fails, investigate before generating a broad allow module, and do not disable SELinux to make the symptom disappear. Both shortcuts produce a system that appears to work and a security posture nobody can describe. A short investigation beats either one.

Artitgels cun il medem tema