# `push.sh`

John Simpson `<jms1@jms1.net>` 2019-08-11

Last update: 2020-09-22

Master copy:

* `/keybase/public/jms1/notes/ACME/push.sh/index.md`
* [`https://jms1.keybase.pub/notes/ACME/push.sh/`](https://jms1.keybase.pub/notes/ACME/push.sh/)

**THIS DOCUMENT IS STILL IN PROGRESS.** Do not trust anything you read here. Or anywhere else, for that matter.

# Background

**ACME**, or Automatic Certificate Management Environment, is a protocol which allows SSL certificates to be issued, renewed, or revoked, without human intervention. The protocol has been formalized as
[RFC 8555](https://tools.ietf.org/html/rfc8555). Because the protocol is open, anybody is free to write their own clients, and any CA is free to write their own server software.

**[Let's Encrypt](https://letsencrypt.org/)** was the first Certification Authority to support the protocol, and was heavily involved in designing both the protocol and the first server implementation, [boulder](https://github.com/letsencrypt/boulder), which is [licensed](https://github.com/letsencrypt/boulder/blob/master/LICENSE.txt) under the [Mozilla Public License 2.0](https://www.mozilla.org/en-US/MPL/2.0/), and is therefore available to be used by any other CA.
 
**[`acme.sh`](https://github.com/Neilpang/acme.sh)** is an ACME client, written as a pure shell script. I started using it a few years ago, because it is a pure shell script, and because it doesn't have any unusual third-party dependencies (i.e. I don't need to install the runtime for an entire new language in order to use it). It comes with a set of "plug-ins" for updating DNS records and deploying key/cert files.

**`push.sh`** is a deployment plug-in that I have written for `acme.sh`. It uses `scp` or `ssh` to deploy key/cert files to remote machines, and is also able to run commands on remote machines as well. The script uses its own configuration file to control which files need to be pushed to which filenames on each machine, along with any commands need to be run before or after pushing those files.

**`push.conf`** is the configuration file for `push.sh`.

### Other considerations

This document was written with the following assumptions in mind:

* The machines on which you run `acme.sh` and this plugin, are running an operating system which provides a real *nix filesystem. I use both macOS and Linux as workstations.

    I've heard that Microsoft is adding some kind of Linux environment within Windows, but I know nothing about it, and have neither a machine, nor the interest, in trying it. If you're able to make `acme.sh` and this plugin work, and you write up directions on how to do so, let me know so I can add a link to your document.

* You are already familiar with normal system administration for the relevant systems, bot the workstation where you run `acme.sh` and the machines to which the resulting SSL key/cert files will be deployed. I will try to show a reasonable amount of detail, but this document isn't going to teach you how to administer your machines.

* You are already familiar with how SSL keys and certificates work, and how Let's Encrypt fits into that process.

# Installation

### Install `acme.sh`

See [the `acme.sh` documentation](https://github.com/Neilpang/acme.sh) for directions on how to install `acme.sh`.

**Remember the directory in which you installed `acme.sh` and its associated files.** In my case the real directories are within Keybase - my personal stuff is within `/keybase/private/jms1/` and at work we use a Keybase team directory.

The `acme.sh` installation process normally modifies your shell environment so that you have an environment variable called `LE_WORKING_DIR`, pointing to the directory where the `acme.sh` script and its plugins live. The default location for this is "`$HOME/.acme.sh/`", however my own installations used Keybase directories for this. The directions below assume that this environment variable is set up correctly.

### Install `push.sh`

Copy the `push.sh` script into your `acme.sh` installation's `deploy/` directory.

* If you're using Keybase to access these files...

    ```
    cd $LE_WORKING_DIR/deploy/
    cp /keybase/public/jms1/notes/ACME/push.sh/push.sh .
    chmod 0755 push.sh
    ```

* If you're not using Keybase...

    ```
    cd $LE_WORKING_DIR/deploy/
    curl -O https://jms1.keybase.pub/notes/ACME/push.sh/push.sh
    chmod 0755 push.sh
    ```

# Target Machine configuration

The `push.sh` script relies on being able to access the `root` account on the target machines.

## SSH Authentication

The `push.sh` script uses either `scp` or `ssh` to access the machines to which it pushes files. Obviously this requires that you have SSH access to these machines, however your life will be *much* easier if you're able to SSH into these machines using keys to authenticate, rather than having to type in a password for *every single file and command*.

Setting this up is outside the scope of this document. If you aren't already using SSH in this manner, you should be able to do an internet search for "`ssh without password`" and find hundreds of different pages which explains how to set it up. I even wrote [a page about this](https://jms1.net/ssh.shtml) years ago.

## Access to `root`

There are two ways for the script to access the `root` account: directly (which I use for my personal machines), or using the `sudo` command (which I use at work).

### Direct access

This is easy to set up: just add your SSH public key to the `root` user's `$HOME/.ssh/authorized_keys` file.

Assuming you've already created a `$HOME/.ssh/authorized_keys` file for your normal user, the process might look something like this:

```
[user@target ~]$ sudo -i
Password:
[root@target ~]# cd .ssh
[root@target ~/.ssh]# cat ~user/.ssh/authorized_keys >> authorized_keys
[root@target ~/.ssh]# exit
[user@target ~] $
```

You can test this from your local workstation, by trying to `ssh` directly into the `root` account on the target machine:

```
[user@laptop ~]$ ssh root@target
  (if it works, you will NOT be prompted for a password here)
[root@target ~]# id
uid=0(root) gid=0(root) groups=0(root)
[root@target ~]# exit
[user@laptop ~]$
```

### Using `sudo`

This is a bit more complicated.

TODO

# Configure the plugin

The plugin is configured using a file called `push.conf`, in the same directory with the `acme.sh` script itself.

### Copy the sample file

Start by copying the sample file.

* If you're using Keybase...

    ```
    cd $LE_WORKING_DIR
    cp /keybase/public/jms1/notes/ACME/push.sh/push.conf.sample push.conf
    ```

* If you're not using Keybase...

    ```
    cd $LE_WORKING_DIR
    curl -O https://jms1.keybase.pub/notes/ACME/push.sh/push.conf.sample
    mv push.conf.sample push.conf
    ```

## Customize the `push.conf` file

**TODO** - details

See comments at the top of the [`push.conf.sample`](push.conf.sample) file

# Using the plugin

Once the `push.conf` file has the correct entries for a certificate, you can use it like any other deployment plugin.

For example, if I needed to deploy the certificate for `jms1.net`, the command might look something like this:

```
./acme.sh --deploy \
    --deploy-hook push \
    -d jms1.net
```
