Background to the recommended installation
Using NGINX mainline
We recommend using NGINX mainline - by default, most Linux distributions will instead install NGINX stable. While the stable branch will receive security updates, the version number will not always reflect the latest published version of NGINX, and scanning tools and other security compliance frameworks in your organisation may deem this as a failure to patch to the latest version.
Using a custom error page
We recommend installing custom error pages for common HTTP errors. Without this, certain errors are handled by NGINX, and this can reveal the version number of NGINX; other errors are handled by Tomcat, and this can reveal information about the version of Tomcat in use, and a stack trace for the error.
The instructions below are for a simple configuration showing a text error message for all 4xx and 5xx HTTP errors.
If you want to add details such as the web address, phone number or email address for your own support desk, update the text in the custom error file
custom_error.html
below.If you wish to show different pages for different errors, or to include images in your error pages, configuring NGINX to do this is well documented on the web.
In the phixflow.conf
file provided below, the following lines specify the errors to be handed using a custom page, and the location of the page. Update these if you want to configure something different:
proxy_intercept_errors on; error_page 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 421 422 423 424 425 426 428 429 431 451 500 501 502 503 504 505 506 507 508 510 511 /custom_error.html; location = /custom_error.html { internal; root /usr/share/nginx/html; }
Including a redirect to connections to port 80
Leaving port 80 open and including a redirect is widely recommended (including, for example, by Let’s Encrypt: https://letsencrypt.org/docs/allow-port-80/). This is done in the NGINX configuration file below. This means that you will need to allow incoming connections through your firewall to port 80 on the server you are using to host NGINX. Doing this also allows Let’s Encrypt to automatically renew the certificate using the default HTTP-01 challenge.
Hide version number
In this installation, we hide the version number on the default NGINX page. This is a useful security measure. Because errors are already redirected to a standard error page (see above), in this installation you are unlikely to see this in a browser. But this can be viewed using a client such as curl that does not apply the port 80 redirect, or by querying for the header information for the service.
Using Let’s Encrypt to provide certificates
The method below uses https://certbot.eff.org/ to issue and install certificates from https://letsencrypt.org/ to provide secure connections over HTTPS. Let’s Encrypt is a well known Certificate Authority (CA) that is free to use. Check with your organisation on standards for certificates. You may need to use a different public CA, or an internal CA. Using CAs aside from Let’s Encrypt is well documented on the web. In particular, most public CAs will document how their certificates can be installed into NGINX.
If you do not use Certbot, skip the section ‘Install certificate using Certbot’ below, and follow instructions appropriate for your CA.
Setting client_max_body_size
The client_max_body_size
is set in the configuration below to allow files of sufficient size to be loaded into PhixFlow. (Note, this is specified in the "Content-Length" request header field.) In particular, this setting must allow configuration files to be uploaded into PhixFlow. Configuration files are used to move applications developed in the PhixFlow GUI between PhixFlow instances (e.g. from a test to a production system).
If PhixFlow users encounter problems loading files into PhixFlow, you may need to further increase this setting. Only authenticated users are able to trigger a file upload, and even then only certain users will have access to funtions that cause a file upload. Even in an instance of PhixFlow that is available through the public internet, general users who are not athenticated on PhixFlow are not able to upload arbitrary files into PhixFlow.
Installing with apt
The instructions below are based on installation on a Debian-based distribution of Linux, and use the apt command. If you are installing on a RedHat-based distribution of Linux, the equivalent yum commands for NGINX installation are well documented on the web.
Single server, single PhixFlow webapp
The following instructions assume that NGINX is installed on the same server as PhixFlow itself (i.e. the same server as the Tomcat installation), and with a single installation of PhixFlow (a “webapp”). If you have multiple webapps on a single server, multiple webapps across several servers, or a single webapp on a different server from the reverse proxy, see ‘Multiple PhixFlow webapps or multiple servers’ below.
Set up a domain record
Choose a domain, e.g. phixflow.mycompany.com, and set up an A record on your DNS to point this domain at the public IP address of the server that you are installing NGINX on.
Install NGINX
Install NGINX from the repository. Instructions for various Linux distributions can be found here: http://nginx.org/en/linux_packages.html.
The example given here is taken from those instructions, and is for installation of NGINX mainline on Ubuntu.
Install prerequisites:
sudo apt install curl gnupg2 ca-certificates lsb-release ubuntu-keyring
Import the official NGINX signing key so that the package can be verified:
curl https://nginx.org/keys/nginx_signing.key | gpg --dearmor | sudo tee /usr/share/keyrings/nginx-archive-keyring.gpg >/dev/null
Verify the downloaded file:
gpg --dry-run --quiet --import --import-options import-show /usr/share/keyrings/nginx-archive-keyring.gpg
The output should contain the full fingerprint 573BFD6B3D8FBC641079A6ABABF5BD827BD9BF62
as follows:
pub rsa2048 2011-08-19 [SC] [expires: 2024-06-14] 573BFD6B3D8FBC641079A6ABABF5BD827BD9BF62 uid nginx signing key <signing-key@nginx.com>
Add the mainline packages to your repository list:
echo "deb [signed-by=/usr/share/keyrings/nginx-archive-keyring.gpg] http://nginx.org/packages/mainline/ubuntu `lsb_release -cs` nginx" | sudo tee /etc/apt/sources.list.d/nginx.list
Set up repository pinning:
echo -e "Package: *\nPin: origin nginx.org\nPin: release o=nginx\nPin-Priority: 900\n" | sudo tee /etc/apt/preferences.d/99nginx
Install NGINX:
sudo apt update sudo apt install nginx
Install certificate using Certbot
The following instructions are based on the recommended installation of Certbot with snap: https://certbot.eff.org/instructions?ws=nginx&os=ubuntubionic. This link also includes alternative instructions for installing Certbot if you don’t want to use snap.
These instructions also assume that snap is installed on your system. If it is not, you can following instructions here: https://snapcraft.io/docs/installing-snapd.
Make sure that any firewalls on the server are open to port 80 (HTTP).
Ensure that snapd is up to date:
sudo snap install core; sudo snap refresh core
Install Certbot:
sudo snap install --classic certbot
Link Certbot command to make it accessible:
sudo ln -s /snap/bin/certbot /usr/bin/certbot
Request a certificate:
sudo certbot certonly --nginx
When the final command runs, it will prompt for several responses:
An email address (for urgent renewal and security notices): e.g. security.notifications@mycompany.com
Terms of service: you must agree to these (press Y)
Agreement to share your email address with EFF: you can choose either option, i.e. Y or N
The domain name assigned to this service: e.g. phixflow.mycompany.com
You can run sudo certbot certificates
to list the installed certificates and confirm that the certificate has been successfully requested
Configure NGINX
Most distributions of NGINX no longer include sites-enabled
and sites-available
directories. This example installation is based on distribution that does not include these directories, and places the configuration file in the /etc/nginx/conf.d directory
. If your installed version of NGINX includes sites-enabled
and sites-available
directories, consult the NGINX documentation for further guidance.
Save a backup of the default configuration file:
sudo mv /etc/nginx/conf.d/default.conf /etc/nginx/conf.d/default.conf.bak
Create configuration file for PhixFlow: open editing on a file /etc/nginx/conf.d/phixflow.conf
(e.g. with sudo nano /etc/nginx/conf.d/phixflow.conf
), and paste in the following, replacing [domain]
with your domain, e.g. phixflow.mycompany.com:
server { listen 80 default_server; server_name _; return 301 https://$host$request_uri; } server { listen 443 ssl; listen [::]:443 ssl ipv6only=on; server_name [domain]; proxy_intercept_errors on; error_page 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 421 422 423 424 425 426 428 429 431 451 500 501 502 503 504 505 506 507 508 510 511 /custom_error.html; location = /custom_error.html { internal; root /usr/share/nginx/html; } # add secure flag to XSRF-TOKEN cookie proxy_cookie_flags XSRF-TOKEN secure; location / { proxy_pass http://127.0.0.1:8080; } ssl_certificate /etc/letsencrypt/live/[domain]/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/[domain]/privkey.pem; include /etc/letsencrypt/options-ssl-nginx.conf; ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; client_max_body_size 150M; add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"; }
Create a custom error page: open editing on a file /usr/share/nginx/html/custom_error.html
(e.g. with sudo nano /usr/share/nginx/html/custom_error.html
), and paste in the following:
<!doctype html> <html> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta http-equiv="X-UA-Compatible" content="IE=11" /> <title>PhixFlow Error</title> </head> <body> <div class="access-error" style="font-family: Verdana, Helvetica, Arial, sans-serif; font-size: 24px; text-align: center; position:absolute; top:300px; width:100%; "> An unexpected error has occurred opening PhixFlow, please contact the support desk. </div> </body> </html>
Hide version number: edit the file /etc/nginx/nginx.conf
, and in the http context add the line server_tokens off;
. This will result in a file that looks similar to:
Restart NGINX:
sudo nginx -s reload ssudo systemctl stop nginx.service sudo systemctl start nginx.service
Notes
You may need to reboot the server as well in order for NGINX to restart successfully.
Run
netstat -tln
to check the server is listening on port 443 and port 80.Check the PhixFlow application loads in the browser.
Configure SSL cipher restriction
This is based on recommendations given at: https://wiki.mozilla.org/Security/Server_Side_TLS#Recommended_configurations.
Open the file at /etc/letsencrypt/options-ssl-nginx.conf
. It should look similar to the following:
ssl_session_cache shared:le_nginx_SSL:10m; ssl_session_timeout 1440m; ssl_session_tickets off; ssl_protocols TLSv1.2 TLSv1.3; ssl_prefer_server_ciphers off; ssl_ciphers "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384";
openssl-1.1.1 and later
At version 1.1.1 OpenSSL changed the method of configuring ciphersuites for TLS1.3. This has an impact on configuration of ciphersuites in NGINX (https://trac.nginx.org/nginx/ticket/1529).
To determine if you are using OpenSSL at a version of 1.1.1 or later, take note of the version of libssl
on your linux distribution rather than openssl
itself. On Debian based distributions of linux, you can find these packges with the command dpkg --list | grep ssl
(this will probably show other ssl related packages, but you can ignore them for this assessment).
E.g. from Ubuntu 18.04:
In practice on Ubuntu, for example, on 22.04 the newer version of OpenSSL is used; on 18.04, the older version.
If you aren’t sure, try the configuration in this section, if you get an error when trying to start NGINX, try the other configuration below.
Edit the ssl_protocols
parameter to be:
ssl_protocols TLSv1.3;
Update the file to replace the current line that starts ssl_ciphers
to be:
ssl_ciphers ECDHE-ECDSA-AES256-GCM-SHA384; ssl_conf_command Ciphersuites TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256;
Save and close the file.
Before openssl-1.1.1
Edit the ssl_protocols
parameter to be:
ssl_protocols TLSv1.3;
Edit the ssl_ciphers
parameter to be:
ssl_ciphers "TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256";
Save and close the file.
Restart NGINX
Run the following to reload the NGINX configuration:
sudo nginx -s reload
Restart the NGINX service:
sudo systemctl restart nginx.service
Multiple PhixFlow webapps or multiple servers
A single reverse proxy can handle connections to different webapps (i.e. installations of PhixFlow), whether these are hosted on a single server, or across several servers. See *** for common network configuration for PhixFlow installation. However, whichever configuration you choose, the configuration is the same: you need an IP address and a webapp name to define each PhixFlow installation.
Note that, since NGINX is acting as the the point of SSL termination, if you specify a PhixFlow installation at an IP address you must make sure that the route from the reverse proxy to the PhixFlow installation is secure. The suggested configurations in *** will provide this since traffic is sent within a private network.
In the following example, a single reverse proxy on a dedicated server is handling incoming connections to four different webapps:
System name | Server IP address | Webapp name |
---|---|---|
Production |
| prod, installed at: |
UAT |
| uat, installed at: |
Dev 1 |
| dev1, installed at |
Dev 2 |
| dev2, installed at |
To support connections to all these systems replace the directive
location / { proxy_pass http://127.0.0.1:8080; }
in the example phixflow.conf
file above with:
location /prod { proxy_pass http://10.154.0.12:8080; } location /uat { proxy_pass http://10.154.0.13:8080; } location /dev1 { proxy_pass http://10.154.0.14:8080; } location /dev2 { proxy_pass http://10.154.0.14:8080; }