14 Production
pw edited this page 7 months ago

Production use

Use in the local network

An easy way (compared to hosting on the Internet) is to run the application on your own PC or school server, which is located in the internal school network. In this case, only the corresponding computer name must be set in the configuration file server.config.production.json. The prerequisite for this, however, is that the students' devices are also integrated into the same network. A connection to the internet is then not necessary, since no files are loaded from third sources. This is especially suitable for classes with younger students.

Automatic startup under Linux

Create a small bash Script lerntools/bin/production.sh and make it executable:

#!/bin/bash
npm start

To start the application automatically at boot time, it can be configured as a system service using the following template:

[Unit]
Description=Lerntools
After=network.target

[Service]
Environment="NODE_ENV=production"
Environment="PORT=8080"
User=node
WorkingDirectory=/srv/lerntools
Type=simple
ExecStart=/srv/lerntools/bin/production.sh
Restart=on-failure

[Install]
WantedBy=multi-user.target

The variables "User" and "WorkingDirectory" must be adapted according to the installation, the service should under no circumstances run under the root account. The file is typically located in the directory /usr/lib/systemd /system/ as lerntools.service (may vary depending on Linux distribution)

The service can then be manually started by means of systemctl start lerntools, with systemctl enable lerntools it is automatically started when booting.

Reverse-Proxy

When running on an open server, you should not expose port 8080 directly. Instead, you should use nginx as reverse-proxy. Please configure support for websockets with a minimum timeout of 5 Minutes. Template for the configuration:

# file /etc/nginx/sites-available/lerntools
server {
    listen 80;
    listen [::]:80;
    server_name <YOUR-SERVER-NAME>;
    return 301 https://<YOUR-SERVER-NAME>$request_uri;
}

server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    server_name <YOUR-SERVER-NAME>;
    ssl_certificate      /etc/letsencrypt/live/<YOUR-SERVER-NAME>/fullchain.pem;
    ssl_certificate_key  /etc/letsencrypt/live/<YOUR-SERVER-NAME>/privkey.pem;
    ssl_session_timeout  5m;
    location / {
	client_max_body_size 50M;
	proxy_pass http://127.0.0.1:8080;
	proxy_http_version 1.1;
	proxy_set_header Upgrade $http_upgrade;
	proxy_set_header Connection 'upgrade';
	proxy_read_timeout 300;
	proxy_set_header Host $host;
	proxy_cache_bypass $http_upgrade;
    }
}

If you are using Apache please use the following snippet (thanks to csett86 for the Websocket part):

<VirtualHost *:443>
    ServerName [FQDN of your site]

    SSLEngine On
    # Path to certificate and private key, provided you are using letsencrypt certs
    SSLCertificateFile /etc/letsencrypt/live/[FQDN of your site]/fullchain.pem
    SSLCertificateKeyFile /etc/letsencrypt/live/[FQDN of your site]/privkey.pem

    # the following options are encouraged by https://httpd.apache.org/docs/trunk/ssl/ssl_howto.html
    # It is paramount that you read the instructions carefully, however, the following options should work on most systems
    # Additionally, you should regularly check for an updated version.
    SSLProtocol         all -SSLv3 -TLSv1 -TLSv1.1
    SSLCipherSuite      ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256
    SSLHonorCipherOrder on
    SSLCompression      off
    SSLSessionTickets   off

    # Requires Apache mod_proxy_http
    ProxyPass / http://127.0.0.1:8080/ # host and port the lerntools app is listening on
    ProxyPassReverse / http://127.0.0.1:8080/ # host and port the lerntools app is listening on
    
    # WebSockets require Apache mod_proxy_wstunnel
    RewriteEngine on
    RewriteCond ${HTTP:Upgrade} websocket [NC]
    RewriteCond ${HTTP:Connection} upgrade [NC]
    RewriteRule .* ws://127.0.0.1:8080%{REQUEST_URI} [P,L] # host and port the lerntools app is listening on
</VirtualHost>

Additionally, you will have to activate additional modules on a pristine / freshly installed Debian / Ubuntu system:

sudo a2enmod ssl # enabling HTTPS / SSL
sudo a2enmod proxy_http proxy_wstunnel # enabling websockets
sudo systemctl restart apache2 # restarting apache

For consideration: You might also want to add a redirection from port 80 to port 443 and again: regularly check https://httpd.apache.org/docs/trunk/ssl/ssl_howto.html for updates. The stated configuration might be secure against attacks such as POODLE and Heartbleed, however, Apache (as any other software) is prone to have other security loop holes, which are yet to be detected (e.g. BREACH).

Additional tasks

In order to run bin/production.sh employ one of the following commands:

chmod +x bin/production.sh
./bin/production.sh

or

sh bin/production.sh

Security considerations

We do not guarantee the safety and functionality of the application, the operation is at your own risk! Some tips:

  • Some files / directories are not required for productive operation: *.git *.sh webpack.....js
  • Use a reverse proxy, redirect incoming traffic to HTTPS (see nginx example above)
  • The reverse proxy needs to support websockets (see nginx example above, read timeout of 300s)
  • nodejs is very fast paced - regular updates are a must.
  • npm checks for known vulnerabilities when executing the npm audit command. Findings can be closed with npm audit fix.
  • The database should be password protected, see https://docs.mongodb.com/manual/tutorial/enable-authentication/.
  • In addition, nodejs should be limited by its own apparmor profile.

Caveat: if therer is a message about the server not running on :8080 check out port 8082 (this is also valid for Docker instances)