How to Get Free 90‑Day HTTPS SSL with acme.sh, Docker, and Nginx
This guide walks you through three practical ways—using SSL For Free, the acme.sh script, and a Docker container—to obtain free 90‑day Let’s Encrypt certificates, configure DNS verification on Alibaba Cloud, automate renewal, and integrate the certificates into Nginx for secure HTTPS access.
Overview
This article describes three practical ways to obtain free Let’s Encrypt SSL certificates (valid for 90 days) and to configure Nginx to use them: (1) manual DNS verification via the SSL For Free service, (2) fully automated DNS‑API issuance with acme.sh, and (3) a Docker‑based workflow that runs acme.sh inside a container.
Method 1 – Manual DNS (SSL For Free)
Open the SSL For Free website and register an account with an email address.
Enter one or more domain names (e.g., sslforfree1.tinywan.com sslforfree2.tinywan.com) and choose DNS verification (Manual Verification) .
Copy the provided TXT record value and add it to the domain’s DNS zone (the article shows an example for Alibaba Cloud).
After the DNS record propagates, click the verification button; the service will generate three files: certificate.crt, private.key, and ca_bundle.crt.
Save the files in a directory (e.g., /sslforfree/) and add the following server block to Nginx:
server {
server_name xxx.com;
listen 443 http2 ssl;
ssl_certificate /sslforfree/certificate.crt;
ssl_certificate_key /sslforfree/private.key;
ssl_trusted_certificate /sslforfree/ca_bundle.crt;
location / {
proxy_pass http://127.0.0.1:6666;
}
}Method 2 – Automated DNS with acme.sh (Recommended)
Install acme.sh (the script clones itself into ~/.acme.sh and adds a wrapper to ~/.bashrc). On CentOS 7, run source ~/.bashrc after opening a new terminal if the command is not found.
Obtain an App_Key and App_Secret from the Alibaba Cloud DNS console (these are the AccessKey ID and Secret).
Export the credentials in the shell and issue the certificate, including a wildcard if needed:
# Replace with your Alibaba Cloud credentials
export Ali_Key="YOUR_APP_KEY"
export Ali_Secret="YOUR_APP_SECRET"
# Issue for a domain and its wildcard
acme.sh --issue --dns dns_ali -d zhuziyu.cn -d "*.zhuziyu.cn"The script pauses for 120 seconds to allow DNS propagation before validation.
Certificates are stored under /home/www/.acme.sh/ (e.g., fullchain.cer, domain.key, ca.cer).
A cron job is automatically added to renew the certificates daily at 00:00:
19 0 * * * "/home/www/.acme.sh"/acme.sh --cron --home "/home/www/.acme.sh" > /dev/nullExample Nginx configuration for the issued domain:
server {
server_name xx.domain.com;
listen 443 http2 ssl;
ssl_certificate /path/.acme.sh/domain/fullchain.cer;
ssl_certificate_key /path/.acme.sh/domain/domain.key;
ssl_trusted_certificate /path/.acme.sh/domain/ca.cer;
location / {
proxy_set_header X-Forwarded-For $proxy_add_forwarded_for;
proxy_set_header Host $host;
proxy_pass http://127.0.0.1:10086;
}
}Advantages: fully automated DNS record updates, no Python dependency, and built‑in renewal.
Method 3 – Docker + acme.sh
Run the official neilpang/acme.sh image, mounting a host directory to persist the certificates and passing the Alibaba Cloud credentials as environment variables:
docker run --rm -it \
-v "D:\Git\docker-lnmp\dev
ginx\v5\etc\letsencrypt":/acme.sh \
-e Ali_Key="LTAIn" -e Ali_Secret="zLzA" \
neilpang/acme.sh --issue --dns dns_ali \
-d tinywan.top -d "*.tinywan.top"The container logs show account registration, domain key creation, a 120‑second sleep for TXT record propagation, successful verification, and the final certificate files saved under /acme.sh/tinywan.top/.
Typical certificate locations after the container exits:
Linux: /home/www/openssl Windows:
D:\Git\docker-lnmp\dev
ginx\v5\etc\letsencryptNginx SSL Configuration (nginx.conf excerpt)
user www;
worker_processes auto;
error_log /var/log/nginx/error.log error;
pid /run/openresty.pid;
worker_rlimit_nofile 204800;
events {
worker_connections 65535;
multi_accept on;
use epoll;
}
http {
charset utf-8;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
server_tokens off;
log_not_found off;
types_hash_max_size 2048;
client_max_body_size 16M;
include mime.types;
default_type application/octet-stream;
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log warn;
# SSL settings
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:50m;
ssl_session_tickets off;
ssl_protocols TLSv1.2;
ssl_ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256;
ssl_prefer_server_ciphers on;
ssl_stapling on;
ssl_stapling_verify on;
resolver 1.1.1.1 1.0.0.1 8.8.8.8 8.8.4.4 208.67.222.222 208.67.220.220 valid=60s;
resolver_timeout 2s;
more_set_headers "X-Frame-Options: SAMEORIGIN";
include "/usr/local/openresty/nginx/conf/conf.d/*.conf";
}Troubleshooting
If the luarocks command is not found, invoke it with its absolute path, for example:
sudo /usr/local/openresty/luajit/bin/luarocksReferences
GitHub repository for lua‑resty‑auto‑ssl: https://github.com/GUI/lua-resty-auto-ssl
Ubuntu guide for automated Let’s Encrypt with Nginx/OpenResty
OpenResty auto‑sign Let’s Encrypt tutorial
FRP intranet penetration with HTTPS
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Open Source Tech Hub
Sharing cutting-edge internet technologies and practical AI resources.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
