OpenVPN Profile in Git: What to Strip Before Committing
Read the file for embedded keys, decide what a repository is allowed to distribute, and revoke before you rewrite history.
Profiles serve two purposes at once: they record connection settings, and they carry a working credential bundle. The file extension tells you nothing about which one you are holding. Read the contents before deciding that it belongs in a repository.
The steps below assume a client template is being considered for version control. Run them in order, and stop before committing anything you cannot revoke.
Read the file you are about to stage
Start with the actual bytes, because a profile that references separate files looks very different from one that embeds them. Search for the PEM block markers and for the inline tags named ca, cert, key, tls-auth and tls-crypt, and the same pass will show you both cases. An encrypted private key still counts as sensitive material, and a shared tls-auth or tls-crypt key is a credential even though it is not a user's identity. Apply the same review to anything staged alongside the profile, including archives and setup scripts that reference a credential file.
Then look at the staged set rather than the working tree. git diff --cached shows what the commit will actually contain, which is the only version that matters for this decision.
Decide what the repository is allowed to distribute
A template can carry the shared, reviewed settings and named placeholders for everything a person receives at enrolment. What it cannot carry is a usable identity, because a repository distributes to everyone who can read it, automation included. A private repository narrows the audience without changing the question of whether each reader is authorised for that credential.
An ignore rule prevents future additions and does nothing about what is already recorded. That asymmetry is worth internalising before the first commit rather than after the tenth. Infrastructure names and addresses are a separate judgement: they are not authentication secrets, but they can disclose more than a team intends to publish. Make that call explicitly instead of sorting every line into password or public.
If the material is already in history
Removing the line in a new commit leaves the old version intact for anyone who fetches it. Treat the exposure as real: identify the credential type, then find the authority that can invalidate it. A client certificate is revoked and the revocation list regenerated; a shared control-channel key is replaced on the server and on every client that uses it.
The two have very different blast radii, and the plan should state which one you are executing before you start. Locate the commit that introduced the material with a pickaxe search such as git log --all -S 'BEGIN PRIVATE KEY', so the cleanup scope is known rather than guessed. A colleague's clone or a fork may already hold the old object, which is why revocation comes first and cleanup second.
Clean up only after containment
History rewriting changes every commit after the one you edit, so it needs the repository owner and the people working in it to agree first. A force-push is not a repair; it is a coordination event with its own rollback risk. Schedule it, take a backup, and tell the team when it will happen.
Afterwards, verify the current tree and the remaining history rather than trusting the tool's summary.
Keep the outcome as two artifacts: the template that is safe to share, and the inventory of credentials issued through the enrolment process. Neither requires a usable identity to live in the repository.
That split is the real fix, and it survives the next person who wants to commit a profile.