diff --git a/.gitignore b/.gitignore index 00aca6da..893f032d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ node_modules coverage dist +.env .idea .DS_Store .nyc_output diff --git a/CONTRIBUTORS b/CONTRIBUTORS index a3e09bfb..87dd4c15 100644 --- a/CONTRIBUTORS +++ b/CONTRIBUTORS @@ -49,6 +49,7 @@ Cynthia Pereira Daniel Thorn Daniela Arcese Danny Coates +David Dumas Davide Derek Tamsen Dhyey Thakore diff --git a/README.md b/README.md index 1958ffa7..ad393ea3 100644 --- a/README.md +++ b/README.md @@ -81,7 +81,7 @@ A file sharing experiment which allows you to send encrypted files to other user ## Requirements -- [Node.js 12.x](https://nodejs.org/) +- [Node.js 15.x](https://nodejs.org/) - [Redis server](https://redis.io/) (optional for development) - [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) +AWS example using Ubuntu Server `20.04` [docs/AWS.md](docs/AWS.md) + --- ## Clients diff --git a/docs/AWS.md b/docs/AWS.md new file mode 100644 index 00000000..6c5c0825 --- /dev/null +++ b/docs/AWS.md @@ -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:::" + ], + "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 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 +``` diff --git a/docs/deployment.md b/docs/deployment.md index e3c39e91..e4f6f60c 100644 --- a/docs/deployment.md +++ b/docs/deployment.md @@ -1,16 +1,20 @@ ## Requirements + 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 -* GIT -* An Apache webserver +* A working (and ideally somewhat recent) installation of NodeJS and npm +* Git +* Apache webserver * 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 + * 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 * 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 ## Running + 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 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: -* telnet localhost 1443 + +```bash +telnet localhost 1443 +``` ## 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 -* a2enmod proxy -* a2enmod proxy_http -* a2enmod proxy_wstunnel -* a2enmod rewrite +* Enable Apache required modules: -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 - RewriteEngine on +# Enable rewrite engine +RewriteEngine on - # Make sure the original domain name is forwarded to Send - # Otherwise the generated URLs will be wrong - ProxyPreserveHost on +# Make sure the original domain name is forwarded to Send +# Otherwise the generated URLs will be wrong +ProxyPreserveHost on - # Make sure the generated URL is https:// - RequestHeader set X-Forwarded-Proto https +# Make sure the generated URL is https:// +RequestHeader set X-Forwarded-Proto https - # If it's a normal file (e.g. PNG, CSS) just return it - RewriteCond %{REQUEST_FILENAME} -f - RewriteRule .* - [L] +# If it's a normal file (e.g. PNG, CSS) just return it +RewriteCond %{REQUEST_FILENAME} -f +RewriteRule .* - [L] - # If it's a websocket connection, redirect it to a Send WS connection - RewriteCond %{HTTP:Upgrade} =websocket [NC] - RewriteRule /(.*) ws://127.0.0.1:1443/$1 [P,L] +# If it's a websocket connection, redirect it to a Send WS connection +RewriteCond %{HTTP:Upgrade} =websocket [NC] +RewriteRule /(.*) ws://127.0.0.1:1443/$1 [P,L] - # Otherwise redirect it to a normal HTTP connection - RewriteRule ^/(.*)$ http://127.0.0.1:1443/$1 [P,QSA] - ProxyPassReverse "/" "http://127.0.0.1:1443" +# Otherwise redirect it to a normal HTTP connection +RewriteRule ^/(.*)$ http://127.0.0.1:1443/$1 [P,QSA] +ProxyPassReverse "/" "http://127.0.0.1:1443" +``` + +* Test configuration and restart Apache: + +```bash +sudo apache2ctl configtest +sudo systemctl restart apache2 ```