Users of one of our local Galaxy servers recently reported a problem with uploading files larger than a few tens of megabytes via the "Upload" interface, where the uploader would stop partway through with the message Warning: Internal server error (500).
For example:
By trial and error it was established that the maximum file size that the uploader could handle without this failure was around 65MB.
The particular server instance was running Galaxy release 19.05 and was configured to use nginx as the proxy; unfortunately there didn't appear to be any relevant error messages in the logs from either Galaxy or nginx.
However, looking at the sizes of the various logical volumes on the virtual machine hosting the Galaxy instance revealed a potential culprit:
# df -h /var
Filesystem Size Used Avail Use% Mounted on
/dev/mapper/lv-var 2.0G 1.8G 65M 97% /var
i.e. the available space on the /var logical volume was around the same size as the maximum size for successful file upload. Additionally, monitoring the available space under /var while uploading a file it was possible to see it shrink (and then reset as the upload either completed or failed). So it appeared that this area was being used by nginx as temporary space for the file uploads before handing the data off to Galaxy.
The nginx configuration for this server didn't explicitly set this location, but the nginx documentation includes a directive called client_body_temp_path, which defines the directory for storing temporary files holding client request bodies.
Explicitly setting this directive (in the server block of the nginx configuration) to point to a location on the virtual machine (in this case under /tmp) with more available space seemed to fix the problem:
server {
...
client_body_temp_path /tmp/nginx;
...
Adventures supporting instances of Penn State's Galaxy platform for data intensive biomedical research
Showing posts with label nginx. Show all posts
Showing posts with label nginx. Show all posts
Wednesday, 29 January 2020
Wednesday, 29 May 2019
Fixing dataset download problems for uWSGI+nginx Galaxy configuration
We recently experienced problems downloading datasets via a web browser from one of our local Galaxy instances, which runs release 18.09 and uses a uWSGI+nginx configuration.
While small files (e.g. of the order of Mb) downloaded without problems, larger files (e.g. of the order of Gb) would fail with a dialog box appearing in the user's web browser complaining that "the source file can't be read". (The Galaxy logs also reported an IOError from uwsgi_response_write_body_do() function.)
The initial problem seemed to be with the temporary directory being used for managing the download on the server. Explicitly setting uwsgi_temp_path in the nginx configuration seemed to help, for example:
uwsgi_temp_path /tmp/uwsgi;
This got rid of the dialog box but the larger downloads still failed without completing. Although the user's browser didn't give any more information, the Galaxy logs now reported a timeout error. To address this we explicitly set the UWSGI timeout limits in the nginx configuration, e.g.:
uwsgi_read_timeout 600s;
uwsgi_write_timeout 600s;
The choice of 600s (10 minutes) was arbitrary but seemed long enough to allow the downloads to complete.
Finally as the temporary area on server is quite small, we also explicitly set the maximum size of temporary files to 1Mb:
uwsgi_max_temp_file_size 1024k;
Together these addressed the download problem in our local instance.
While small files (e.g. of the order of Mb) downloaded without problems, larger files (e.g. of the order of Gb) would fail with a dialog box appearing in the user's web browser complaining that "the source file can't be read". (The Galaxy logs also reported an IOError from uwsgi_response_write_body_do() function.)
The initial problem seemed to be with the temporary directory being used for managing the download on the server. Explicitly setting uwsgi_temp_path in the nginx configuration seemed to help, for example:
uwsgi_temp_path /tmp/uwsgi;
This got rid of the dialog box but the larger downloads still failed without completing. Although the user's browser didn't give any more information, the Galaxy logs now reported a timeout error. To address this we explicitly set the UWSGI timeout limits in the nginx configuration, e.g.:
uwsgi_read_timeout 600s;
uwsgi_write_timeout 600s;
The choice of 600s (10 minutes) was arbitrary but seemed long enough to allow the downloads to complete.
Finally as the temporary area on server is quite small, we also explicitly set the maximum size of temporary files to 1Mb:
uwsgi_max_temp_file_size 1024k;
Together these addressed the download problem in our local instance.
Tuesday, 25 April 2017
Securing Galaxy with HTTPS running with Nginx using Let’s Encrypt
Background
To secure communication between a Galaxy instance and its users it is best to enable HTTPS on the Galaxy web server, to ensure that all data transmissions between Galaxy and the end user (including sensitive information such as usernames and passwords) are encrypted. This can done by obtaining and installing SSL/TLS certificates on the server.
The simplest approach in the past was to use self-signed certificates as a way to enable HTTPS while avoiding the cost of purchasing certificates from a commercial Certificate Authority (CA) (for example by using the make-dummy-certs utility found in e.g. /usr/ssl/certs). The downside of this approach is that when a user first tries to access the server their web browser will complain that the certificates are not trusted, and they would typically have to create a one-off security exception before they can access the Galaxy service.
The simplest approach in the past was to use self-signed certificates as a way to enable HTTPS while avoiding the cost of purchasing certificates from a commercial Certificate Authority (CA) (for example by using the make-dummy-certs utility found in e.g. /usr/ssl/certs). The downside of this approach is that when a user first tries to access the server their web browser will complain that the certificates are not trusted, and they would typically have to create a one-off security exception before they can access the Galaxy service.
More recently however, a free Certificate Authority called Let’s Encrypt (https://letsencrypt.org/) has been set up which issues free certificates as part of its stated mission to “secure the web”. This blog post gives an overview of how we obtained and installed certificates from Let's Encrypt to enable HTTPS for our production Galaxy instances, using their automated cert-bot client utility.
Before beginning
The procedure described below uses the 'webroot' plugin of cert-bot (see https://certbot.eff.org/docs/using.html#webroot), which is a general method recommended for obtaining certificates web servers running nginx. cert-bot also has a plugin for nginx but at the time of writing this is still at alpha-release stage so I didn't use it for our Galaxy servers (see https://certbot.eff.org/docs/using.html#nginx for more details).
For Apache-based servers you can use a dedicated plugin described at https://certbot.eff.org/docs/using.html#apache, which offers a more automated procedure than the one described here.
Also, although it targets a different operating system to ours and while many of the details are now out-of-date, DigitalOcean's how-to guide at https://www.digitalocean.com/community/tutorials/how-to-secure-nginx-with-let-s-encrypt-on-ubuntu-14-04 is still a useful resource and was immensely helpful to me for understanding the overall process.
Finally, please note that the procedure and its details are likely to change over time. Make sure you check the documentation before carrying out any of these operations on your own infrastructure!
Step 1: Install cert-bot (Let’s Encrypt client) on the server
Before beginning
The procedure described below uses the 'webroot' plugin of cert-bot (see https://certbot.eff.org/docs/using.html#webroot), which is a general method recommended for obtaining certificates web servers running nginx. cert-bot also has a plugin for nginx but at the time of writing this is still at alpha-release stage so I didn't use it for our Galaxy servers (see https://certbot.eff.org/docs/using.html#nginx for more details).
For Apache-based servers you can use a dedicated plugin described at https://certbot.eff.org/docs/using.html#apache, which offers a more automated procedure than the one described here.
Also, although it targets a different operating system to ours and while many of the details are now out-of-date, DigitalOcean's how-to guide at https://www.digitalocean.com/community/tutorials/how-to-secure-nginx-with-let-s-encrypt-on-ubuntu-14-04 is still a useful resource and was immensely helpful to me for understanding the overall process.
Finally, please note that the procedure and its details are likely to change over time. Make sure you check the documentation before carrying out any of these operations on your own infrastructure!
Step 1: Install cert-bot (Let’s Encrypt client) on the server
To begin you need to ensure the Let's Encrypt cert-bot utility (https://certbot.eff.org/) is available on the server, to perform the job of obtaining and installing the certificates.
The documentation recommends that if possible you should use the cert-bot package provided by the package manager for your system (e.g. yum, apt etc). However if one isn't available (or is unsuitable e.g. because it's out-of-date) then you can install the client using the certbot-auto wrapper script instead (see https://certbot.eff.org/docs/install.html#certbot-auto). This is the approach I used, putting certbot-auto into /usr/local/bin on the server running Galaxy and nginx.
(Note that certbot-auto takes the same arguments as the cert-bot utility, the only difference is that if necessary it will download and update itself first each time it's run.)
- Aside: there is also a cert-bot package available via the Python Package Index (PyPI). When I first performed this procedure I noted that the documentation emphasised that cert-bot should not be installed 'pip install', but now I can't find any reference to this. However I would still avoid installing from PyPI for the time being.
Step2: Get certificates using the 'webroot' method
cert-bot provides a number of different ways to obtain certificates depending on the webserver software being used. The 'webroot' protocol used here is less automated than some of the other procedures but is still quite straightforward, and works by placing a special file on your webserver which Let's Encrypt can attempt to fetch in order to verify the server name and details that are supplied when the cert-bot client is run.
First we need to set up a special directory called .well-known, where Let's Encrypt will place its file:
- Create a directory called .well-known in the document root of the server (the default for nginx is /usr/share/nginx/hmtl but the actual path can be found by looking up the value of webroot-path in the server configuration), e.g.:
mkdir /usr/share/nginx/hmtl/.well-known
Optionally also add a dummy index file to help check that the directory is visible via web browser later, e.g.:
cat >/usr/share/nginx/hmtl/.well-known/index.html <<EOF
Hello world!
EOF
- Add a new location block inside the server block in the nginx configuration file, to allow access to the .well-known directory:
location ~ /.well-known {
allow all;
}
- Restart nginx and check that the .well-known directory is visible (e.g. by pointing a web browser at it)
Then we need to run certbot-auto (or cert-bot) interactively to generate and install the certificates:
certbot will then prompt you to agree to Let's Encrypt's terms and conditions and ask you to provide an email address which will be used for notices and for lost key recovery.
If all goes well then this should produce a set of certificate files under /etc/letsencrypt/archive (with links to these from /etc/letsencrypt/live/):
To enable HTTPS we need to configure nginx to listen on port 443 with SSL enabled, and to use the certificates from Let's Encrypt. This is done by adding the following to the server block in the nginx configuration file, for example:
server {
listen 443;
ssl on;
ssl_certificate /etc/letsencrypt/live/MYDOMAIN/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/MYDOMAIN/privkey.pem;
}
(Again, your actual domain name should be substituted for MYDOMAIN above.)
It's also a good idea to block or redirect HTTP traffic, so that users don't accidentally send data via an insecure connection - for example to redirect to :
server {
listen 80 default;
server_name MYDOMAIN;
rewrite ^ https://$server_name$request_uri? permanent;
}
Once nginx is restarted you can check using your browser that HTTPS is working for your Galaxy instance; you can also use the Qualys SSL Labs website to check your server configuration:
https://www.ssllabs.com/ssltest/index.html
(NB this is useful for flagging up other issues which you might wish to address!)
Step 4: set up automated certificate renewal
Finally: since all certificates issued by Let's Encrypt expire after 90 days, they recommend that they should be renewed at least once every 3 months.
It's straightforward to automate this process by setting up a cron job on the server to run cert-bot or certbot-auto's 'renew' command (which will renew any previously-obtained certificates that are due to expire in less than 30 days) and then restart nginx (so that any renewed certificates will be loaded).
For example I have the following commands in the root crontab on our server:
- sudo certbot-auto certonly --webroot -w /usr/share/nginx/html -d MYDOMAIN
where MYDOMAIN is the domain name of your Galaxy server (e.g. "palfinder.ls.manchester.ac.uk").
- Aside: note that this bootstraps certbot, including checking for the system packages that it requires; you'll be prompted to install any that it thinks are missing via the system package manager e.g. yum.
certbot will then prompt you to agree to Let's Encrypt's terms and conditions and ask you to provide an email address which will be used for notices and for lost key recovery.
If all goes well then this should produce a set of certificate files under /etc/letsencrypt/archive (with links to these from /etc/letsencrypt/live/):
- cert.perm (your domain's certificate)
- chain.pem (the Let's Encrypt chain certificate)
- fullchain.pem (cert.pem and chain.pem combined)
- privkey.pem (your certificate's private key)
- IMPORTANT: you should ensure that the certificate files are backed up to a secure and safe location!
To enable HTTPS we need to configure nginx to listen on port 443 with SSL enabled, and to use the certificates from Let's Encrypt. This is done by adding the following to the server block in the nginx configuration file, for example:
server {
listen 443;
ssl on;
ssl_certificate /etc/letsencrypt/live/MYDOMAIN/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/MYDOMAIN/privkey.pem;
}
(Again, your actual domain name should be substituted for MYDOMAIN above.)
It's also a good idea to block or redirect HTTP traffic, so that users don't accidentally send data via an insecure connection - for example to redirect to :
server {
listen 80 default;
server_name MYDOMAIN;
rewrite ^ https://$server_name$request_uri? permanent;
}
Once nginx is restarted you can check using your browser that HTTPS is working for your Galaxy instance; you can also use the Qualys SSL Labs website to check your server configuration:
https://www.ssllabs.com/ssltest/index.html
(NB this is useful for flagging up other issues which you might wish to address!)
Step 4: set up automated certificate renewal
Finally: since all certificates issued by Let's Encrypt expire after 90 days, they recommend that they should be renewed at least once every 3 months.
It's straightforward to automate this process by setting up a cron job on the server to run cert-bot or certbot-auto's 'renew' command (which will renew any previously-obtained certificates that are due to expire in less than 30 days) and then restart nginx (so that any renewed certificates will be loaded).
# Check SSL certificate renewal from Let's Encrypt
See the documentation at https://certbot.eff.org/docs/using.html#renewing-certificates for more information on certificate renewal.
Update 22nd October 2018: the original crontab lines above didn't work for me - the certificate renewals would fail and have to be performed manually, resulting in downtime for the period when nginx would no longer have valid SSL certificates.
Since then I've replaced the original crontab lines with the following single line:
30 2 * * 1 /usr/local/bin/certbot-auto renew --deploy-hook "/sbin/service nginx reload" >> /var/log/le-renew
which uses certbot-auto's --deploy-hook option to reload the nginx configuration on successful certificate renewal via the service command. Note that the full path to service is required as cron jobs have a minimal PATH which doesn't seem to include /sbin.
Tuesday, 2 June 2015
Exposing Galaxy reports via nginx in a production instance
Galaxy includes a report tool that is separate from the main process but which gives lots of potentially useful information about the usage of a Galaxy instance, for example the numbers of jobs that have been run each month, how much disk space each user is currently consuming and so on.
However there doesn't appear to be much documentation about the report tool on the official Galaxy wiki: the most I could find was a rather sparse page at https://wiki.galaxyproject.org/Admin/UsageReports, which gives a very bare bones overview, and doesn't include any information on how it might be exposed in a secure manner in a production environment. Therefore in this post I outline how I've done this for our local Galaxy set up, which uses nginx; however I imagine it could be adapted to work with Apache instead.
1. Set up up the report tool to run on localhost
The report tool takes its configuration settings from a file called reports_wsgi.ini, which is located in the config subdirectory of the Galaxy distribution.
Configuring the reports for your local setup is a case of:
However there doesn't appear to be much documentation about the report tool on the official Galaxy wiki: the most I could find was a rather sparse page at https://wiki.galaxyproject.org/Admin/UsageReports, which gives a very bare bones overview, and doesn't include any information on how it might be exposed in a secure manner in a production environment. Therefore in this post I outline how I've done this for our local Galaxy set up, which uses nginx; however I imagine it could be adapted to work with Apache instead.
1. Set up up the report tool to run on localhost
The report tool takes its configuration settings from a file called reports_wsgi.ini, which is located in the config subdirectory of the Galaxy distribution.
Configuring the reports for your local setup is a case of:
- Making a copy of reports_wsgi.ini.sample called reports_wsgi.ini
- Editing the database_connection and file_path (if not the default) parameters to match those in your galaxy.ini (or universe_wsgi.ini) file
- Optionally, editing the port parameter (by default the tool uses port 9001)
- You should also set the 'salt' parameter session_secret if you intend to expose the reports via the web proxy (see below)
Then you can start the report server using
sh run_reports.sh
and view the reports by pointing a web browser running on the same server to http://127.0.0.1:9001.
If you'd like the report tool to persist between sessions then use
sh run_reports.sh --daemon
to run it as a background process. As with Galaxy itself, use --stop-daemon to halt the background process. (The log file is written to reports_webapp.log if you need to try and debug a problem.)
2. Expose the report tool via nginx
If you're running a production Galaxy and want to be able access the reports from a browser running on a different machine to your Galaxy server then you can could consider using SSH tunnelling, which essentially forwards a port on your local machine to one on the server i.e. port 9001 where the report tool is serving from (see "SSH Tunneling Made Easy" at http://www.revsys.com/writings/quicktips/ssh-tunnel.html for more details of how to do this).
Alternatively if you are using a web proxy (as is standard for a production setup) then you could try serving the reports also via the proxy (in this case nginx). In this example I assume that if Galaxy is being served from e.g. http://galaxy.example.org/ then the reports will be viewed via http://galaxy.example.org/reports/.
First, make the appropriate edits to reports_wsgi.ini: if you have an older Galaxy instance then you'll need to add some sections to the file, specifically:
[filter:proxy-prefix]
use = egg:PasteDeploy#prefix
prefix = /reports
(before the [app:main] section), and
filter-with = proxy-prefix
cookie_path = /reports
(within the [app:main] section.)
For more recent latest Galaxy instances it's simply a case of making sure that the existing filter-with and cookie_path lines are uncommented and set to the values above.
Next it's necessary to add upstream and location sections in your nginx.conf file:
(This has many similarities to serving Galaxy from a subdirectory via nginx proxy at a subdirectory, see https://wiki.galaxyproject.org/Admin/Config/nginxProxy).
One important thing to be aware of is that the report tool doesn't include any built-in authentication, so it's recommended that you add some authentication within the web proxy. Otherwise anyone in the world could potentially access the reports for your server and see sensitive information such as user login names.
To do this with nginx, first create a htpasswd file to hold a set of user names and associated passwords, using the htpassword utility, e.g.:
htpasswd -c /etc/nginx/galaxy-reports.htpasswd admin
-c means create a new file (in this case /etc/nginx/galaxy-reports.htpasswd); admin is the username to add. The program will prompt for a password for that username, and store it in the file. You can use any username, and any filename or location (with the caveat that it must be readable by the nginx process) that you wish.
Finally to associate the password file with the reports location update the nginx config file appropriately by adding two more lines:
(I found this article very helpful here; note that it also works for https in spite of the title: "How to set up http authentication with nginx on Ubuntu 12.10" https://www.digitalocean.com/community/tutorials/how-to-set-up-http-authentication-with-nginx-on-ubuntu-12-10).
Once nginx has been restarted then anyone attempting to view the reports at http://galaxy.example.org/reports/ will be prompted to enter a username/password combination matching an entry in the htpasswd file before they are given access. Authorised users can then peruse the reports to their heart's content.
Subscribe to:
Posts (Atom)
