OpenVPN não encontra ca.crt embora o perfil carregue
O caminho do perfil não é a base dos ficheiros lá dentro. Veja por que um --config absoluto ainda falha em ca.crt e como o arranque decide a resposta.
O serviço arranca, lê o perfil sem queixas e depois morre numa linha que parece não ter relação: não consegue abrir ca.crt. Nada do certificado mudou, e o caminho do perfil na unidade é absoluto. É precisamente essa combinação a pista. O caminho que indicou localiza um ficheiro, e os nomes dentro desse ficheiro são resolvidos noutro sítio por completo, pelo que um arranque que parece plenamente qualificado pode continuar a ler as suas chaves de um diretório que ninguém pretendia.
A falha tem poucas causas e vale a pena separá-las por ordem: o diretório base que o processo tinha na realidade, o contexto de arranque do serviço e as permissões ou a sandbox em torno do ficheiro quando o caminho já está correto. Cada uma deixa um rasto diferente: na unidade, no processo e no sistema de ficheiros.
O caminho do perfil não é um diretório base
Imagine um processo que arranca em /tmp e recebe /etc/vpn/prod/tenant-a.ovpn. Dentro desse perfil, a linha ca ca.crt nomeia um caminho relativo. Nada no argumento que localizou o perfil reescreve esse nome, pelo que o processo procura /tmp/ca.crt e reporta um ficheiro em falta.
O confuso é a ordem dos erros. OpenVPN analisa primeiro a configuração e abre os ficheiros referenciados à medida que chega a eles, pelo que uma gralha no perfil é reportada antes de se tocar em qualquer chave, enquanto um certificado em falta só aparece quando a análise chega lá. Um perfil que carrega é, portanto, prova de que a sintaxe está correta, não de que os ficheiros que nomeia foram encontrados.
O que o manual separa: --config e --cd
O manual do OpenVPN 2.6 descreve duas opções distintas. Uma carrega um ficheiro de configuração. A outra muda o diretório do processo antes de se lerem a configuração, a chave, o script e outros ficheiros, e exige um diretório absoluto sem qualquer referência ao atual.
openvpn --cd /etc/vpn/prod --config tenant-a.ovpn
Essa invocação é uma forma, não uma instrução para lançar o perfil de outra pessoa. O que oferece é determinismo: a base de cada nome relativo da cadeia é declarada no comando em vez de ser herdada da shell ou do gestor que iniciou o processo. A alternativa é igualmente válida e muitas vezes melhor para um serviço: deixe o diretório de trabalho em paz e torne absoluto cada ficheiro referenciado dentro do perfil.
Escolha o que escolher, audite toda a cadeia e não a primeira falha. Um perfil pode incluir outro ficheiro de configuração, e os nomes relativos do ficheiro incluído são resolvidos contra o mesmo diretório do processo, não contra o diretório do ficheiro que os incluiu. Os caminhos de registo, os ficheiros de autenticação e os scripts auxiliares seguem a mesma regra.
O serviço arranca noutro sítio
Uma shell interativa no diretório do perfil não prova nada sobre uma unidade empacotada. Os gestores definem o seu próprio diretório de trabalho, e um script envoltório pode voltar a mudá-lo antes de o binário correr. A unidade que falha é o único arranque sobre o qual vale a pena raciocinar.
systemctl show -p WorkingDirectory -p ExecStart --value openvpn@tenant-a
ls -l /proc/$(pgrep -n openvpn)/cwd
O segundo comando mostra o diretório que o processo vivo mantém de facto, e isso é mais fiável do que o ficheiro da unidade quando há um envoltório. Se ambos não coincidirem, o envoltório é a sua resposta e a unidade é uma pista falsa.
Depois da procura: permissões, chroot e sandbox
Um diretório base correto pode ainda produzir a mesma mensagem, porque a resolução e o acesso são passos separados. O processo precisa de permissão de execução em cada diretório pai e de leitura no ficheiro, e uma unidade de serviço que esconde parte do sistema de ficheiros altera aquilo que o processo consegue ver.
Três variantes comuns produzem o mesmo erro. O ficheiro só é legível pelo root enquanto o serviço abdica de privilégios antes de o abrir. A unidade define uma vista protetora do sistema de ficheiros que não inclui o diretório do perfil. O daemon corre com chroot, pelo que o caminho que existe no anfitrião não existe dentro dessa vista.
Diagnostique com a propriedade do ficheiro e a identidade do processo, não afrouxando permissões. Tornar uma chave privada legível por todos para silenciar este erro troca uma falha ruidosa por uma silenciosa, e a chave é justamente a parte do diretório que menos quer expor.
Prove a correção com o arranque próprio
Reinicie a unidade real a partir de um diretório sem relação com o perfil e observe a mesma linha de arranque. Depois confirme que o processo mantém o diretório pretendido enquanto corre, e que o certificado que carregou é o que espera.
systemctl restart openvpn@tenant-a
systemctl status openvpn@tenant-a --no-pager
journalctl -u openvpn@tenant-a -n 20 --no-pager
Quando o carregamento dos caminhos tem êxito, a autenticação e o encaminhamento continuam a ser etapas separadas com as suas próprias falhas, e uma ligação que sobe mas não deixa passar tráfego é outra investigação. A correção aqui diz apenas respeito a de que diretório vieram os ficheiros, e devia ser visível na invocação em vez de recordada por quem a executou à mão da última vez.
Se o perfil for implantado por um gestor de configuração, coloque lá também o diretório base ou os nomes absolutos dos ficheiros. Uma correção manual num único anfitrião é a versão deste problema que volta depois da reconstrução seguinte.