Quick manual deploy to EC2 with github
Tags: github, webdev, deploy, tutorial
Published: 2021-03-12 03:54:52

This article is about my preferred way to bootstrap a deploy process ASAP (with AWS/EC2). It is most useful for prototyping ideas or publishing solo projects. For more mature projects, I've used a variety of other deploys styles - which are all more expensive to set up.

I use a simple on-demand instance in EC2 with SSH, and use `git clone`/`git pull` via deploy keys - then directly running the server the same way I work with it locally (except with a different set of environment variables).

I pair this with an nginx/SSL configuration with free SSL certificates via certbot: https://dev.to/alexeydc/modern-https-configuration-2h86

# Deploy keys
Github has a notion of deploy keys, designed for this very purpose.

## Step 1: Generate keys
On the machine you want to deploy to, run:
```
ssh-keygen -t ed25519 -f ~/.ssh/my_project_deploy_key -C "your_email@example.com"
```

Note the `-t ed25519` - an upgrade from RSA to elliptic curve cryptography. More info: https://medium.com/risan/upgrade-your-ssh-key-to-ed25519-c6e8d60d3c54.

In this case, we're only going to use the key to pull the repo on a deploy - so you don't really need the `-C` flag. But e.g. if you develop on a remote machine and plan to commit with the key - it's helpful to tie it to your github email.

## Step 2: Add the public key to github
In the target repository, go to *Settings* -> *Deploy keys*.

Click `Add Deploy Key`.

Give it a descriptive title, like "Production MyProject EC2". Copy-paste the contents of `~/.ssh/my_project_deploy_key.pub` into the key field, *don't* tick `Allow write access` (or do - but for deploys you shouldn't want to).

## Step 3: Configure git to use the key
Actually, if we had named the key `id_rsa`, git would already have access to it (just make sure to clone via the `git:` URL, not `https:`).

However, then you are limited to just one repository for this machine, and... are forced to use the default key name.

Instead of being handcuffed by defaults, let's set up the config ( https://snipe.net/2013/04/11/multiple-github-deploy-keys-single-server/ ):
```
vim ~/.ssh/config

# Then add this type of config to the file
Host github.com-any_string_identifying_our_service
HostName github.com
IdentityFile /home/ubuntu/.ssh/my_project_deploy_key
User git

# You can have entries for multiple repos
Host github.com-another_string_for_another_project
HostName github.com
IdentityFile /home/ubuntu/.ssh/other_deploy_key
User git

```

Then you need a special clone command, using the host defined above. Let's say our github organization name is `shiny_deploys_inc`, and the repository name is `deploy_alpha`. The web URL for the repo would be `https://github.com/shiny_deploys_inc/deploy_alpha`. Here is the clone command, given the example config above:

```
git clone git@github.com-any_string_identifying_our_service:shiny_deploys_inc/deploy_alpha.git
```

After that, `git pull` should work as usual to update the project.

# What next?
This barebones setup can work quite well to get started, but it's far from being complete.

Each deploy will involve a bit of downtime. One way to get around that is with pm2 ( https://futurestud.io/tutorials/pm2-cluster-mode-and-zero-downtime-restarts ).

Eventually (e.g. as more people start to work on the project), it becomes a bad idea to SSH into an instance to deploy, and deploys can grow more complex. A first step could be to simply send a message to the server so it can pull the new version and start it. It's possible to set up github webhooks, but it's also possible to configure the server to be another remote, push directly to the server, and have it perform a relaunch on deploy https://gist.github.com/noelboss/3fe13927025b89757f8fb12e9066f2fa

I'll write more about these configurations in an upcoming post.