# Klienci ACMEUżywać standardowych klientów ACME z wewnętrzną CA — co jest takie samo jak przy Let's Encrypt, co jest inne.

## Co pozostaje takie samo jak przy Let's Encrypt

Jeśli kiedykolwiek pobrałeś certyfikat Let's Encrypt, już umiesz używać wewnętrznego CA. Protokół jest identyczny — ACME RFC 8555. Klienci, których już znasz, działają bez modyfikacji.

To samo:

- Challenges HTTP-01 i DNS-01.
- Rejestracja konta i zarządzanie kluczami.
- Domyślny okres ważności certyfikatu 90 dni.
- Automatyczne odnawianie przy 60 dniach.
- Certyfikaty wildcard przez DNS-01.

## Co jest inne

Dwie drobne różnice, obie jednorazowe kroki setupowe:

1. **URL katalogu ACME** wskazuje na wewnętrzne CA, nie na `https://acme-v02.api.letsencrypt.org/directory`.
2. **Certyfikat root** wewnętrznego CA musi być akceptowany jako zaufany przez klienta wnioskującego. To jest z reguły konfigurowane przez configuration management (Ansible, Puppet, MDM) podczas provisioningu hosta.

To cała różnica. Wszystko inne to ten sam workflow Let's Encrypt, który już znasz.

## Skierować klienta na wewnętrzne CA

Wewnętrzny endpoint ACME jest opublikowany pod stabilnym wewnętrznym URL (typowo `https://acme.example.internal/acme/acme/directory`, ale dokładna ścieżka zależy od deploymentu). Poniżej przepisy dla popularnych klientów.

### `certbot`

```sh
certbot --server https://acme.example.internal/acme/acme/directory \
        --email ops@example.internal \
        --no-eff-email \
        --agree-tos \
        certonly --standalone -d service.example.internal
```

Przy odnawianiu flaga `--server` jest persystowana w `renewal/*.conf`, dzięki czemu periodyczny cron `certbot renew` przejmuje ją automatycznie.

### `acme.sh`

```sh
acme.sh --register-account \
        --server https://acme.example.internal/acme/acme/directory \
        -m ops@example.internal

acme.sh --issue \
        --server https://acme.example.internal/acme/acme/directory \
        --standalone \
        -d service.example.internal
```

### `lego`

```sh
lego --server=https://acme.example.internal/acme/acme/directory \
     --email=ops@example.internal \
     --domains=service.example.internal \
     --http run
```

### Caddy

W twoim `Caddyfile`:

```caddy
{
  acme_ca https://acme.example.internal/acme/acme/directory
  email ops@example.internal
}

service.example.internal {
  reverse_proxy localhost:8080
}
```

Caddy pobiera i odnawia certyfikat automatycznie.

### Traefik

W twojej konfiguracji dynamicznej:

```yaml
certificatesResolvers:
  internal:
    acme:
      caServer: "https://acme.example.internal/acme/acme/directory"
      email: ops@example.internal
      storage: /etc/traefik/acme.json
      httpChallenge:
        entryPoint: web
```

Odwoływać się przez `certResolver: internal` w definicjach routerów.

## Zainstalować certyfikat root na klientach

Aby wystawione przez CA certyfikaty były ufane bez ostrzeżenia, root CA musi leżeć w systemowym truststore każdego hosta, który widzi te certyfikaty.

### Linux (rodzina Debian/Devuan)

```sh
sudo cp internal-ca-root.crt /usr/local/share/ca-certificates/internal-ca-root.crt
sudo update-ca-certificates
```

### Linux (rodzina RHEL)

```sh
sudo cp internal-ca-root.crt /etc/pki/ca-trust/source/anchors/
sudo update-ca-trust extract
```

### OpenBSD / FreeBSD

```sh
# OpenBSD
sudo install -m 0644 internal-ca-root.crt /etc/ssl/internal-ca-root.crt
sudo cat /etc/ssl/cert.pem internal-ca-root.crt > /etc/ssl/cert.pem.new
sudo mv /etc/ssl/cert.pem.new /etc/ssl/cert.pem
```

### macOS

```sh
sudo security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain internal-ca-root.crt
```

### Windows

```cmd
certutil.exe -addstore -f "ROOT" internal-ca-root.crt
```

Dla przeglądarek, które utrzymują własne truststores (Firefox), root musi być dodatkowo zaimportowany przez Ustawienia → Prywatność → Certyfikaty → Urzędy certyfikacji.

Instalacja ta jest z reguły przejmowana przez configuration management. Ręcznie jest OK na pojedynczy przypadek, ale nie skaluje się na flotę.

## Certyfikaty wildcard

Wildcards są wystawiane przez challenge DNS-01 — klient wykazuje kontrolę nad domeną przez założenie rekordu TXT. Działa to dla czysto wewnętrznych domen, ponieważ wewnętrzne CA może walidować rekordy TXT na każdym serwerze DNS, który kontrolujesz.

Przykład z `acme.sh` i providerem BIND-nsupdate:

```sh
acme.sh --issue \
        --server https://acme.example.internal/acme/acme/directory \
        --dns dns_nsupdate \
        -d '*.example.internal' \
        -d 'example.internal'
```

Provider nsupdate musi być skonfigurowany wobec twojego wewnętrznego DNS — patrz dokumentacja `acme.sh` po specyficzne zmienne środowiskowe.

## Odnawianie

Odnawianie działa dokładnie tak samo jak przy Let's Encrypt: klient sprawdza pozostały okres ważności i odnawia, gdy próg zostanie przekroczony (60 dni dla certyfikatu 90-dniowego).

Dla większości deploymentów istniejący cron odnawiania po prostu działa (`certbot renew`, `acme.sh --cron`, automatyczne odnawianie Caddy'ego).

Przy błędach odnawiania:

1. **Czy URL katalogu jest nadal dostępny?** Zmiana sieci mogła złamać ścieżkę od klienta do CA.
2. **Czy certyfikat root nie wygasł lub został zrotowany?** Roots są typowo ważne 10 lat; intermediates krócej. Rotacja, która nie została propagowana do wszystkich klientów, manifestuje się jako błąd odnawiania.
3. **Czy typ challenge nadal jest adekwatny?** Serwis, który wcześniej był dostępny przez HTTP-01, może teraz siedzieć za load-balancerem, który łamie odpowiedź challenge.

## Limity i polityki

Wewnętrzne CA wymusza polityki per-account — jakie domeny każde konto może wnioskować o certyfikaty, jaka maksymalna ważność jest dozwolona, jakie typy challenge są akceptowane.

Jeśli request, który wczoraj działał, nagle pada z błędem `policy denied`, zmieniła się polityka (lub twoje account-binding). Zwróć się do swojego operatora CA. Usługa [Wsparcie](/pl/services/support/) jest ścieżką eskalacji, jeśli twoim operatorem CA jesteśmy my.
