A profile that used to start now fails with an options error, and the line the parser quotes looks perfectly reasonable on screen. That is the trap: a configuration file is a list of physical lines, each holding one option keyword and its arguments, and a long line wrapped by an editor looks identical to two lines until you look at the bytes. Nothing about the network, the certificate or the tunnel is involved in this class of failure. Two lines that look identical on screen can differ by a single byte.

Work the checks below in order and stop at the first one that fails. Each one is cheaper than the next, and each one eliminates a different explanation.

One line, one directive

The parser reads a line, takes the first word as the option, and treats the rest as that option's arguments. A line such as cert server.crt port 1194 is therefore not two instructions in sequence. It is one cert option with three arguments, and the third one is not a filename the option accepts. Reading the error as a missing newline is right; reading it as a missing directive is not.

# malformed: one option, three arguments
cert server.crt port 1194

# intended: two options, one argument each
cert server.crt
port 1194

Those two corrected lines are a fragment, not a configuration. They exist to show where the boundary belongs. Every ordinary directive in a profile follows the same rule, and a line that joins two of them produces either an argument error or a value the option did not expect.

Prove the line break is real

Editors wrap for display. Some of them also insert hard breaks when you paste, and some do not, so the same visual result can come from two very different files. Show the line endings and count the lines before you change anything. Measuring costs a command; guessing costs an evening.

cat -A /etc/openvpn/server/lab.conf | sed -n '10,20p'
awk 'NR>=10 && NR<=20 {printf "%d:%s\n", NR, $0}' /etc/openvpn/server/lab.conf

In the first output every real newline appears as a $ marker, so a wrapped-but-unbroken line shows no marker where your screen wraps. The second command prints numbered lines, which is the quickest way to compare what the parser reports with what the file contains.

Extra spaces do not create a directive either. Indentation is cosmetic, and a line that begins with whitespace is still the same single option. If the error message points at a line number, read that exact line rather than the paragraph it belongs to.

Quote a path, not a directive list

Quoting exists for arguments that contain spaces, not for grouping options. A certificate path with a space needs its own quotes; two directives sharing a pair of quotes is still one malformed line.

cert "/etc/openvpn/pki/lab certs/server.crt"
key "/etc/openvpn/pki/lab certs/server.key"

Check the option names at the same time as the layout, because a joined line can produce a plausible-looking token that never existed. The port directive is port; a profile that uses something else for the same idea will fail even after the line boundaries are fixed. When a name looks unfamiliar, compare it with the option list for the version you run rather than with a forum example.

Keep inline blocks as blocks

Profiles can carry certificates and keys inline, and those blocks are data rather than configuration. The PEM lines inside a block are not options to be flattened, re-indented or joined, and the block markers have to stay on their own lines.

Treat an inline block as an opaque region: correct the option lines around it, leave its contents byte-for-byte alone, and never paste it into a public support thread. If a formatting tool rewrote the block, restore it from your PKI rather than repairing it by hand.

Fix the smallest section, not the template

The tempting repair is to replace the whole file with a configuration from a tutorial that "works". That trades one malformed line for a set of policy changes nobody reviewed: different DH parameters, compression settings, cipher choices, duplicate listeners. The original problem is small and local, and the replacement is neither.

Copy the profile to a protected working file, correct the line boundaries in that copy, and let the normal owner of the service load it. Then start the instance and read the first error, if any, from the beginning.

openvpn --config /etc/openvpn/server/lab.conf --verb 3 --log /tmp/parse.log
grep -n 'Options error' /tmp/parse.log

When the parse stage passes, the next failure will be about a file, a certificate or a cipher rather than about vocabulary, and that is real progress. Keep the working copy and a one-line note about what was joined; the same paste will happen again to somebody else on the same team.

Inyandiko zihuye