Creating wildcard subdomain SSL certificates isn't that straightforward with Let's encrypt as a normal SSL certificate. As you need to prove you own the full domain before you can issue a certificate.
In most of my personal projects, or the projects we do at Spatie, setting up an SSL certificate is as easy as choosing "Let's Encrypt" in the UI of Laravel Forge. Forge also supports wildcard subdomains through a number of DNS providers (DigitalOcean, CloudFlare, ...).
For Mailcoach Cloud, our hosted email marketing service, we're using BunnyCDN as our DNS provider, as it acts as a proxy that provides DDOS protection and caching for a number of endpoints. Setting up a wildcard subdomain SSL certificate is sadly not as easy when using Bunny.
The steps below assume you're working on a Laravel Forge provisioned server.
Certbot and Certbot plugins can be installed through snap
:
sudo snap install certbot --classic sudo snap install certbot-dns-bunny
After both are installed, you can connect the DNS Bunny plugin:
sudo snap set certbot trust-plugin-with-root=ok sudo snap connect certbot:plugin certbot-dns-bunny
The DNS Bunny plugin needs a credentials file, you can create this at for example ~/.secrets/bunny.ini
# Bunny API token used by Certbot dns_bunny_api_key = xxxxx-xxxx
Once everything is set up, it's time to request the certificate. More information can be found on the DNS Bunny plugin documentation.
Certbot will ask for your email address and to accept the license.
certbot certonly \ --authenticator dns-bunny \ --dns-bunny-credentials ~/.secrets/bunny.ini \ --dns-bunny-propagation-seconds 60 \ -d example.com \ -d *.example.com
Once that's completed, Certbot will output where it stored the certificates:
Requesting a certificate for example.com and *.example.com Unsafe permissions on credentials configuration file: /home/.secrets/bunny.ini Waiting 60 seconds for DNS changes to propagate Successfully received certificate. Certificate is saved at: /etc/letsencrypt/live/example.com/fullchain.pem Key is saved at: /etc/letsencrypt/live/example.com/privkey.pem This certificate expires on 2023-01-30. These files will be updated when the certificate renews. Certbot has set up a scheduled task to automatically renew this certificate in the background. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - If you like Certbot, please consider supporting our work by: * Donating to ISRG / Let's Encrypt: https://letsencrypt.org/donate * Donating to EFF: https://eff.org/donate-le - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Once you know where the certificate & key are saved, it's time to update your Nginx configuration:
# FORGE CONFIG (DO NOT REMOVE!) include forge-conf/example.com/before/*; server { - listen 80; + listen 443 ssl http2; - listen [::]:80; + listen [::]:443 ssl http2; server_name example.com *.example.com; server_tokens off; root /home/forge/example.com; + # SSL managed by Certbot + ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem; + ssl_protocols TLSv1.2 TLSv1.3; + ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384; + ssl_prefer_server_ciphers off; + ssl_dhparam /etc/nginx/dhparams.pem; + proxy_ssl_server_name on; add_header X-Frame-Options "SAMEORIGIN"; add_header X-XSS-Protection "1; mode=block"; add_header X-Content-Type-Options "nosniff"; index index.html index.htm index.php; charset utf-8; # FORGE CONFIG (DO NOT REMOVE!) include forge-conf/example.com/server/*; location / { try_files $uri /index.php?$query_string; } location = /favicon.ico { access_log off; log_not_found off; } location = /robots.txt { access_log off; log_not_found off; } access_log off; error_log /var/log/nginx/example.com-error.log error; error_page 404 /index.php; location ~ \.php$ { fastcgi_split_path_info ^(.+\.php)(/.+)$; fastcgi_pass unix:/var/run/php/php8.1-fpm.sock; fastcgi_index index.php; include fastcgi_params; } location ~ /\.(?!well-known).* { deny all; } } # FORGE CONFIG (DO NOT REMOVE!) include forge-conf/example.com/after/*;
After restarting Nginx, your SSL certificate should be added successfully!