Certbot on Windows – Symlink Behavior and Certificate Loading Failure

Certbot’s directory structure is designed for Linux, not Windows. When Certbot issues a certificate, it creates:

Example (Linux behavior):

Code

/etc/letsencrypt/live/<domain>/fullchain.pem → symlink
/etc/letsencrypt/archive/<domain>/fullchain1.pem → real file

On Linux, this works flawlessly.

On Windows, it does not.

When NGINX attempts to load certificates from the live/ directory on Windows, it fails with:

Code

BIO_new_file() failed
Input/output error

This occurs even when the file appears to exist, because Windows treats the symlink as an unreadable object.

Symptoms observed:

Root Cause:

Certbot’s live/ directory contains symlinks, not real files. Windows NGINX and Windows OpenSSL cannot follow these symlinks.

Resolution:

Use the real certificate files from the archive/ directory and copy them into a Windows‑native directory.

Example:

Code

C:\nginx-1.27.3\certs\fullchain.pem
C:\nginx-1.27.3\certs\privkey.pem

Then update nginx.conf:

nginx

ssl_certificate     C:/nginx-1.27.3/certs/fullchain.pem;
ssl_certificate_key C:/nginx-1.27.3/certs/privkey.pem;

Operational Takeaway:

On Windows, never point NGINX at Certbot’s live/ directory. Always use the real files from archive/, copied into a Windows‑safe path.

This avoids:

Why this matters:

This behavior is unique to Windows and is not documented clearly in Certbot’s official guides. Understanding it demonstrates: