Installing Let's Encrypt SSL Certificates On Namecheap Hosting: Difference between revisions

From Littledamien Wiki
Jump to navigation Jump to search
No edit summary
 
(25 intermediate revisions by the same user not shown)
Line 1: Line 1:
== Installing a certificate for the first time ==
== Acme.sh ==


This [https://gist.github.com/Shourai/bfd9f549a41c836c99c0c660c9271df6 Gist] has detailed instructions on how to install a Let's Encrypt SSL certificate for a web site hosted on Namecheap.
[https://github.com/acmesh-official/acme.sh acme.sh overview]


It references [https://github.com/diafygi/acme-nosudo this Python script] which conducts the challenge with Let's Encrypt that verifies control of the domain(s).
In theory, his process only needs to be performed once. Running the acme.sh script creates a cron job that will handle certificate renewals.  


== Renewing the certificate ==
* [https://github.com/acmesh-official/acme.sh/wiki/Simple-guide-to-add-TLS-cert-to-cpanel How to use acme.sh with cPanel for automatically renewing Let's Encrypt SSL] (Gist)
* [https://dev.to/atomar/let-s-encrypt-ssl-certificate-in-namecheap-autorenewal-verified-working-using-acme-sh-4m7i Let’s Encrypt SSL certificate in Namecheap AutoRenewal – Verified & working – Using ACME.sh] (dev.to)<br />Same basic instructions as above, but with comments and some extra information.


<div class="alert alert-warning">Todo: figure out if there is a way to automate renewing the certificate. Right now it seems that it requires manually entering commands into a terminal.</div>
=== Installing certificates ===
 
==== Run a test install ====
 
`--webroot` points to the working root of the website. If there is an "app" subdirectory that contains the web root, this path will need to reflect that.
 
<syntaxhighlight lang="bash">
$ acme.sh --issue --webroot ~/damienjay.com -d www.mydomain.com -d mydomain.com -d etc.mydomain.com --staging
</syntaxhighlight>
 
==== Run the actual certificate installation ====
 
<syntaxhighlight lang="bash">
$ acme.sh --issue --webroot ~/damienjay.com -d www.mydomain.com -d mydomain.com -d etc.mydomain.com --force
</syntaxhighlight>
 
==== Apply the certificate to the site in cPanel ====
 
There is only one domain identifier for the website. This is the first domain listed for the site when issuing the certificate in the previous step.
 
<syntaxhighlight lang="bash">
$ acme.sh --deploy --deploy-hook cpanel_uapi --domain www.mydomain.com
</syntaxhighlight>
 
==== Make certificate active in cPanel ====
 
It's still necessary to make this the active certificate in cPanel.
 
* '''cPanel''' > '''Security''' > '''SSL/TLS''' > '''Certificates (CRT)''' > '''Generate, view, upload, or delete certificates'''
* Locate the new certificate in the list > Click the '''Install''' link to the right of the certificate.
* Under '''Manage Installed SSL Websites''' locate the new certificate
* Click '''Make primary''' to the right of the certificate.
 
At this point the new certificate should handling secure requests on the website.
 
==== Delete old certificates ====
 
Clean up older certificates in cPanel.
 
* Click '''Return to SSL Manager''' at the bottom of the page.
* '''Certificates (CRT)''' > '''Generate, view, upload, or delete certificates'''
* Delete any certificates for the domain in question with older expiration dates.
 
=== Listing websites managed by acme.sh ===
 
At a command prompt on the server, list the contents of `~/.acme.sh`. Each certificate managed by acme.sh will have its own directory here.
 
<syntaxhighlight lang="shell">
$ ls ~/.acme.sh
</syntaxhighlight>
 
=== Updating acme.sh ===
 
<syntaxhighlight lang="shell">
$ acme.sh --upgrade
</syntaxhighlight>
 
=== Specifying default acme.sh CA server ===
 
<syntaxhighlight lang="shell">
$ acme.sh --set-default-ca --server letsencrypt
</syntaxhighlight>
 
See [https://github.com/acmesh-official/acme.sh/wiki/Server https://github.com/acmesh-official/acme.sh/wiki/Server]
 
== Renewals ==
 
Renewals are supposed to happen automatically after installing a certificate with `acme.sh`, but I have been receiving expiration notices for domains up to two days prior to the expiration date. Not sure when exactly a domain would be renewed?
 
== Confirm expiration date of a certificate ==
 
=== Using a browser ===
 
* Load the site in a Chrome browser.
* Open '''Developer Tools'''.
* Click the '''Security''' tab.
* '''Certificate''' > '''View Certificate''' button.
* Expiration Date is displayed in the dialog.
 
=== Using cPanel ===
 
* Log into cPanel.
* '''Security''' > '''SSL/TLS'''
* '''Generate, view, upload, or delete SSL certificates''' will show who issued the certificates in use.
* '''Manage SSL Sites''' will show which sites have certificates, and when those certificates expire.
 
== Troubleshooting ==
 
=== Script doesn't have access to `/.well-known/acme-challenge` ===
 
The script reports it can't access `http://mysite.com/.well-known/acme-challenge/[VERIFICATION_FILE]`.
 
Make sure if the web root is in a subdirectory, that you include the subdirectory in the `--webroot` argument!!! e.g. `--webroot ~/mysite.com/app`
 
=== Certificate not renewing ===
 
After installing a certificate with `acme.sh` it should be renewed automatically. However, it's possible to [https://github.com/acmesh-official/acme.sh#12-how-to-renew-the-certs manually renew certificates].
 
=== Certificate failing to verify on password-protected server ===
 
'''Use case'''
 
The server is password-protected with `.htaccess` directives.
 
'''Resolution'''
 
==== Option 1 ====
 
Edit the `.htaccess` file installed in the web app root directory.
 
<syntaxhighlight lang="ApacheConf" highlight="2,8,9,10,12">
# Authentication exception for validating the server when issuing SSL certificates
SetEnvIf Request_URI ^/.well-known/acme-challenge/ noauth=1
 
# login prompt
AuthType Basic
AuthUserFile "/path/to/auth/file"
<RequireAny>
Order Deny,Allow
Satisfy Any
Deny from all
Require valid-user
Allow from env=noauth
</RequireAny>
 
</syntaxhighlight>
 
==== Option 2 ====
 
Make an exception for directory `.well-known/acme-challenge/` but placing an `.htaccess` file there with the following contents:
 
<syntaxhighlight lang="ApacheConf">
require all granted
</syntaxhighlight>
 
<p class="alert alert-warning">This seems like the cleaner solution, but in at least one instance (June 2023) it did not work as needed.
 
=== Certificate failing to verify using .well-known challenge ===
 
'''Use case'''
 
* Log into the server using ssh.
* Run `acme.sh` script from the command line to renew certificate.
* There will be errors to effect of `"verify error"` and `"invalid response from [domain]/.well-knonwn/acme-challenge/..."`.
 
'''Cause'''
 
Permissions errors prevent the script from writing the file to `.well-known/acme-challenge/` that is used to verify ownership of the domain.
 
'''Fix'''
 
The last time this happened, I compared the permissions for the web roots and `.well-known` directories for two sites hosted on the same server where one site's certificate was being renewed and the other was failing. I could not find any differences in the permissions.
 
What I ended up doing was to move the root directory of the site, create a new directory for the site, put a potboiler index html page in the directory, and then run the acme script. After this allowed me to renew the certificate, I copied all the content from the original directory back into the new one.
 
'''Also!''' Remember that the root of many of the web apps is in the `app/` subdirectory! When issuing the certificate make sure to set the web root option appropriately, e.g. `--webroot ~/mydomain.com/app`
 
=== Timeout polling order status while issuing certificate ===
 
'''Use case'''
 
Manually issue a certificate with the following command:


* SSH to the server.
* Navigate to the directory containing Let's Encrypt keys and scripts, e.g. `~/letsencrypt/letsencrypt_nosudo/`
* Generate a new signed certificate:
<syntaxhighlight lang="bash">
<syntaxhighlight lang="bash">
python sign_csr.py -f --public-key user.pub ./[DOMAIN]/domain.csr > ./[DOMAIN]/signed.crt
$ acme.sh --issue --webroot ~/my_webapp_root -d mydomain.com --force
</syntaxhighlight>
</syntaxhighlight>


This will first prompt for an admin email address.
'''Expected result'''
 
`acme.sh` sends request to the CA server and receives successful response.
 
'''Actual result'''


Then it will prompt for a series of commands to be entered, which create JSON files that are used by the signing script.
<pre>
[Sat Apr  9 17:40:56 EDT 2022] Polling order status: https://acme.zerossl.com/v2/DV90/order/dtElfwFq1sLFiXaP188uDw
[Sat Apr  9 17:40:59 EDT 2022] Order status is processing, lets sleep and retry.
[Sat Apr  9 17:40:59 EDT 2022] Retry after: 15
[Sat Apr  9 17:41:15 EDT 2022] Polling order status: https://acme.zerossl.com/v2/DV90/order/dtElfwFq1sLFiXaP188uDw
[Sat Apr  9 17:41:18 EDT 2022] Order status is processing, lets sleep and retry.
[Sat Apr  9 17:41:18 EDT 2022] Retry after: 15
</pre>


Then it will prompt for a file to be installed on the server for each of the subdomains included in the certificate.
Over and over again until finally the script times out with an error similar to this:


(Those are the three steps that would need to be automated somehow.)
<pre>
[Sat Apr  9 17:42:29 EDT 2022] Sign error, wrong status
</pre>


After verifying each of the domains, a signed certificate is created.
'''Solution'''


The certificate is installed with: <ref>[https://gist.github.com/Shourai/bfd9f549a41c836c99c0c660c9271df6#gistcomment-2351618 Using uapi tool to install certificates]</ref>
This happened using the default acme.sh CA server which is ZeroSSL. Changing the default CA server to Let's Encrypt fixed this.


<syntaxhighlight lang="bash">
<syntaxhighlight lang="bash">
crt=`cat ./[DOMAIN]/signed.crt | python urlencode.py`
$ acme.sh --set-default-ca --server letsencrypt
key=`cat ./[DOMAIN]/.key | python urlencode.py`
uapi SSL install_ssl domain=[MYDOMAIN.TLD] cert="$crt" key="$key"
</syntaxhighlight>
</syntaxhighlight>


== See also ==
== See also ==
[[Let's Encrypt SSL Certificates on Namecheap Hosting (Legacy)]]
<references />
<references />


[[Category:SSL]][[Category:Web Hosting]][[Category:Web Development]]
[[Category:SSL]][[Category:Web Hosting]][[Category:Web Development]]

Latest revision as of 12:22, 30 November 2024

Acme.sh[edit]

acme.sh overview

In theory, his process only needs to be performed once. Running the acme.sh script creates a cron job that will handle certificate renewals.

Installing certificates[edit]

Run a test install[edit]

--webroot points to the working root of the website. If there is an "app" subdirectory that contains the web root, this path will need to reflect that.

$ acme.sh --issue --webroot ~/damienjay.com -d www.mydomain.com -d mydomain.com -d etc.mydomain.com --staging

Run the actual certificate installation[edit]

$ acme.sh --issue --webroot ~/damienjay.com -d www.mydomain.com -d mydomain.com -d etc.mydomain.com --force

Apply the certificate to the site in cPanel[edit]

There is only one domain identifier for the website. This is the first domain listed for the site when issuing the certificate in the previous step.

$ acme.sh --deploy --deploy-hook cpanel_uapi --domain www.mydomain.com

Make certificate active in cPanel[edit]

It's still necessary to make this the active certificate in cPanel.

  • cPanel > Security > SSL/TLS > Certificates (CRT) > Generate, view, upload, or delete certificates
  • Locate the new certificate in the list > Click the Install link to the right of the certificate.
  • Under Manage Installed SSL Websites locate the new certificate
  • Click Make primary to the right of the certificate.

At this point the new certificate should handling secure requests on the website.

Delete old certificates[edit]

Clean up older certificates in cPanel.

  • Click Return to SSL Manager at the bottom of the page.
  • Certificates (CRT) > Generate, view, upload, or delete certificates
  • Delete any certificates for the domain in question with older expiration dates.

Listing websites managed by acme.sh[edit]

At a command prompt on the server, list the contents of ~/.acme.sh. Each certificate managed by acme.sh will have its own directory here.

$ ls ~/.acme.sh

Updating acme.sh[edit]

$ acme.sh --upgrade

Specifying default acme.sh CA server[edit]

$ acme.sh --set-default-ca --server letsencrypt

See https://github.com/acmesh-official/acme.sh/wiki/Server

Renewals[edit]

Renewals are supposed to happen automatically after installing a certificate with acme.sh, but I have been receiving expiration notices for domains up to two days prior to the expiration date. Not sure when exactly a domain would be renewed?

Confirm expiration date of a certificate[edit]

Using a browser[edit]

  • Load the site in a Chrome browser.
  • Open Developer Tools.
  • Click the Security tab.
  • Certificate > View Certificate button.
  • Expiration Date is displayed in the dialog.

Using cPanel[edit]

  • Log into cPanel.
  • Security > SSL/TLS
  • Generate, view, upload, or delete SSL certificates will show who issued the certificates in use.
  • Manage SSL Sites will show which sites have certificates, and when those certificates expire.

Troubleshooting[edit]

Script doesn't have access to /.well-known/acme-challenge[edit]

The script reports it can't access http://mysite.com/.well-known/acme-challenge/[VERIFICATION_FILE].

Make sure if the web root is in a subdirectory, that you include the subdirectory in the --webroot argument!!! e.g. --webroot ~/mysite.com/app

Certificate not renewing[edit]

After installing a certificate with acme.sh it should be renewed automatically. However, it's possible to manually renew certificates.

Certificate failing to verify on password-protected server[edit]

Use case

The server is password-protected with .htaccess directives.

Resolution

Option 1[edit]

Edit the .htaccess file installed in the web app root directory.

# Authentication exception for validating the server when issuing SSL certificates 
SetEnvIf Request_URI ^/.well-known/acme-challenge/ noauth=1

# login prompt
AuthType Basic
AuthUserFile "/path/to/auth/file"
<RequireAny>
	Order Deny,Allow
	Satisfy Any
	Deny from all
	Require valid-user
	Allow from env=noauth
</RequireAny>

Option 2[edit]

Make an exception for directory .well-known/acme-challenge/ but placing an .htaccess file there with the following contents:

require all granted

This seems like the cleaner solution, but in at least one instance (June 2023) it did not work as needed.

Certificate failing to verify using .well-known challenge[edit]

Use case

  • Log into the server using ssh.
  • Run acme.sh script from the command line to renew certificate.
  • There will be errors to effect of "verify error" and "invalid response from [domain]/.well-knonwn/acme-challenge/...".

Cause

Permissions errors prevent the script from writing the file to .well-known/acme-challenge/ that is used to verify ownership of the domain.

Fix

The last time this happened, I compared the permissions for the web roots and .well-known directories for two sites hosted on the same server where one site's certificate was being renewed and the other was failing. I could not find any differences in the permissions.

What I ended up doing was to move the root directory of the site, create a new directory for the site, put a potboiler index html page in the directory, and then run the acme script. After this allowed me to renew the certificate, I copied all the content from the original directory back into the new one.

Also! Remember that the root of many of the web apps is in the app/ subdirectory! When issuing the certificate make sure to set the web root option appropriately, e.g. --webroot ~/mydomain.com/app

Timeout polling order status while issuing certificate[edit]

Use case

Manually issue a certificate with the following command:

$ acme.sh --issue --webroot ~/my_webapp_root -d mydomain.com --force

Expected result

acme.sh sends request to the CA server and receives successful response.

Actual result

[Sat Apr  9 17:40:56 EDT 2022] Polling order status: https://acme.zerossl.com/v2/DV90/order/dtElfwFq1sLFiXaP188uDw
[Sat Apr  9 17:40:59 EDT 2022] Order status is processing, lets sleep and retry.
[Sat Apr  9 17:40:59 EDT 2022] Retry after: 15
[Sat Apr  9 17:41:15 EDT 2022] Polling order status: https://acme.zerossl.com/v2/DV90/order/dtElfwFq1sLFiXaP188uDw
[Sat Apr  9 17:41:18 EDT 2022] Order status is processing, lets sleep and retry.
[Sat Apr  9 17:41:18 EDT 2022] Retry after: 15

Over and over again until finally the script times out with an error similar to this:

[Sat Apr  9 17:42:29 EDT 2022] Sign error, wrong status

Solution

This happened using the default acme.sh CA server which is ZeroSSL. Changing the default CA server to Let's Encrypt fixed this.

$ acme.sh --set-default-ca --server letsencrypt

See also[edit]

Let's Encrypt SSL Certificates on Namecheap Hosting (Legacy)