Curso de Ubuntu 26.04 / Emitir, renovar y comprobar certificados HTTPS
HTTPS protege HTTP mediante seguridad de la capa de transporte (TLS). Para configurarlo, prepare un dominio que administre, obtenga su certificado con Certbot y aplíquelo al servidor web. Compruebe por separado la emisión, el certificado que recibe un cliente externo, la renovación automática y su fecha de caducidad.
Verificar condiciones de dominio y HTTP público
El sitio de práctica 127.0.0.1:8080 .test del tutorial de Nginx no es un objetivo para la emisión de certificados. Primero, se debe preparar un sitio con DNS real que apunte al servidor y con server_name, la raíz del documento y la respuesta en el puerto 80 configuradas correctamente en Nginx. Si hay un registro IPv6 AAAA, esa ruta también debe funcionar realmente.
La siguiente consulta se ejecuta ingresando un dominio real. Si no se tiene dig, se debe preparar el paquete dnsutils en Ubuntu. También se debe verificar la respuesta DNS y HTTP desde clientes en otras redes y revisar las reglas de firewall, router y nube.
read -r -p "Domain you control: " domain
dig +short A "$domain"
dig +short AAAA "$domain"
curl -I "http://$domain/"
Completar primero el sitio HTTP del dominio real
Esta sección se dirige a un servidor web Ubuntu separado donde el dominio propiedad del usuario se conecta públicamente. La VM exclusiva para hosts utilizada en la práctica de IP fija no se puede acceder directamente desde Internet, por lo que no se intenta emitir certificado allí. Si no se pueden preparar un servidor público y DNS, la práctica de emisión se pospone o se sigue una ruta DNS-01 por separado con un complemento DNS oficial y almacenamiento de credenciales.
Prepare Nginx y curl, y conecte el registro A a la dirección IPv4 pública del servidor. Si publica AAAA, la ruta IPv6 también debe funcionar. Guarde el script completo como ~/prepare-public-http.sh y ejecútelo con bash ~/prepare-public-http.sh DOMINIO_REAL. La comprobación inicial filtra la forma del nombre ASCII, pero no demuestra que el dominio exista o le pertenezca; verifique el DNS y su control por separado. Para nombres internacionalizados, use su forma punycode validada. Si ya existe una ruta de la práctica, deténgase y conserve su contenido.
set -eu
if [ "$#" -ne 1 ]; then
printf 'Usage: bash prepare-public-http.sh YOUR_DOMAIN\n' >&2; exit 2
fi
domain=$(printf '%s' "$1" | tr '[:upper:]' '[:lower:]')
if [[ ! "$domain" =~ ^([a-z0-9]([a-z0-9-]*[a-z0-9])?\.)+[a-z]([a-z0-9-]*[a-z0-9])?$ ]]; then
printf 'Use a valid ASCII hostname you control.\n' >&2; exit 2
fi
case "$domain" in
*.test|*.invalid|*.localhost|*.example|example.com|*.example.com)
printf 'Use your real domain, not an example name.\n' >&2; exit 2 ;;
esac
site=/etc/nginx/sites-available/ubuntu-course-public
enabled=/etc/nginx/sites-enabled/ubuntu-course-public
root_dir=/srv/ubuntu-course-public
for path in "$site" "$enabled" "$root_dir"; do
if sudo test -e "$path" || sudo test -L "$path"; then
printf 'Existing lab path: %s; stop and inspect.\n' "$path" >&2; exit 1
fi
done
backup_dir=$(sudo mktemp -d /root/nginx-before-public.XXXXXX)
sudo cp -a /etc/nginx "$backup_dir/"
sudo install -d -m 0755 "$root_dir"
printf 'public-http-lab\n' | sudo sh -c 'set -C; cat > "$1/index.html"' sh "$root_dir"
sudo chmod 0644 "$root_dir/index.html"
sudo sh -c 'set -C; cat > "$1"' sh "$site" <<EOF
server {
listen 80;
listen [::]:80;
server_name $domain;
root /srv/ubuntu-course-public;
index index.html;
location / {
try_files \$uri \$uri/ =404;
}
}
EOF
sudo ln -s "$site" "$enabled"
sudo nginx -t
sudo systemctl reload nginx
printf 'HTTP site prepared; backup: %s\n' "$backup_dir"
Si el servidor no admite escucha IPv6, adapte la directiva listen [::]:80 antes de ejecutar el script y no publique AAAA sin una ruta válida. Continúe solo si la creación de archivos y enlaces, nginx -t y la recarga terminan correctamente. Si falla un paso, investigue el material creado y compárelo con la copia; conserve los demás sitios.
En un servidor web público nuevo que ya utiliza UFW, la regla siguiente permite HTTP y HTTPS. Conserve el acceso SSH y prepare también las rutas del cortafuegos del proveedor o del enrutador. Estas órdenes no activan UFW. HTTP-01 necesita que el verificador externo llegue al puerto 80; permitir únicamente el cliente privado de prácticas no basta.
sudo ufw allow 80/tcp && sudo ufw allow 443/tcp && sudo ufw status verbose
La variable domain del script no queda definida en su intérprete de órdenes padre. Introduzca de nuevo el nombre real en la sesión Bash actual y, desde otra conexión a Internet, confirme que la respuesta contiene public-http-lab. Compare nombre, contenido y rutas A/AAAA antes de continuar con Certbot.
read -r -p "Domain you control: " domain
dig +short A "$domain"
dig +short AAAA "$domain"
curl --fail --show-error "http://$domain/"
Determinar una ruta única para la instalación de Certbot
Si ya existe un Certbot, primero verifique la fuente de instalación y la tarea de renovación, y no mezcle instalaciones de APT, Snap o pip. Este ejemplo elige la ruta oficial de Snap en un nuevo servidor dedicado. Lea que es un paquete que requiere permisos classic antes de instalarlo, y ejecute los comandos con la ruta completa para no confundirlo con otras instalaciones.
sudo snap install --classic certbot
/snap/bin/certbot --version
Emitir después de respaldo y verificación de sintaxis
(
set -eu
backup=$(sudo mktemp -d /root/nginx-before-tls.XXXXXX)
sudo cp -a /etc/nginx "$backup/"
sudo nginx -t
sudo /snap/bin/certbot --nginx -d "$domain"
)
Confirme nuevamente que la variable domain de la misma sesión de Bash contiene el dominio real y ejecute Certbot solo después de pasar la verificación de sintaxis. Las elecciones de correo electrónico, términos y redirección se deciden según la guía. La configuración automática modifica los archivos de Nginx, así que compare con el respaldo para ver qué ha cambiado.
HTTP-01 requiere una ruta accesible por el verificador externo. En un entorno inaccesible, seleccione por separado métodos compatibles como el complemento oficial de DNS y guarde las credenciales de DNS API con los mínimos privilegios. No intente resolver fallos de emisión repetidamente mediante solicitudes; primero investigue DNS, puertos y registros de verificación.
Verificar el HTTPS externo y el certificado real
curl --fail --show-error "https://$domain/"
openssl s_client -connect "$domain:443" -servername "$domain" -verify_return_error -verify_hostname "$domain" </dev/null
Verifique el nombre, la cadena de certificados y la respuesta web esperada. No haga que aparezca éxito utilizando curl -k para desactivar la verificación. Incluso si los archivos emitidos localmente están actualizados, servidores proxy, equilibradores de carga u otros servidores IPv6 pueden proporcionar certificados antiguos, por lo que debe probar la ruta real a la que el usuario accede.
Pruebas de renovación y detección de expiración
sudo /snap/bin/certbot certificates
sudo /snap/bin/certbot renew --dry-run
systemctl list-timers --all | grep certbot
La prueba --dry-run verifica la ruta de renovación actual; no garantiza futuras ejecuciones. Revise el temporizador real, sus registros y alertas. Para leer las fechas del certificado que entrega la conexión externa, confirme primero domain y ejecute en Bash (set -o pipefail; openssl s_client -connect "$domain:443" -servername "$domain" -verify_return_error -verify_hostname "$domain" </dev/null | openssl x509 -noout -dates). La opción openssl x509 -dates muestra notBefore y notAfter; compruebe la zona horaria indicada y alerte antes del vencimiento real en vez de suponer un período fijo. pipefail conserva el fallo de verificación aunque el segundo comando pudiera leer un certificado.
Al restaurar, solo revise los cambios de Certbot y la configuración de Nginx de esta vez, y no elimine la configuración de certificados y renovación de otros dominios. Después de renovar el certificado, debe verificar el nuevo certificado y la respuesta del servicio en la ruta real de entrega para completar la inspección de la operación HTTPS.




