# 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:::" ], "Effect": "Allow" }, { "Action": [ "s3:GetObject", "s3:GetObjectVersion", "s3:ListMultipartUploadParts", "s3:PutObject", "s3:AbortMultipartUpload", "s3:DeleteObject", "s3:DeleteObjectVersion" ], "Resource": [ "arn:aws:s3:::/*" ], "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 ``` _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='' S3_BUCKET='' ``` 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 ```