-
-
Save davidbalbert/6815258 to your computer and use it in GitHub Desktop.
| ########################################### | |
| # IMPORTANT NOTE: | |
| # | |
| # As of asuswrt-merlin 380.67 Beta, you | |
| # can now configure SSL certificates from | |
| # the Webui, making these instructions | |
| # unnecessary. | |
| ########################################### | |
| # First, enable SSH in the Administration->System tab. | |
| # Then log in to the device. | |
| # Verify that https_crt_save is off | |
| admin@RT-N66U:/tmp/home/root# nvram get https_crt_save | |
| 0 | |
| # Enable https_crt_save and verify that it was set correctly | |
| admin@RT-N66U:/tmp/home/root# nvram set https_crt_save=1 | |
| admin@RT-N66U:/tmp/home/root# nvram get https_crt_save | |
| 1 | |
| # Write your custom key and certificate to the ephemeral file system. | |
| # Note that these files will not be preserved on restart. | |
| admin@RT-N66U:/tmp/home/root# cat >/etc/key.pem | |
| # paste in key | |
| admin@RT-N66U:/tmp/home/root# cat >/etc/cert.pem | |
| # paste in cert | |
| # Verify https_crt_file is empty | |
| admin@RT-N66U:/tmp/home/root# nvram get https_crt_file | |
| admin@RT-N66U:/tmp/home/root# | |
| # Restart httpd. When httpd starts up with https_crt_save enabled, it does the | |
| # following: If /etc/cert.pem and /etc/key.pem exist, it tars them together and | |
| # saves them in https_crt_file. If they do not exist (this would be the case | |
| # on reboot) and https_crt_file exists, httpd will extract the contents of | |
| # https_crt_file. You can see how this works in the start_ssl function here: | |
| # https://github.com/RMerl/asuswrt-merlin/blob/master/release/src/router/httpd/httpd.c | |
| admin@RT-N66U:/tmp/home/root# service restart_httpd | |
| # Ensure https_crt_file is now full | |
| admin@RT-N66U:/tmp/home/root# nvram get https_crt_file | |
| # ...snip... | |
| # Reboot AP to make sure cert is put back on boot | |
| admin@RT-N66U:/tmp/home/root# reboot |
GitHubbie0836
commented
Sep 17, 2025
Root cause: missing Basic Constraints in the server cert (ASUS httpd requirement)
If you’re seeing Merlin fall back to the default RT-AX86U-XXXX Server Certificate even though your custom cert uploads successfully, the issue is not Merlin, not NVRAM, and not cert.tgz structure.
The issue is the X.509 extensions.
ASUS’s embedded httpd strictly requires the server certificate to explicitly contain:
X509v3 Basic Constraints:
CA:FALSE
If this extension is missing or not parsable, httpd will log something like:
httpd: Can't get basic constrain from /jffs/.cert/cert.pem
httpd: Delete uploaded certificate
Then silently reverts to the auto-generated ASUS certificate.
Cause of mkcert failure (Theory)
mkcert generates valid browser certificates, but some server certificates don't include an explicit basicConstraints = CA:FALSE entry in a format ASUS’s stripped-down OpenSSL parser accepts.
Fix: generate the router cert with OpenSSL & explicit extensions
Use OpenSSL directly for the router cert and explicitly declare Basic Constraints.
Example router-openssl.conf:
[ req ]
default_bits = 2048
prompt = no
default_md = sha256
distinguished_name = dn
req_extensions = req_ext
[ dn ]
CN = router.lan
[ req_ext ]
basicConstraints = CA:FALSE
keyUsage = digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth
subjectAltName = @alt_names
[ alt_names ]
DNS.1 = router.lan
IP.1 = 192.168.1.1
Generate and sign with your local CA (mkcert’s CA works fine):
openssl genrsa -out router-key.pem 2048
openssl req -new -key router-key.pem -out router.csr -config router-openssl.cnf
openssl x509 -req \
-in router.csr \
-CA rootCA.pem \
-CAkey rootCA-key.pem \
-CAcreateserial \
-out router.pem \
-days 3650 \
-sha256 \
-extensions req_ext \
-extfile router-openssl.cnfYou can verify this by using:
openssl x509 -in router.pem -noout -text | grep -A4 "Basic Constraints"Expected Output:
X509v3 Basic Constraints:
CA:FALSE
Certificate & key requirements
| Requirement | Source |
|---|---|
| Certificate must be PEM | Implicitly supported by ASUS documentation |
| Must be RSA (not ECDSA) | Common community reports (e.g., GitHub, SNBForums) |
| Subject Alternative Name (SAN) required | Older guides and community usage assume SAN for hostname matching |
Basic Constraints: CA:FALSE |
Supported by community discussions and httpd rejection logs |
| X509v3 Subject Key Identifier (SKI) & Authority Key Identifier (AKI) | Explicitly mentioned by commenters in Merlin-related discussions |
Correct tar layout (/jffs/cert.tgz) |
Part of documented ASUSWRT-Merlin workflow |
NVRAM flags (https_crt_save=1) |
Known ASUSWRT-Merlin requirement |
Requirements are not Merlin-specific and are enforced by ASUS’s embedded httpd and OpenSSL build.
Merlin simply exposes the failure logs and allows persistence of custom certificates, which makes the issue debuggable.
Summary
- Not a Merlin bug
- Not an NVRAM or cert.tgz issue
- ASUS httpd enforces strict X.509 parsing
- Missing or malformed Basic Constraints causes silent cert rejection
- OpenSSL with explicit CA:FALSE resolves the issue permanently