send/docs/AWS.md
2021-05-19 12:34:35 +00:00

236 lines
5.2 KiB
Markdown

# Deployment to AWS
This document describes how to do a deployment of Send in AWS
## AWS requirements
### Security groups (2)
* ALB:
- inbound: allow traffic from anywhere on port 80 and 443
- ountbound: allow traffic to the instance security group on port `8080`
* Instance:
- inbound: allow SSH from your public IP or a bastion (changing the default SSH port is a good idea)
- inbound: allow traffic from the ALB security group on port `8080`
- ountbound: allow all traffic to anywhere
### Resources
* An S3 bucket (block all public access)
* A private EC2 instance running Ubuntu `20.04` (you can use the [Amazon EC2 AMI Locator](https://cloud-images.ubuntu.com/locator/ec2/) to find the latest)
Attach an IAM role to the instance with the following inline policy:
```json
{
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"s3:ListAllMyBuckets"
],
"Resource": [
"*"
],
"Effect": "Allow"
},
{
"Action": [
"s3:ListBucket",
"s3:GetBucketLocation",
"s3:ListBucketMultipartUploads"
],
"Resource": [
"arn:aws:s3:::<s3_bucket_name>"
],
"Effect": "Allow"
},
{
"Action": [
"s3:GetObject",
"s3:GetObjectVersion",
"s3:ListMultipartUploadParts",
"s3:PutObject",
"s3:AbortMultipartUpload",
"s3:DeleteObject",
"s3:DeleteObjectVersion"
],
"Resource": [
"arn:aws:s3:::<s3_bucket_name>/*"
],
"Effect": "Allow"
}
]
}
```
* A public ALB:
- Create a target group with the instance registered (HTTP on port `8080` and path `/`)
- Configure HTTP (port 80) to redirect to HTTPS (port 443)
- HTTPS (port 443) using the latest security policy and an ACM certificate like `send.mydomain.com`
* A Route53 public record, alias from `send.mydomain.com` to the ALB
## Software requirements
* Git
* NodeJS `15.x` LTS
* Local Redis server
### Prerequisite packages
```bash
sudo apt update
sudo apt install -y apt-transport-https ca-certificates curl software-properties-common
```
### Add repositories
* NodeJS `15.x` LTS (checkout [package.json](../package.json)):
```bash
curl -fsSL https://deb.nodesource.com/gpgkey/nodesource.gpg.key | sudo apt-key add -
echo 'deb [arch=amd64] https://deb.nodesource.com/node_15.x focal main' | sudo tee /etc/apt/sources.list.d/nodejs.list
```
* Git (latest)
```bash
sudo add-apt-repository ppa:git-core/ppa
```
* Redis (latest)
```bash
sudo add-apt-repository ppa:redislabs/redis
```
### Install required packages
```bash
sudo apt update
sudo apt install git nodejs redis-server telnet
```
### Redis server
#### Password (optional)
Generate a strong password:
```bash
makepasswd --chars=100
```
Edit Redis configuration file `/etc/redis/redis.conf`:
```bash
requirepass <redis_password>
```
_Note: documentation on securing Redis https://redis.io/topics/security_
#### Systemd
Enable and (re)start the Redis server service:
```bash
sudo systemctl enable redis-server
sudo systemctl restart redis-server
sudo systemctl status redis-server
```
## Website directory
Setup a directory for the data
```
sudo mkdir -pv /var/www/send
sudo chown www-data:www-data /var/www/send
sudo 750 /var/www/send
```
### NodeJS
Update npm:
```bash
sudo npm install -g npm
```
Checkout current NodeJS and npm versions:
```bash
node --version
npm --version
```
Clone repository, install JavaScript packages and compiles the assets:
```bash
sudo su -l www-data -s /bin/bash
cd /var/www/send
git clone https://gitlab.com/timvisee/send.git .
npm install
npm run build
exit
```
Create the file `/var/www/send/.env` used by Systemd with your environment variables
(checkout [config.js](../server/config.js) for more configuration environment variables):
```
BASE_URL='https://send.mydomain.com'
NODE_ENV='production'
PORT='8080'
REDIS_PASSWORD='<redis_password>'
S3_BUCKET='<s3_bucket_name>'
```
Lower files and folders permissions to user and group `www-data`:
```
sudo find /var/www/send -type d -exec chmod 750 {} \;
sudo find /var/www/send -type f -exec chmod 640 {} \;
sudo find -L /var/www/send/node_modules/.bin/ -exec chmod 750 {} \;
```
### Systemd
Create the file `/etc/systemd/system/send.service` with `root` user and `644` mode:
```
[Unit]
Description=Send
After=network.target
Requires=redis-server.service
Documentation=https://gitlab.com/timvisee/send
[Service]
Type=simple
ExecStart=/usr/bin/npm run prod
EnvironmentFile=/var/www/send/.env
WorkingDirectory=/var/www/send
User=www-data
Group=www-data
Restart=on-failure
[Install]
WantedBy=multi-user.target
```
_Note: could be better tuner to secure the service by restricting system permissions,
check with `systemd-analyze security send`_
Enable and start the Send service, check logs:
```
sudo systemctl daemon-reload
sudo systemctl enable send
sudo systemctl start send
sudo systemctl status send
journalctl -fu send
```