
SSL Certificates with Lets Encrypt and certbot on a Linux Server
To install our certificates for SSL we use a tool called certbot. We install certbot with apt on our Linux machine.
sudo apt update
sudo apt install certbot
Then we run certbot.
sudo certbot certonly --standalone -d <yourDomain>
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Enter email address (used for urgent renewal and security notices)
(Enter 'c' to cancel): <yourEmail>
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Please read the Terms of Service at
https://letsencrypt.org/documents/LE-SA-v1.5-February-24-2025.pdf. You must
agree in order to register with the ACME server. Do you agree?
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(Y)es/(N)o: Y
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Would you be willing, once your first certificate is successfully issued, to
share your email address with the Electronic Frontier Foundation, a founding
partner of the Let's Encrypt project and the non-profit organization that
develops Certbot? We'd like to send you email about our work encrypting the web,
EFF news, campaigns, and ways to support digital freedom.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(Y)es/(N)o: Y
Account registered.
Requesting a certificate for <yourDomain>
Successfully received certificate.
Certificate is saved at: /etc/letsencrypt/live/<yourDomain>/fullchain.pem
Key is saved at: /etc/letsencrypt/live/<yourDomain>/privkey.pem
This certificate expires on 2025-07-25.
These files will be updated when the certificate renews.
Certbot has set up a scheduled task to automatically renew this certificate in the background.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
If you like Certbot, please consider supporting our work by:
* Donating to ISRG / Let's Encrypt: https://letsencrypt.org/donate
* Donating to EFF: https://eff.org/donate-le
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
The Letsencrypt certificates are automatically stored by certbot in the directory /etc/letsencrypt. Pls. Check the permissions accordingly.
#700 for letsencrypt and owned by root
sudo ls -l /etc
drwx------ 9 root root 4096 Mai 22 04:49 letsencrypt
#750 for archive and live and owned by root
ls -l /etc/letsencrypt
drwx------ 3 root root 4096 Apr 26 10:16 accounts
drwxr-x--- 3 root root 4096 Apr 26 10:18 archive
-rw-r--r-- 1 root root 207 Nov 12 2021 cli.ini
drwx------ 2 root root 4096 Mai 16 07:15 csr
drwx------ 2 root root 4096 Mai 16 07:15 keys
drwxr-x--- 3 root root 4096 Apr 26 10:18 live
drwxr-x--- 2 root root 4096 Mai 16 07:15 renewal
drwxr-xr-x 5 root root 4096 Apr 26 10:16 renewal-hooks
#700 for the directory with the real certificates
sudo ls -l /etc/letsencrypt/archive
drwx------ 2 root root 4096 Mai 16 07:15 <domain>
#750 for the directory with the symlinks
sudo ls -l /etc/letsencrypt/live
drwxr-x--- 2 root root 4096 Mai 16 07:15 <domain>
note: Permissions in Linux are set using the following scheme.
Owner | Group | Others |
---|---|---|
Read (r) = 4 – Write (w) = 2 – execute (x) = 1 | Read (r) = 4 – Write (w) = 2 – execute (x) = 1 | Read (r) = 4 – Write (w) = 2 – execute (x) = 1 |
Example: | ||
7 = r(4)+w(2)+x(1) | 5 = r(4)+x(1) | 0 |
The following permissions are recommended:
Directory | Permissions | Recommendation | Comment |
---|---|---|---|
accounts/
|
drwx------
|
750. Ok | Contains Let’s Encrypt account information – only root is allowed access |
archive/
|
drwxr-x---
|
750 or 700 | Contains real keys/certificates – do not make publicly readable |
cli.ini
|
-rw-r--r--
|
644 or 600 if sensitive content | Not critical unless cli.ini contains API keys or email addresses |
csr/
|
drwx------
|
700. Ok | CSR files (may contain sensitive information) – not readable by others |
keys/
|
drwx------
|
700. Ok | Contains private keys – only root is allowed access |
live/
|
drwxr-x---
|
750. Ok | Only root + webserver group should have access to symlinks |
renewal/
|
drwxr-x---
|
750 or 700 | Contains configs with paths to key files – do not leave open |
renewal-hooks/
|
drwxr-xr-x
|
755. Ok | Contains mostly harmless scripts – leaving it readable is okay unless you have sensitive hooks |
The keys are set up the following structure:
- In /etc/letsencrypt/live/<domain> there are only symlinks that point to the real key files
- the real files are stored in /etc/letsencrypt/archive/<domain>
A symlink itself in /etc/letsencrypt/live/<domain> has no real permissions. It effectively inherits the access rights of the file it points to. However: ls -l shows symbolic permissions which, for symlinks, are usually lrwxrwxrwx. This isn’t problematic in itself, since access is always controlled by the target files.
sudo ls -l /etc/letsencrypt/live/<domain>
total 4
lrwxrwxrwx 1 root root 48 Mai 16 07:15 cert.pem -> ../../
lrwxrwxrwx 1 root root 49 Mai 16 07:15 chain.pem -> ../../
lrwxrwxrwx 1 root root 53 Mai 16 07:15 fullchain.pem -> ../../
lrwxrwxrwx 1 root root 51 Mai 16 07:15 privkey.pem -> ../../
Important are the permissions of the actual certificate files in the directory /etc/letsencrypt/archive/<domain>. The permissions should be set as follows.
File | Required permissions | Owner |
---|---|---|
privkey*.pem
|
600
|
root:root
|
cert*.pem
|
644
|
root:root
|
chain*.pem
|
644
|
root:root
|
fullchain*.pem
|
644
|
root:root
|
sudo ls -l /etc/letsencrypt/archive/<domain>
total 32
-rw-r--r-- 1 root root 1858 Apr 26 10:18 cert1.pem
-rw-r--r-- 1 root root 1801 Apr 26 10:18 chain1.pem
-rw-r--r-- 1 root root 3659 Apr 26 10:18 fullchain1.pem
-rw------- 1 root root 1704 Apr 26 10:18 privkey1.pem
You should pay special attention to some other files.
/etc/letsencrypt/accounts/acme-<v02.api>/directory/<accountID>
The files meta.json, regr.json and private_key.json in the accounts directory should be owned by root and only root should have access. These files contain your Let’s Encrypt account credentials, especially the private account key, and are therefore highly sensitive.
Files | Recommendation | Comment |
---|---|---|
private_key.json
|
400 | contains private account key |
meta.json , regr.json
|
600 | contains metadata, optionally sensitive information (email, ID) |
sudo ls -l /etc/letsencrypt/accounts/acme-<v02.api>/directory/<accountID>
total 12
-rw------- 1 root root 85 Apr 26 10:18 meta.json
-r-------- 1 root root 1632 Apr 26 10:17 private_key.json
-rw------- 1 root root 80 Apr 26 10:17 regr.json
private_key.json: Contains your ACME account key – this is like a password for your certificate management.
- Read-only: The file must be readable by root so that Let’s Encrypt (or other tools like certbot) can communicate with this key to renew or issue certificates.
- Write-protected: Making the file unreadable even by root prevents it from being modified accidentally or through an unsafe operation. The private key should not be changed, as this could prevent access to your Let’s Encrypt account.
meta.json: Contains information such as the registered email address.
regr.json: Let’s Encrypt registration details.
A leak of these files would allow attackers to:
- Hijack your Let’s Encrypt account
- Issue certificates for any domain (if DNS access is compromised)
- Tamper or delete existing certificates
/etc/letsencrypt/csr and /etc/letsencrypt/keys directory
The files in the /etc/letsencrypt/csr and /etc/letsencrypt/keys directories should have the following permissions to ensure security.
File Type | Path | Permission | Why |
---|---|---|---|
Private Key | /etc/letsencrypt/keys/.pem | Must be 600 | Contains the private key for the certificate |
CSR (Certificate Signing Request) | /etc/letsencrypt/csr/.pem | Recommended 600 (alternatively 644 less secure) | Contains no private key, just public key + metadata |
Directory /etc/letsencrypt/csr stores Certificate Signing Requests (CSRs) generated by Certbot during certificate issuance or renewal. These are not used after issuance — they are kept for reference or debugging, not for active use.
sudo ls -l /etc/letsencrypt/csr
total 8
-rw------- 1 root root 936 Apr 26 10:18 0000_csr-certbot.pem
-rw-r--r-- 1 root root 936 Mai 16 07:15 0001_csr-certbot.pem
CSR files contain requests for certificate issuance and may contain sensitive information, such as the public key associated with a private key. Although the CSR file itself does not contain the private key, it can still pose informational risks because it represents an association with a private key.
Security measure: Access should be restricted to root to prevent an attacker from tampering with or accessing the CSR files.
Issue:After a renewal of the certificates on Mai 16 you can see above that the permissions to the file 0001_csr-certbot.pem has been set by certbot to 644. You can correct this with the following command.
sudo find /etc/letsencrypt/csr -name '*.pem' -exec chmod 600 {} +
sudo ls -l /etc/letsencrypt/csr
total 8
-rw------- 1 root root 936 Apr 26 10:18 0000_csr-certbot.pem
-rw------- 1 root root 936 Mai 16 07:15 0001_csr-certbot.pem
Directory /etc/letsencrypt/keys holds actual private keys used to sign CSRs and serve HTTPS. They must never be world-readable.
sudo ls -l /etc/letsencrypt/keys
total 8
-rw------- 1 root root 1704 Apr 26 10:18 0000_key-certbot.pem
-rw------- 1 root root 1704 Mai 16 07:15 0001_key-certbot.pem
Private keys are critical for security because they are used for authentication during certificate requests and for encrypting and decrypting data. The private key should be readable and writable only by root to prevent unauthorized access. Important: Any user with access to these key files could perform encryption operations or misuse certificates.
/etc/letsencrypt/renewal/<yourDomain>.conf
The file /etc/letsencrypt/renewal/<yourDomain>.conf contains the configuration for automatic certificate renewal and can contain sensitive data, such as the paths to private keys and certificates. Therefore, it is important to secure this file accordingly. The file should only be readable and writable by root, as it contains potentially sensitive information about the certificate configuration and the paths to private keys.
sudo ls -l /etc/letsencrypt/renewal
total 4
-rw------- 1 root root 606 Mai 16 07:15 <yourDomain>.conf