# Certificat Let's Encrypt pentru IIS - Ghid Rapid ## Instalare Win-ACME ```powershell # Download și instalare Invoke-WebRequest -Uri "https://github.com/win-acme/win-acme/releases/download/v2.2.9.1701/win-acme.v2.2.9.1701.x64.pluggable.zip" -OutFile "$env:TEMP\win-acme.zip" Expand-Archive -Path "$env:TEMP\win-acme.zip" -DestinationPath "C:\Tools\win-acme" -Force ``` ## Prerequisite IIS ### Verificare Site ID-uri ```powershell Import-Module WebAdministration Get-Website | Select-Object ID, Name, State, @{N='Bindings';E={$_.Bindings.Collection.bindingInformation}} ``` ### Adaugă Binding-uri pentru Domeniu ```powershell # Exemplu pentru roa.romfast.ro pe Default Web Site New-WebBinding -Name "Default Web Site" -Protocol http -Port 80 -HostHeader "roa.romfast.ro" New-WebBinding -Name "Default Web Site" -Protocol https -Port 443 -HostHeader "roa.romfast.ro" ``` ## Generare Certificate ### Metoda 1: Comenzi PowerShell (Automat) ```powershell cd C:\Tools\win-acme # Pentru fiecare site (înlocuiește Site ID și email) .\wacs.exe --source iis --siteid 1 --accepttos --emailaddress your@email.com .\wacs.exe --source iis --siteid 2 --accepttos --emailaddress your@email.com .\wacs.exe --source iis --siteid 3 --accepttos --emailaddress your@email.com ``` ### Metoda 2: Mod Interactiv ```powershell cd C:\Tools\win-acme .\wacs.exe # În meniu: # N - Create certificate (simple for IIS) # Selectează site-ul # Confirmă binding-urile # yes - Accept ToS # Enter email ``` ## Configurare Binding-uri IIS cu SNI ### Important: SNI OBLIGATORIU pentru Multiple Certificate pe Același IP **GUI - IIS Manager:** 1. Deschide IIS Manager (`inetmgr`) 2. Pentru fiecare site: - Site → **Bindings** → Selectează **https** → **Edit** - ☑️ **Bifează "Require Server Name Indication"** - Selectează **certificatul corect** pentru site - **OK** 3. Restart IIS: `iisreset` **PowerShell:** ```powershell Import-Module WebAdministration # Exemplu pentru un site $siteName = "Dokploy" $hostHeader = "dokploy.romfast.ro" # Găsește certificatul $cert = Get-ChildItem Cert:\LocalMachine\My | Where-Object { $_.Subject -like "*$hostHeader*" -and $_.NotAfter -gt (Get-Date).AddDays(60) } | Select-Object -First 1 # Șterge binding vechi și creează cu SNI (SslFlags = 1) Remove-WebBinding -Name $siteName -Protocol https -HostHeader $hostHeader -ErrorAction SilentlyContinue New-WebBinding -Name $siteName -Protocol https -Port 443 -HostHeader $hostHeader -SslFlags 1 # Asociază certificatul $binding = Get-WebBinding -Name $siteName -Protocol https -HostHeader $hostHeader $binding.AddSslCertificate($cert.Thumbprint, "My") # Restart IIS iisreset ``` ## Verificare ### Listare Certificate Gestionate ```powershell cd C:\Tools\win-acme .\wacs.exe --list ``` ### Verificare Certificate în Browser ```bash # Din WSL sau Linux echo | openssl s_client -connect domain.ro:443 -servername domain.ro 2>/dev/null | openssl x509 -noout -dates -subject ``` ### Verificare Task Scheduler ```powershell Get-ScheduledTask | Where-Object {$_.TaskName -like "*acme*"} ``` ### Verificare Certificate IIS ```powershell Get-ChildItem Cert:\LocalMachine\My | Where-Object { $_.Issuer -like "*Let's Encrypt*" -and $_.NotAfter -gt (Get-Date) } | Select-Object Subject, NotAfter, Thumbprint ``` ## Reînnoire ### Automată - Task Scheduler verifică zilnic - Reînnoiește automat cu 30 zile înainte de expirare ### Manuală ```powershell cd C:\Tools\win-acme .\wacs.exe --renew --force iisreset ``` ## Troubleshooting ### Certificat Vechi Încă Servit ```powershell # Verifică SNI Get-WebBinding | Where-Object {$_.Protocol -eq "https"} | Select-Object @{N='Site';E={$_.ItemXPath -replace '.*name=''([^'']+)''.*','$1'}}, bindingInformation, @{N='SNI';E={($_.sslFlags -band 1) -eq 1}} # Forțează reinstalare cd C:\Tools\win-acme .\wacs.exe --renew --force iisreset ``` ### Validare HTTP-01 Eșuează - Verifică că portul 80 este accesibil din internet - Verifică că DNS pointează corect - Verifică că URL Rewrite nu blochează `/.well-known/acme-challenge/*` ### Certificate Nu Se Asociază Automat Folosește scriptul: `configure-iis-sni.ps1` ## Structură Site-uri IIS | Site ID | Nume | Hostname | Binding HTTPS | SNI | |---------|--------------------|-----------------------|------------------------|----------| | 1 | Default Web Site | roa.romfast.ro | *:443:roa.romfast.ro | ☑️ Activ | | 2 | Dokploy | dokploy.romfast.ro | *:443:dokploy.romfast.ro | ☑️ Activ | | 3 | Gitea | gitea.romfast.ro | *:443:gitea.romfast.ro | ☑️ Activ | ## Scripturi Utile ### Script Verificare/Reînnoire Certificate (PowerShell) **Locație repo:** `../scripts/check-ssl-certificates.ps1` **Locație VM 201:** `D:\kit\ssl\check-ssl-certificates.ps1` ```powershell # Verificare manuală D:\kit\ssl\check-ssl-certificates.ps1 -Verbose # Forțare reinstalare toate certificatele D:\kit\ssl\check-ssl-certificates.ps1 -Force -Verbose ``` ### Script Monitorizare Certificate (Bash - Proxmox) **Locație repo:** `../scripts/monitor-ssl-certificates.sh` **Locație Proxmox:** `/opt/scripts/monitor-ssl-certificates.sh` ```bash # Verificare manuală /opt/scripts/monitor-ssl-certificates.sh # Verificare log tail -50 /var/log/ssl-monitor.log ``` ## Comenzi Rapide ```powershell # Instalare Expand-Archive win-acme.zip -DestinationPath C:\Tools\win-acme # Generare certificate cd C:\Tools\win-acme .\wacs.exe --source iis --siteid X --accepttos --emailaddress email@domain.com # Verificare .\wacs.exe --list # Reînnoire .\wacs.exe --renew --force # Restart IIS iisreset ``` ## Monitorizare Automată Certificate ### Problema Cunoscută Win-acme poate reînnoi certificatele, dar IIS uneori nu aplică noile certificate pe binding-uri. Acest lucru cauzează servirea certificatelor expirate chiar dacă cele noi sunt în Certificate Store. ### Soluția: Scripturi de Monitorizare #### 1. Script PowerShell pe VM 201 **Locație:** `D:\kit\ssl\check-ssl-certificates.ps1` **Task Scheduler:** "SSL Certificate Check" - rulează zilnic la 07:00 ```powershell # Verificare manuală D:\kit\ssl\check-ssl-certificates.ps1 -Verbose # Forțare reinstalare toate certificatele D:\kit\ssl\check-ssl-certificates.ps1 -Force -Verbose ``` #### 2. Script Bash pe Proxmox (pvemini) **Locație:** `/opt/scripts/monitor-ssl-certificates.sh` **Cron:** Zilnic la 08:00 ```bash # Verificare manuală /opt/scripts/monitor-ssl-certificates.sh # Verificare log tail -50 /var/log/ssl-monitor.log ``` ### Ce Fac Scripturile - Verifică zilele rămase pentru fiecare certificat - Dacă < 14 zile: forțează reinstalare cu `wacs.exe --force` - Restart IIS după reinstalare - Trimite alertă email dacă există probleme ### Verificare Task Schedulers ```powershell # Pe VM 201 Get-ScheduledTask | Where-Object {$_.TaskName -like "*SSL*" -or $_.TaskName -like "*acme*"} ``` ```bash # Pe Proxmox grep ssl /etc/crontab ``` ## Wildcard `*.roa.romfast.ro` — Reînnoire Automată DNS-01 (cPanel) > **Incident 2026-05-31:** wildcardul a expirat. Renewal-ul win-acme era de tip > `[Manual]` (DNS-01 cu TXT pus de mână) → nu rula din Scheduled Task → ~60 de > erori consecutive → expirare. Subdomeniile Dokploy (`efactura.roa…`, `space.roa…`) > dădeau `ERR_CERT_DATE_INVALID`. Monitorizarea nu prindea pentru că `*.roa` nu era > în lista de domenii verificate (era doar `roa.romfast.ro`, un cert separat). Wildcardul **nu** poate folosi HTTP-01 (ca site-urile 1–6); necesită **DNS-01**. DNS-ul `romfast.ro` e pe **hosting.com (cPanel)**, fără plugin nativ în win-acme, deci folosim hook-ul de script `cpanel-acme-dns.ps1` care pune/șterge TXT-ul prin cPanel API. ### Setup (o singură dată, pe VM 201 ca Administrator) 1. cPanel → **Manage API Tokens** → creează token cu drept de editare DNS. 2. Copiază pe VM 201: - `scripts/cpanel-acme-dns.ps1` → `C:\Tools\win-acme\cpanel-acme-dns.ps1` - `scripts/cpanel-dns.config.example.json` → `C:\Tools\win-acme\cpanel-dns.config.json` și completează `Hostname`, `User`, `ApiToken`. **Nu commite** fișierul real (e în `.gitignore`). 3. Test manual: ```powershell cd C:\Tools\win-acme .\cpanel-acme-dns.ps1 create _acme-challenge.roa.romfast.ro testvalue123 # verifică TXT-ul în cPanel Zone Editor, apoi: .\cpanel-acme-dns.ps1 delete _acme-challenge.roa.romfast.ro testvalue123 ``` 4. Recreează renewal-ul wildcard: ``` .\wacs.exe (ca Administrator) M → Create renewal (full options) Source: Manual → *.roa.romfast.ro Validation: dns-01 → "Create verification records with your own script" Run create: Powershell.exe -File C:\Tools\win-acme\cpanel-acme-dns.ps1 Create args : create {RecordName} {Token} Run delete: Powershell.exe -File C:\Tools\win-acme\cpanel-acme-dns.ps1 Delete args : delete {RecordName} {Token} Store: Windows Certificate Store (My) Installation: IIS → site "roa-apps" (re-leagă certul automat pe binding) ``` 5. Confirmă Scheduled task (rulând `wacs.exe` ca admin) → reînnoire 100% automată. ### Verificare ```bash echo | openssl s_client -connect efactura.roa.romfast.ro:443 \ -servername efactura.roa.romfast.ro 2>/dev/null | openssl x509 -noout -dates ``` ### Monitorizare `monitor-ssl-certificates.sh` include acum `efactura.roa.romfast.ro` ca **sentinel** pentru wildcard (Site ID `WILDCARD`). Dacă expiră, scriptul **alertează** (nu mai încearcă auto-renew prin guest-exec, care e dezactivat) → intervenție pe VM 201. > **Securitate:** tokenul cPanel ajunge pe VM 201. Dă-i drepturi cât mai granulare > (doar DNS). Dacă panoul e vechi și expune doar API2 ZoneEdit, setează > `"LegacyZoneEdit": true` în config. --- ## Note Importante - **SNI este OBLIGATORIU** pentru multiple certificate pe același IP:port - Certificatele expiră la **90 zile** - Task Scheduler reînnoiește automat cu **30 zile** înainte - Fiecare domeniu trebuie să fie **accesibil pe port 80** din internet pentru validare HTTP-01 - DNS trebuie să pointeze corect către IP-ul public - **Monitorizarea duală** (Windows + Proxmox) asigură redundanță