> ## Documentation Index
> Fetch the complete documentation index at: https://wiki.lumiweb.cc/llms.txt
> Use this file to discover all available pages before exploring further.

# SSL and Let's Encrypt

> HTTPS on your own server

<Note>
  This page is for those setting up a site on the server themselves (SSH access required). If you just bought a VPS for software or a VPN, you most likely don't need SSL here.
</Note>

## Certificate options

<CardGroup cols={3}>
  <Card title="Universal SSL" icon="cloud">
    Automatic in [Cloudflare](/en/domains/cloudflare). Encrypts "browser ↔ CF".
  </Card>

  <Card title="CF Origin CA" icon="certificate">
    Free cert on the origin, 15 years. Encrypts "CF ↔ origin".
  </Card>

  <Card title="Let's Encrypt" icon="certificate">
    Public, 90 days, auto-renewal. For end-to-end and Full (Strict).
  </Card>
</CardGroup>

<Tip>
  Production recommendation: **Cloudflare Full (Strict) + Let's Encrypt on the origin**. Encryption from the browser all the way to the server, with no gaps.
</Tip>

## Installing Let's Encrypt

Everything below runs over SSH as `root` (the IP and password are in the server card in the bot). The server runs Ubuntu 22.04 by default.

<Steps>
  <Step title="Check the prerequisites">
    * The domain's A record points to the server IP (the one in the server card in the bot). How to add it — [DNS records](/en/domains/dns).
    * Ports 80 and 443 are open in the firewall.
    * The web server (nginx or apache) is running.
  </Step>

  <Step title="Update the system">
    ```bash theme={"system"}
    sudo apt-get -y update && sudo apt-get -y upgrade
    ```
  </Step>

  <Step title="Install certbot">
    ```bash theme={"system"}
    sudo apt-get -y install certbot python3-certbot-nginx
    ```

    For Apache — `python3-certbot-apache`.
  </Step>

  <Step title="Get the certificate">
    ```bash theme={"system"}
    sudo certbot certonly --nginx -d example.com -d www.example.com
    ```

    Path: `/etc/letsencrypt/live/example.com/`.
  </Step>
</Steps>

## Renewal

The certificate lives for 90 days. Certbot installs a system auto-renewal timer — nothing needs configuring. To check:

```bash theme={"system"}
sudo certbot certificates
sudo certbot renew --dry-run
```

## Wildcard (`*.example.com`)

Only via the DNS challenge:

```bash theme={"system"}
sudo certbot certonly --manual --preferred-challenges dns -d "*.example.com"
```

The process is interactive: certbot will ask you to create a `_acme-challenge` TXT record in your [domain's DNS](/en/domains/dns). Wait for the record to propagate, and only then press Enter.

## Common errors

| Error              | Cause                          | What to do                                                |
| ------------------ | ------------------------------ | --------------------------------------------------------- |
| Timeout            | Port 80 is closed              | Open it in the firewall                                   |
| Domain not found   | The A record hasn't propagated | Wait, check [DNS](/en/domains/dns)                        |
| Connection refused | nginx/apache isn't running     | `sudo systemctl start nginx`                              |
| Rate limit         | Too many requests              | Wait. Limit: 5 failures/hour, 50 certificates/domain/week |

## Where to next

<CardGroup cols={2}>
  <Card title="Web server (Nginx)" icon="server" href="/en/vps/webserver">
    Configure Nginx to work with the certificate.
  </Card>

  <Card title="Server hardening" icon="lock" href="/en/vps/hardening">
    The next step — close off the remaining gaps.
  </Card>
</CardGroup>
