riju/doc/infrastructure.md

223 lines
6.6 KiB
Markdown

# Riju infrastructure
You can host your own instance of Riju! This requires a bit of manual
setup, but everything that *can* be automated, *has* been automated.
## Sign up for accounts
* [AWS](https://aws.amazon.com/)
* [Docker Hub](https://hub.docker.com/)
* [GitHub](https://github.com/)
## Configure accounts
### AWS
You need to generate an access key with sufficient permission to apply
[Riju's Terraform](../tf/infra.tf). The easiest way to do that if you
don't already know your way around IAM is:
* Go to [IAM](https://console.aws.amazon.com/iam/home)
* Create a new user
* Select "Programmatic access"
* Select "Attach existing policies directly"
* Attach the "AdministratorAccess" policy
* Copy and save the access key ID and secret access key
You also need to create an S3 bucket to store Terraform's state. Go to
[S3 in
us-west-1](https://s3.console.aws.amazon.com/s3/home?region=us-west-1#)
and create a new bucket called `riju-yourname-tf`.
### Docker Hub
Create a new repository to use for Riju.
### GitHub
Fork the Riju repository under your account.
## Install dependencies
* [Docker](https://www.docker.com/)
* [Git](https://git-scm.com/)
* [SSH](https://www.openssh.com/)
## Set up Riju locally
Clone the repository:
$ git clone https://github.com/yourname/riju.git
$ cd riju
Build and start the admin shell; all future actions can be done from
within the shell:
$ make image shell I=admin
To get multiple terminal sessions inside the shell, run `make tmux`
and refer to a [tmux
cheatsheet](https://danielmiessler.com/study/tmux/) if you are
unfamiliar with tmux usage.
## Configure your instance
### AWS
Sign in locally to the AWS CLI by running
$ aws configure
and entering the access key that you generated on AWS. The default
region is unimportant, although you may want to set it to `us-west-1`
because this is where Riju is configured to be deployed and having
that be consistent with your default command-line environment may
reduce confusion.
### Password
You need an administrator password that will be used for `sudo` access
on the production instance of Riju. You can generate one using `pwgen
-s 20 1`.
### SSH keys
You need two keys. One is used for administrator login on the
production instance, and the other is used to trigger deployments. You
can use your personal SSH key, if you already have one, for the admin
key. However, you should definitely generate a new key for
deployments. To generate an SSH key, use the `ssh-keygen` utility.
Place both keys in `~/.ssh`. This directory is automatically mounted
into the admin shell at `/home/riju/.ssh`.
### Additional configuration
You also need to have:
* The name of the Docker Hub repository that you created earlier (e.g.
`raxod502/riju`).
* The base name of the S3 bucket(s) for Riju that will be created in
your AWS account. The official buckets use prefix `riju`, but since
S3 buckets must be globally unique you should use `riju-yourname`.
With configuration in hand, create a file `.env` in the Riju directory
with the following contents, adjusting the values to match your
configuration:
```
ADMIN_PASSWORD=50M9QDBtkQLV6zFAwhVg
ADMIN_SSH_PUBLIC_KEY_FILE=/home/riju/.ssh/id_rsa.pub
DEPLOY_SSH_PUBLIC_KEY_FILE=/home/riju/.ssh/id_rsa_riju_deploy.pub
DOCKER_REPO=raxod502/riju
S3_BUCKET=riju-yourname
```
## Create infrastructure
Run `make env` in the admin shell to start a subshell with environment
variables set from `.env`. Your first step will be to create an
[AMI](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/AMIs.html)
for Riju.
```
$ cd packer
$ packer build config.json
```
This will take several minutes. Note the name of the AMI that is
printed, and add a corresponding line to `.env`:
```
AMI_NAME=riju-1609531301
```
Next, we will create the rest of the infrastructure.
```
$ cd ../tf
$ terraform init -backend-config="bucket=riju-yourname-tf"
$ terraform apply
```
This will print out the IP address of your newly provisioned server,
as well as permission-limited AWS credentials for use in CI. Add a
line to `.env` with the IP address:
```
DOMAIN=54.183.183.91
```
## Bootstrap server
Your newly provisioned server also isn't running anything yet.
You'll want to bootstrap it with the official image to make sure
everything is in working order:
```
$ ./tools/deploy.bash raxod502/riju:app
```
This may take a while. After it's finished, however, you should be
able to navigate to the IP address of your server in a browser and see
Riju up and running.
## Bootstrap S3
You probably don't want to build all of Riju's languages from scratch
when deploying a modified version, since that would take a long time.
You can avoid it by copying the latest built languages from Riju's
production S3 bucket. This will be fastest if you SSH into your
production server, which lives in AWS:
```
$ ssh admin@your-ip-address
$ export AWS_ACCESS_KEY_ID=...
$ export AWS_SECRET_ACCESS_KEY=...
$ aws s3 cp --recursive --source-region us-west-1 s3://riju-debs s3://riju-yourname-debs
```
## Set up CI
Go to [CircleCI](https://app.circleci.com/dashboard) and enable builds
for your fork of Riju. In the project settings, configure the
following environment variables:
* `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY`: the AWS access
credentials generated by Terraform
* `DEPLOY_SSH_PRIVATE_KEY`: base64-encoded SSH private key, e.g. from
`base64 -w0 ~/.ssh/id_rsa_riju_deploy`
* `DOCKER_REPO`: same as in `.env`
* `DOCKER_USERNAME` and `DOCKER_PASSWORD`: your credentials for Docker
Hub
* `DOMAIN`: same as in `.env`
* `S3_BUCKET`: same as in `.env`
You should now be able to trigger a build and see the production
instance updated automatically with a newly built image.
## Enable TLS
By default Riju will serve HTTP traffic if a TLS certificate is not
available. You can fix this. First, you'll need a domain name (or
subdomain on an existing domain). If you don't have one, you can buy
one at e.g. [Namecheap](https://www.namecheap.com/).
In your domain registrar's configuration interface, go to the
manual/advanced DNS settings and create an A record for your domain
pointing at your server's IP address. (To point the top-level domain
at Riju, set the host to `@`; to point a subdomain
`foo.yourdomain.io`, set the host to `foo`.)
Now SSH into the production server and run:
```
$ sudo systemctl stop riju
$ sudo certbot certonly --standalone
$ riju-install-certbot-hooks
$ sudo systemctl start riju
```
Alternatively, if you have an existing Certbot certificate you'd like
to transfer to the new server, you can copy over the entire
`/etc/letsencrypt` direction exactly as it stands, and run
`riju-install-certbot-hooks`.