๐ Letโs Encrypt#
Overview
Letโs Encrypt is a free, automated, and open certificate authority (CA), run for the publicโs benefit. ๐
Certbot DNS Gandi#
Creating a Wildcard Certificate#
Find a DNS plugin.
Create a virtualenv, install certbot and gandi-plugin.
mkdir guisam_xyz_LE_certs && cd guisam_xyz_LE_certs
python -m venv CertbotEnv
pip list --outdated | awk 'NR>2{print $1}' | xargs pip install -U
pip install certbot certbot-plugin-gandi
Create gandi API key file : ~/guisam_xyz_LE_certs/gandi.ini.
# live dns v5 api key
dns_gandi_api_key=xxxxxxxxxxxxxxxxxxxxxxxx
Create your certificate.
certbot certonly -d "guisam.xyz" -d "*.guisam.xyz" \
--authenticator dns-gandi \
--dns-gandi-credentials /root/guisam_xyz_LE_certs/gandi.ini \
--email guisam@guisam.xyz \
--agree-tos
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Requesting a certificate for *.guisam.xyz
Unsafe permissions on credentials configuration file: /root/guisam_xyz_LE_certs/gandi.ini
Waiting 10 seconds for DNS changes to propagate
Successfully received certificate.
Certificate is saved at: /etc/letsencrypt/live/guisam.xyz/fullchain.pem
Key is saved at: /etc/letsencrypt/live/guisam.xyz/privkey.pem
This certificate expires on 2023-04-08.
These files will be updated when the certificate renews.
[...]
Check the wildcard certificate.
openssl x509 -noout -text -in /etc/letsencrypt/live/guisam.xyz/fullchain.pem | \
awk '/Validity|Not|Subject.*CN|Alternative|DNS/'
Validity
Not Before: Jan 9 09:52:49 2023 GMT
Not After : Apr 9 09:52:48 2023 GMT
Subject: CN = guisam.xyz
X509v3 Subject Alternative Name:
DNS:*.guisam.xyz, DNS:guisam.xyz
.. _letsencrypt_certbot_dns_ovh:
Cerbot DNS OVH#
OVH guisam.fr former ip#
แ
dig guisam.fr +noall +answer
guisam.fr. 2974 IN A 213.186.33.5
แ
sudo resolvectl status
แ
sudo systemctl restart systemd-resolved.service
แ
dig guisam.fr +noall +answer
guisam.fr. 3600 IN A 82.64.232.18
letโs encrypt certificate OVH#
Manual Setup via Certbot (Advanced)
If you prefer full control, use Certbot with the dns-ovh plugin to automate DNS challenges:
Create an API token in your OVHcloud account for DNS API access.
Tip
To create an OVH API token for Letโs Encrypt automation, follow these steps:
- Access the API Token Creation Page
- Configure Token Permissions.Set the following rights for the API token:
GET
/domain/zone/*
POST
/domain/zone/*
PUT
/domain/zone/*
DELETE
/domain/zone/*
- Set Token ValidityChoose
Unlimitedvalidity to avoid frequent renewals, especially for automated scripts. - Generate the TokenClick Create Token. Youโll receive:
Application Key
Application Secret
Consumer Key
Install
certbot-dns-ovhplugin.
root@forge:~# mkdir certbot && pytohn3 -m venv certbot/Venv && source certbot/Venv/bin/activate
root@forge:~# pip install certbot certbot-dns-ovh
Configure
/home/guisam/ovh.confwith your OVH API credentials.
root@forge:~# awk -F "=" '{if($2 !~ /ovh-/){$2="xxx"};printf "%-28s %s %s\n", $1, "=", $2}' /home/guisam/ovh.conf
dns_ovh_endpoint = ovh-eu
dns_ovh_application_key = xxx
dns_ovh_application_secret = xxx
dns_ovh_consumer_key = xxx
Use the command:
แ
sudo certbot certonly --dns-ovh --dns-ovh-credentials /home/guisam/ovh.conf \
--preferred-challenges dns --agree-tos --email guisam@free.fr -d forge.guisam.fr
Automate renewal using a cron job:
แ
sudo cat /etc/cron.d/cerbot_renew
30 21 * * * root /root/certbot_renew.sh
แ
sudo cat /root/certbot_renew.sh
#!/usr/bin/env bash
set -euo pipefail
typeset -r forgejo_wkd="/home/guiam/forgejo/"
typeset -r certs_dst="$forgejo_wkd/forgejo/gitea/conf/"
typeset -r certs_src="/etc/letsencrypt/live/forge.guisam.fr/"
# shellcheck source=/dev/null
source /root/certbotVenv/bin/activate
cb="$(command -v certbot)"
d="$(command -v docker)"
p="$(command -v pip)"
printf "### Upgrade Pkgs\n%s %s\n\n" "$p" install
"$p" install -U certbot-dns-ovh
printf "\n### Renew Certs\n%s %s\n\n" "$cb" renew
cbr_status=$("$cb" renew)
echo "$cbr_status"
if grep -q skipped <<< "$cbr_status";then
echo No renewals.
else
cp "$certs_src"[fp]*.pem "$certs_dst"
chown guisam: "$certs_dst"[fp]*.pem
"$d" compose -f "$forgejo_wkd"docker-compose.yaml restart server
fi
Secure traffic using Letโs Encrypt and cert-manager#
Deploy
cert-manager.
แ
helm repo add jetstack https://charts.jetstack.io
แ
htlm repo update
แ
helm install \
cert-manager jetstack/cert-manager \
--namespace cert-manager \
--create-namespace \
--set config.apiVersion="controller.config.cert-manager.io/v1alpha1" \
--set config.kind="ControllerConfiguration" \
--set config.enableGatewayAPI=true \
--set crds.enabled=true
Install webhook OVH via Helm.
แ
git clone https://github.com/baarde/cert-manager-webhook-ovh.git
แ
cd cert-manager-webhook-ovh
แ
helm install cert-manager-webhook-ovh ./deploy/cert-manager-webhook-ovh \
--set groupName=guisam.fr
Create API token
Create k8s secret with application_secret
แ
k create secret generic ovh-credentials \
--namespace cert-manager \
--from-literal=applicationSecret=xxx
แ
k get secrets -n cert-manager ovh-credentials \
-o jsonpath='{.data.applicationSecret}' | base64 -d
Create RBAC authorization (ServiceAccount
cert-managercan get Secretovh-credentials)
cert-manager-webhook-ovh-rbac.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: cert-manager-webhook-ovh:secret-reader
rules:
- apiGroups: [""]
resources: ["secrets"]
resourceNames: ["ovh-credentials"]
verbs: ["get", "watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: cert-manager-webhook-ovh:secret-reader
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cert-manager-webhook-ovh:secret-reader
subjects:
- apiGroup: ""
kind: ServiceAccount
name: cert-manager-webhook-ovh
namespace: cert-manager
แ
k apply -f cert-manager-webhook-ovh-rbac.yaml
Create
ClusterIssuerCreate
GatewayCreate
HTTPRoute
See Helm Charts
แ
helm template notes . -n notes | \
yq '.| select(.kind == "Gateway")'
{
"apiVersion": "gateway.networking.k8s.io/v1",
"kind": "Gateway",
"metadata": {
"name": "notes",
"namespace": "notes",
"annotations": {
"cert-manager.io/cluster-issuer": "letsencrypt-dns01"
}
},
"spec": {
"gatewayClassName": "nginx",
"listeners": [
{
"name": "http",
"port": 80,
"protocol": "HTTP"
},
{
"name": "https",
"port": 443,
"protocol": "HTTPS",
"hostname": "guisam.fr",
"tls": {
"mode": "Terminate",
"certificateRefs": [
{
"kind": "Secret",
"name": "notes-secret"
}
]
}
}
]
}
}
แ
helm template notes . -n notes | \
yq '.| select(.kind == "Gateway" or .kind == "HTTPRoute" or .kind == "ClusterIssuer")'
แ
k get clusterissuers,gtw,httproutes -n notes
NAME READY AGE
clusterissuer.cert-manager.io/letsencrypt-dns01 True 113m
NAME CLASS ADDRESS PROGRAMMED AGE
gateway.gateway.networking.k8s.io/notes nginx 10.96.222.193 True 4d17h
NAME HOSTNAMES AGE
httproute.gateway.networking.k8s.io/notes ["guisam.fr"] 4d17h
