Merge branch 'deploy' into 'master'

Documentation : full deployment example in AWS with Ubuntu 20.04

See merge request timvisee/send!16
This commit is contained in:
Tim Visée 2021-05-19 09:17:13 +00:00
commit a1ca355771
5 changed files with 299 additions and 32 deletions

1
.gitignore vendored
View File

@ -1,6 +1,7 @@
node_modules node_modules
coverage coverage
dist dist
.env
.idea .idea
.DS_Store .DS_Store
.nyc_output .nyc_output

View File

@ -49,6 +49,7 @@ Cynthia Pereira
Daniel Thorn Daniel Thorn
Daniela Arcese Daniela Arcese
Danny Coates Danny Coates
David Dumas
Davide Davide
Derek Tamsen Derek Tamsen
Dhyey Thakore Dhyey Thakore

View File

@ -81,7 +81,7 @@ A file sharing experiment which allows you to send encrypted files to other user
## Requirements ## Requirements
- [Node.js 12.x](https://nodejs.org/) - [Node.js 15.x](https://nodejs.org/)
- [Redis server](https://redis.io/) (optional for development) - [Redis server](https://redis.io/) (optional for development)
- [AWS S3](https://aws.amazon.com/s3/) or compatible service (optional) - [AWS S3](https://aws.amazon.com/s3/) or compatible service (optional)
@ -141,6 +141,8 @@ Find a list of public instances here: https://github.com/timvisee/send-instances
See also [docs/deployment.md](docs/deployment.md) See also [docs/deployment.md](docs/deployment.md)
AWS example using Ubuntu Server `20.04` [docs/AWS.md](docs/AWS.md)
--- ---
## Clients ## Clients

236
docs/AWS.md Normal file
View File

@ -0,0 +1,236 @@
# 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 chmod 750 /var/www/send/node_modules/.bin/*
```
### 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
```

View File

@ -1,16 +1,20 @@
## Requirements ## Requirements
This document describes how to do a full deployment of Send on your own Linux server. You will need: This document describes how to do a full deployment of Send on your own Linux server. You will need:
* A working (and ideally somewhat recent) installation of NodeJS and NPM * A working (and ideally somewhat recent) installation of NodeJS and npm
* GIT * Git
* An Apache webserver * Apache webserver
* Optionally telnet, to be able to quickly check your installation * Optionally telnet, to be able to quickly check your installation
For Debian/Ubuntu systems this probably just means something like this: For example in Debian/Ubuntu systems:
* apt install git apache2 nodejs npm telnet ```bash
sudo apt install git apache2 nodejs npm telnet
```
## Building ## Building
* We assume an already configured virtual-host on your webserver with an existing empty htdocs folder * We assume an already configured virtual-host on your webserver with an existing empty htdocs folder
* First, remove that htdocs folder - we will replace it with Send's version now * First, remove that htdocs folder - we will replace it with Send's version now
* git clone https://github.com/timvisee/send.git htdocs * git clone https://github.com/timvisee/send.git htdocs
@ -19,51 +23,74 @@ For Debian/Ubuntu systems this probably just means something like this:
* npm run build * npm run build
## Running ## Running
To have a permanently running version of Send as a background process: To have a permanently running version of Send as a background process:
* Create a file "run.sh" with: * Create a file `run.sh` with:
```
```bash
#!/bin/bash #!/bin/bash
nohup su www-data -c "npm run prod" 2>/dev/null & nohup su www-data -c "npm run prod" 2>/dev/null &
``` ```
* chmod +x run.sh
* ./run.sh * Execute the script:
```bash
chmod +x run.sh
./run.sh
```
Now the Send backend should be running on port 1443. You can check with: Now the Send backend should be running on port 1443. You can check with:
* telnet localhost 1443
```bash
telnet localhost 1443
```
## Reverse Proxy ## Reverse Proxy
Of course, we don't want to expose the service on port 1443. Instead we want our normal webserver to forward all requests to Send ("Reverse proxy"). Of course, we don't want to expose the service on port 1443. Instead we want our normal webserver to forward all requests to Send ("Reverse proxy").
# Apache webserver # Apache webserver
* a2enmod proxy * Enable Apache required modules:
* a2enmod proxy_http
* a2enmod proxy_wstunnel
* a2enmod rewrite
In your Apache virtual host configuration file, insert this: ```bash
sudo a2enmod headers
sudo a2enmod proxy
sudo a2enmod proxy_http
sudo a2enmod proxy_wstunnel
sudo a2enmod rewrite
```
* Edit your Apache virtual host configuration file, insert this:
``` ```
# Enable rewrite engine # Enable rewrite engine
RewriteEngine on RewriteEngine on
# Make sure the original domain name is forwarded to Send # Make sure the original domain name is forwarded to Send
# Otherwise the generated URLs will be wrong # Otherwise the generated URLs will be wrong
ProxyPreserveHost on ProxyPreserveHost on
# Make sure the generated URL is https:// # Make sure the generated URL is https://
RequestHeader set X-Forwarded-Proto https RequestHeader set X-Forwarded-Proto https
# If it's a normal file (e.g. PNG, CSS) just return it # If it's a normal file (e.g. PNG, CSS) just return it
RewriteCond %{REQUEST_FILENAME} -f RewriteCond %{REQUEST_FILENAME} -f
RewriteRule .* - [L] RewriteRule .* - [L]
# If it's a websocket connection, redirect it to a Send WS connection # If it's a websocket connection, redirect it to a Send WS connection
RewriteCond %{HTTP:Upgrade} =websocket [NC] RewriteCond %{HTTP:Upgrade} =websocket [NC]
RewriteRule /(.*) ws://127.0.0.1:1443/$1 [P,L] RewriteRule /(.*) ws://127.0.0.1:1443/$1 [P,L]
# Otherwise redirect it to a normal HTTP connection # Otherwise redirect it to a normal HTTP connection
RewriteRule ^/(.*)$ http://127.0.0.1:1443/$1 [P,QSA] RewriteRule ^/(.*)$ http://127.0.0.1:1443/$1 [P,QSA]
ProxyPassReverse "/" "http://127.0.0.1:1443" ProxyPassReverse "/" "http://127.0.0.1:1443"
```
* Test configuration and restart Apache:
```bash
sudo apache2ctl configtest
sudo systemctl restart apache2
``` ```