The message says OpenVPN cannot load an inline certificate, and the filename cached in your head says otherwise. What the parser received matters more than what the file system contains, because the cert directive accepts two completely different kinds of value. One is a path it opens; the other is PEM text that arrived inside the configuration. Until you know which shape the running client was given, every fix is a guess.

Two storage shapes, one directive

The cert, key and ca directives each accept a path or an inline block. When the value is a path, OpenVPN opens that file and reads the object from disk. When the configuration contains a block delimited by cert tags, the same directive consumes the content between those tags instead, and no separate file is involved.

Both shapes produce the same kind of object at the end, which is why a working deployment can move between them without any other change. A profile that carries an embedded client certificate and private key is self-contained, and copying it to another machine works without also copying a certificate directory.

The reverse is not true. Dropping client.crt next to a profile that embeds its own data changes nothing, because nothing in the configuration refers to that file. This is the single most common reason a file that clearly exists appears to be ignored.

How an inline block turns into an object

Inline content is extracted from the configuration and handed to the PEM parser as text. That parser expects the usual boundaries: a BEGIN line, base64 payload, and a matching END line. If the block was truncated by a failed copy, wrapped in HTML by a download page, or opened in an editor that normalized the dashes, the parser fails on content that looks present.

<cert>
-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----
</cert>

That is also why the error wording is misleading. The word inline describes where the loader looked, not what it found there. A file named in a config and an object embedded in it can produce the same complaint when the underlying bytes are unusable.

Check which shape the loaded profile actually uses rather than which file your editor happened to open:

grep -nE '^(ca|cert|key) |^<(ca|cert|key)>' client.ovpn

How a path reference is resolved

A path value is opened relative to the client's working directory, not to the directory containing the configuration. Under systemd that working directory is whatever the unit sets, and an interactive run from your shell inherits something else entirely. This is why the same configuration file can work when you test it by hand and fail as a service.

Relative paths inherit the same ambiguity. When you see a bare filename, ask what the process's current directory is in production rather than assuming it matches your terminal.

For a certificate stored separately, an offline parse confirms the object before you debug anything above it:

openssl x509 -in client.crt -noout -subject -issuer -dates
openssl pkey -in client.key -noout -check

Those commands prove the files are readable and structurally valid. They do not prove that the peer trusts the issuer, that the certificate is still inside its validity window, or that the key belongs with it.

What the parser error can and cannot tell you

A parse failure localizes the problem to one input and one stage. It does not tell you which of the two storage shapes the client used, and it does not tell you whether the object would have been accepted. Those are separate questions with separate evidence.

Once parsing succeeds, the next failure belongs to a later stage. A trust rejection, a purpose mismatch or a key mismatch is reported by the peer or by the TLS layer, not by the loader. Replacing the same file repeatedly will not move that error.

Keep the sensitive half out of public reports while you investigate. Share the directive names, the error text and the structure of the block, with the key material and any identifying payload removed. The openvpn(8) manual documents both forms of the file directives and the working-directory behaviour behind them.

Ingingo zihuye