LetsEncrypt SSL cert on GoDaddy Shared Hosting with No Root and No nc

$ acme.sh --issue -d mydomain.com -d www.mydomain.com -w ~/www

Looks simple, doesn't it?

Nope. Here's what you have to do to get to that point.

(The following Worked For Me™ on shared GoDaddy hosting, where the server was running Linux and Apache, but I don't think there's any Apache-specific commands, so if you're running Nginx + Linux, I think the following will work fine. If you're running Windows rather than Linux, the following tutorial will not work.)

Log into GoDaddy and give yourself SSH access

Here's how... actually, since the GoDaddy docs are painful to read, here's a screenshot instead:

Go do your CPanel and scroll down till you find this section, then click "SSH Access" and then "Enable":

Note: later you'll return to the same "Security" section and click "SSL/TLS" to upload the LetsEncrypt/acme.sh-generated cert and (private) key.

Then generate a new SSH key on your local machine at ~/.ssh/mydomain add its public key to GoDaddy.

ssh-keygen -b 4096

/home/YOURUSERNAMEHERE/.ssh/mydomain
<ENTER> (empty passphrase)  
<ENTER> (repeat empty passphrase)

echo  
cat ~/.ssh/mydomain.pub  

(Copy and paste that pub key to GoDaddy, then authorize that user to connect via SSH; adding a key is not enough, strangely.)

SSH in

ssh -i .ssh/mydomain t$YOUR_CUSTOMER_NUMBER@$YOUR_DOMAIN.com  

Yes, that's right... even though GoDaddy says here that you can use "[y]our account's primary username" to log in, that doesn't work (I checked 3 times).

You need to use lower-case t, followed by your GoDaddy membership number (which you often log in with as your username), then @, then your domain.

Even though you're authenticating via SSH, you must also now type in a password at the command line. This is your normal account password.

(Oh, and if you get some sort of ssh_exchange_identification: read: Connection reset by peer error, turn off your VPN; GoDaddy doesn't like people SSHing in from those.)

Download and install acme.sh

acme.sh is a full implementation of a LetsEncrypt client but that doesn't depend on Python/pip/virtualenv/etc, and that doesn't require root -- exactly what we need, since we don't have root an a shared GoDaddy server, and we can't install new software outside of our home directory.

curl https://get.acme.sh | sh  

Now log out and SSH back in so acme.sh's install is complete in every way (include the Bash alias).

Download a statically-compiled version of netcat

...from a GitHub repo of hacker tools that are hopefully not backdoored.

Why? Well, acme.sh is written in Bash, Bash of course doesn't have a native web server, so it uses nc (aka "netcat") as a webserver to serve files to LetsEncrypt to prove you own the domain, etc etc:

mkdir bin  
cd bin  
wget  
https://github.com/ZephrFish/static-tools/blob/master/netcat?raw=true -O nc  
chmod +x nc  

I have no particular reason to trust this binary, so if you have a better solution, please let me know!

(Luckily, GoDaddy puts ~/bin in your $PATH by default, so when acme.sh runs nc, it'll find it.)

Now it'll work!... but you're still not done

acme.sh --issue -d MYDOMAIN.com -d www.MYDOMAIN.com -w ~/www  

(Yes, literally ~/www, no trailing /.)

Boom! You should have just gotten your first good news of the day -- your cert, cert key, intermediate CA cert, and full cert chain have been generated!

...but GoDaddy still doesn't know that the cert exists, so it's not using it.

Upload cert and private key via GoDaddy's web interface

Handy instructions on how to do that here that I've copied and pasted just for you, in case the just-mentioned ones disappear (note that the "SSL/TLS" link mentioned here is in the "Security" section of your CPanel -- the same place you enabled SSH above):

  1. Home > SSL/TLS > Certificate (CRT) (Generate, view, upload, or delete SSL certificates.).
  2. Copy/Paste the contents of your cer file (acme.sh folder) into the "Upload a New Certificate" textbox.
  3. Click on "Save certificate", then "Go back".
  4. Now go to: Install and Manage SSL for your site (HTTPS) (Manage SSL sites.).
  5. Under "Install an SSL website" select the required domain/subdomain.
  6. Select "Autofill".
  7. Enter the contents of the corresponding key file in the "Private Key (KEY)" textbox.
  8. Click on "Install certificate".

So close!

To take stock: we've generated a LetsEncrypt cert for our domain, acme.sh installed a cronjob that'll auto-renew it(!) (run crontab -l if you don't believe me), and we've now given this cert to GoDaddy so it can use it to host a secure version of our site.

So we're done!... right?

Almost.

GoDaddy doesn't automatically redirect from the HTTP version of your site to the HTTPS version. Here's how to do that:

SSH in, then run

nano www/.htaccess  

Then, right after

# BEGIN WordPress
<IfModule mod_rewrite.c>  
RewriteEngine On  

add these 2 lines:

RewriteCond %{HTTPS} off  
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]  

(Here's GoDaddy's arguably more complete, but in my case misleading instructions on how to supposedly do this in a non-WordPress environment.)

...aaaand -- finally -- that's it!

(P.S. Don't use GoDaddy for anything unless you're helping a friend who's already locked in there like I was; use NameCheap instead.)