[Solved] Fatal: unable to open config file: [...] x509: certificate has expired or is not yet valid

Hello, I received this error today, and was going to post this as a question, but ended up finding the solution. Posting it anyway in case it helps someone else.

It has been some time since I setup restic to backup my nextcloud installation. Recently I have been getting this error:

# restic --cacert=/root/keys/public_key --password-file /root/keys/ncpass -r rest:https://username:pass@192.168.xxx.xxx:8000/username/nc --verbose check
Fatal: unable to open config file: Head "https://username:***@192.168.xxx.xxx:8000/username/nc/config": x509: certificate has expired or is not yet valid: current time 2024-01-19T21:02:47-05:00 is after  2024-01-12T19:54:21Z

on the server side, in systemctl status rest-server.service I get a TLS error

Jan 20 01:42:00 deb12server rest-server[332384]: http: TLS handshake error from 192.168.xxx.xxx:55070: remote error: tls: bad certificate

Looking at the manual in the REST section, it specifies:

If you use TLS, restic will use the system’s CA certificates to verify the server certificate. When the verification fails, restic refuses to proceed and exits with an error. If you have your own self-signed certificate, or a custom CA certificate should be used for verification, you can pass restic the certificate filename via the --cacert option. It will then verify that the server’s certificate is contained in the file passed to this option, or signed by a CA certificate in the file. In this case, the system CA certificates are not considered at all.

From this it’s not clear to me whether it is the server certificate that is wrong, or the client’s certificate. But since it seems more likely that it is the client’s certificate, I tried this openssl x509 -enddate -noout -in /path/to/certificate and found out that it was expired.

I’m not sure if I can just create a new certificate, but I’ll try it. Looking in GitHub - restic/rest-server: Rest Server is a high performance HTTP server that implements restic's REST backend API. it looks like I can with openssl req -newkey rsa:2048 -nodes -x509 -keyout private_key -out public_key -days 365 -addext "subjectAltName = IP:,DNS:yourdomain.com"

with a self-signed certificate you have to distribute your public_key file to every restic client

It was about this time that I realized I was supposed to make the cacert on the rest-server side, and then copy it to the client. This involved

  1. Creating the new keypair, and figuring out where to put it…

add a private and public key at the root of your persistence directory

So I put private_key and public_key in the same path as rest-server -tls -path=/foo/bar in the systemd unit file and restarted the service, but now I get (code=exited, status=1/FAILURE) in systemctl status rest-server.service.

So I ran the same command from root, but had no problem. Maybe the permissions on those key files are incorrect. I did ls -l and the permissions look correct, but I see the files are owned by root while everything else is owned by www-data. I used chown www-data:www-data public_key private_key and and now systemd starts it cleanly.

  1. Copying the public key to the client. This was easy and now it works.

Thank you for this software and the above-average documentation!!! Seriously – by thinking through it and reading, I was able to solve my problem. Thanks!