Marvin Live install guide
Marvin Live is a NodeJS based application for real time collaboration between chemists. It includes an HTTP and WebSocket server to serve multiple clients running the embedded web application.
Installation is only required for the server, clients access the web server through the configured host and port.
Server requirements
-
Windows Server 2008 or newer, or Ubuntu 16.04.3 LTS, RHEL/CentOS 7.0 or newer
-
Up to 1GB free RAM
-
100MB free space
-
optionally, check JChem Web Services’s requirements as well
-
live internet connection to https://hub.chemaxon.com/ and https://github.com during installation
Client requirements
-
Latest Chrome, Firefox 31 or newer, Opera 15 or newer, IE 11 or newer, Safari 10 or newer
Installing NodeJS
You need NodeJS 6.12.2 or newer to run Marvin Live. Download the installer from http://nodejs.org/ and follow the installation wizard. Linux users may install from their mainline repositories if available, or use NodeSource’s fantastic install scripts. NodeJS v6 and v8 LTS releases are supported, but NodeJS v6 support requires newer Linux distributions, with glibc version 2.14 or newer. To verify a successful installation, open the terminal and type:
user:~$ node -
v
v6.12.2
NodeJS installs its package manager as well, called npm. To verify it’s been installed:
user:~$ npm -
v
3.10.10
Note 1: if node or npm command are unrecognized, it’s missing from the environmental variables. On Windows, closing and opening the command prompt or restarting the server may help.
Note 2: on Ubuntu servers, if you install NodeJS from the mainline repository, the node executable may be called nodejs.
Prerequisites on RedHat / CentOS 6.x releases
From version v16.11.7, RedHat / CentOS 6.x releases with glibc 2.14 or older require additional steps before a successful installation.
# confirm affected libc version
bash-
4.1
# ldd --version
ldd (GNU libc)
2.12
# install software collections, devtools and enable it
bash-
4.1
# yum install centos-release-scl scl-utils
bash-
4.1
# yum install devtoolset-
3
-gcc devtoolset-
3
-gcc-c++
bash-
4.1
# scl enable devtoolset-
3
bash
Installing Marvin Live - network installer
Now you need to point npm to the ChemAxon download site and login. Please follow the Public Repositories guide if you don't already have the ChemAxon npm repository configured. This is required the first time only.
Public Repository
user:~$ curl -o ~/.npmrc -u<email address>:<api key> https:
//hub
.chemaxon.com
/artifactory/api/npm/auth
user:~$ npm config
set
registry https:
//hub
.chemaxon.com
/artifactory/api/npm/npm
You may set your proxy configuration now, these setting will be used for outgoing HTTP requests that download Marvin Live and its components.
user:~$ npm
set
http_proxy ...
user:~$ npm
set
https_proxy ...
Choose an application directory where you want to install the application, to store configuration files and persistent storage. Once there, you can install the application with:
user:~$
mkdir
app
user:~$
cd
app/
user:~
/app
$ npm
install
marvin-live
This will download and install the latest version of the application in the app directory. You can find the full list of recently added features and changes in the History of changes document.
Note: at this point on Windows 8 and Windows Server 2008 and Windows Server 2012, you may get this error: Error: ENOENT, stat 'C:\Users\User\AppData\Roaming\npm'. This error message is about a missing folder. You can resolve this issue by creating the quoted folder or starting the command prompt as administrator.
Upgrading to a new version
You can upgrade Marvin Live with the install command, which will fetch the latest version. To install a specific version (not recommended), append its version number to the package name with the following syntax: [email protected]
user:~
/app
$ npm
install
marvin-live
This will replace the existing Marvin Live installation folder, but leave any configuration, persistence intact.
Installing Marvin Live - offline bundle
With the offline installer bundle, you can warm the cache with all required dependencies that would be otherwise fetched from the (external) NPM repository.
user:~$ .
/addcache
.sh
...
user:~$ npm
install
/data/npm/marvin-live-17
.30.0-offline.tgz
This will install the latest version of the application in the app directory. You can find the full list of recently added features and changes in the History of changes document.
Note: at this point on Windows 8 and Windows Server 2008 and Windows Server 2012, you may get this error: Error: ENOENT, stat 'C:\Users\User\AppData\Roaming\npm'. This error message is about a missing folder. You can resolve this issue by creating the quoted folder or starting the command prompt as administrator.
Upgrading to a new version
You can upgrade Marvin Live by re-running the above command and a new offline installer package
user:~
/app
$ npm
install
/data/npm/marvin-live-17
.30.0-offline.tgz
This will replace the existing Marvin Live installation folder, but leave any configuration, persistence intact.
Configuration
This application requires a configuration file to be passed as a command line argument. The configuration file holds all the key settings regarding networking, security, persistence, plugins and more. A sample file with defaults is provided within the application: ~/app/node_modules/marvin-live/config-sample.json.
Please copy this to your application directory, and rename it to your preference. Do not modify this file in place, and do not store your settings within the node_modules directory, because it is automatically removed / replaced on upgrade !
user:~
/app
$
cp
node_modules
/marvin-live/config-sample
.json \
.
/config
.json
Note: on Windows, make sure you save the json file with ANSI encoding when editing with a text editor such as Notepad.
The minimum configuration requires port and license attributes to be specified, but a more general sample of the options is below:
{
"converterService"
:
"http://localhost:8080/webservices/"
,
"servicesDirectory"
:
"../services/"
,
"port"
: 8888,
"license"
: [
"./marvin4js-license.cxl"
,
"./mlive-license.cxl"
],
"secretKey"
:
"CHANGETHIS"
,
"authentication"
: {
"internal"
: {
"type"
:
"local"
,
"label"
:
"Testing domain"
,
"accounts"
: [{
"username"
:
"demo"
,
"password"
:
"demo"
}]
}
},
"snapshotFields"
: [{
"name"
:
"task"
,
"label"
:
"Task"
}, {
"name"
:
"status"
,
"label"
:
"Status"
,
"values"
: [
"Not ready for review"
,
"Ready for review"
,
"Approved"
,
"On hold"
,
"Synthesized"
,
"Cancelled"
]
}]
}
Below you can find a detailed description for each option:
Note: All relative paths are resolved against the location of config.json.
Parameter name |
Type |
Description |
||||||||||||||||||
converterService |
string |
URL to JChem Web Services without the rest-v0/ ending. Marvin Live will proxy requests by Marvin JS to this location for format converters and cleaners. Required: no |
||||||||||||||||||
servicesDirectory |
string |
Path to the folder where your real time, resolver, exporter and storage plugins are stored. For further details and examples, check the developer guide . Required: no |
||||||||||||||||||
license |
string or array of strings |
Path to the license file(s) provided by ChemAxon for this application. Accepts wildcards like *.cxl as of v16.12.5. Required: yes |
||||||||||||||||||
tls |
object |
HTTPS server options in key-value pair form.
All options of the NodeJS TLS module are supported. For more configuration options and details please see the official module description . |
||||||||||||||||||
hostname |
string |
Hostname of the server. Needed only for single sign-on authentication, where a service callback needs to registered. Required: if SAML authentication is configured |
||||||||||||||||||
port |
number |
The HTTP port you want the application to bind to. Naturally this port needs to be free. Default: 80 Required: yes |
||||||||||||||||||
secretKey |
string |
Key to sign the session cookie with to prevent tampering. This string should be known only to the administrator of the server. The following command will generate a random string you can consider using: node -p "require('crypto').randomBytes(20).toString('base64');" Required: yes |
||||||||||||||||||
authentication |
object |
The available identity providers users can authenticate with, in key-value pair form. Key: identifier or name of the domain, containing only lowercase letters, numbers and -, i.e: [a-z0-9-]+ Value: object containing the settings for the domain and protocol specific settings. Each option must have the following attributes, but may specify further options:
Provider specific options are document below in separate sections: LDAP, SAML, local. |
||||||||||||||||||
hideDomainsOnLoginScreen |
boolean |
Hides the domain picklist from the login page. When set to true, generated login URLs are printed on STDOUT , one for each authentication domain. Default: false |
||||||||||||||||||
databaseLocation |
string |
Path to the folder where databases can be created and kept. Default: in the folder of config.json |
||||||||||||||||||
deleteUnusedRooms |
string |
Duration of inactivity in a room before it can be deleted in the following syntax: [0-9]+[m|h|d]. This option is available in authenticated domains as well to control different domains individually. Examples: "90m" : delete after 90 minutes of inactivity "24h" : delete after 24 hours of inactivity "30d" : delete after 30 days of inactivity Default: no deletion |
||||||||||||||||||
databaseCleanupInterval |
number |
Frequency of checking inactivity in rooms for cleanup, see deleteUnusedRooms. This option is available in authenticated domains as well to control different domains individually. Examples: When deleteUnusedRooms is "90m", databaseCleanupInterval could be lowered to 10 minutes by setting 600000. Default: 3600000 (1 hour in milliseconds) |
||||||||||||||||||
saveReportOnDelete |
string |
Path to the folder where an MRV formatted meeting report should be saved before a room is deleted with deleteUnusedRooms. This option is available in authenticated domains as well to control different domains individually. Default: no automatic saving |
||||||||||||||||||
themeOverrides |
string |
Path to a CSS file that adds or changes styles used in the Marvin Live theme. Default: no custom CSS file |
||||||||||||||||||
allowCrossOriginUploads |
boolean |
Enable CORS on the /upload/api endpoint (URL integration guide). Default: false |
||||||||||||||||||
enablePrivateRooms |
boolean |
Enable or disable the creation of private rooms from the lounge. Only available in authenticated domains, where a persistent user handle is available (username, DN, NameID). Default: true |
||||||||||||||||||
enablePublicRooms |
boolean |
Enable or disable the creation of public rooms from the lounge. Default: true |
||||||||||||||||||
marvinjs |
object |
Configure Marvin JS’s display options and services (API reference). This option is available in authenticated domains as well to control different domains individually.
Reference: https://marvinjs-demo.chemaxon.com/latest/jsdoc.html Example: "marvinjs" : { "templates" : "./templates.mrv" , "webservices" : { "clean2dws" : "/rest-v0/util/convert/clean" , "molconvertws" : "/rest-v0/util/calculate/molExport" , "reactionconvertws" : "/rest-v0/util/calculate/reactionExport" , "stereoinfows" : "/rest-v0/util/calculate/cipStereoInfo" }, "displaySettings" : { "toolbars" : "reporting" } } |
||||||||||||||||||
additionalSnapshotFields |
array of objects |
Deprecated as of v17.30.0. Please see snapshotFields configuration below. Configure what metadata fields - besides Task - should be prompted and tracked for each snapshot. This option is available in authenticated domains as well to control different domains individually. A field has the attributes:
Example: "additionalSnapshotFields" : [{ "label" : "Series" , "placeholder" : "CXN123" , "pattern" : "^CXN\\d+$" }, { "label" : "Chemist" }, { "label" : "Status" , "values" : [ "Not ready for review" , "Ready for review" , "Approved" , "On hold" , "Synthesized" , "Cancelled" ] }], Available from v16.10.17. Deprecated with v17.30.0. |
||||||||||||||||||
snapshotFields |
array of objects |
Replaces the previous additionalSnapshotFields configuration. Configure what metadata fields should be prompted and tracked for each snapshot. This option is available in authenticated domains as well to control different domains individually. A field has the attributes:
Example: "snapshotFields" : [{ "name" : "task" , "label" : "Task" }, { "name" : "series" , "label" : "Series" , "placeholder" : "CXN123" , "pattern" : "^CXN\\d+$" }, { "name" : "status" "label" : "Status" , "values" : [ "Not ready for review" , "Ready for review" , "Approved" , "On hold" , "Synthesized" , "Cancelled" ] }], Default: "snapshotFields" : [{ "name" : "task" , "label" : "Task" }], Available from v17.30.0 |
Note 1: port 0 is treated as an ephemeral port, i.e: a random open port will be chosen.
Note 2: On Linux/Unix servers non-root processes aren’t allowed to use port <1024, unless you change cap_net_bind_service in setcap. See below for the details of using setcap.
# Since Linux kernel 2.6.24, you can use the setcap command to set specific capabilities to a program.
# setcap functions per-program, therefore this enables all NodeJS programs to bind on any port lower than 1024,
# and if you update your NodeJS version, you will need to run this command again:
sudo
setcap
'cap_net_bind_service=+ep'
`
which
node`
Starting Marvin Live
You can start the server in foreground mode with:
user:~
/app
$ node node_modules
/marvin-live/
-c config.json
When the application is ready to use, it prints Listening on http://localhost:80/.
To stop a running instance, simply press Ctrl+C.
Given the IP or hostname of your server and the port set in the configuration, you may now distribute the web interface link to the users of the application.
Setting up a service
To run Marvin Live as a daemon/service, you could create configurations in supervisord/supervisorctl or use an init script. Below you can find an example for both:
[program:marvinlive]
command
=
/usr/bin/node
/home/user/app/node_modules/marvin-live/
-c
/home/user/app/config
.json
autostart=
true
autorestart=
true
stderr_logfile=
/var/log/marvinlive
.err.log
stdout_logfile=
/var/log/marvinlive
.out.log
user=user
#!/bin/bash
# /etc/init.d/marvin-live -- startup script for the Marvin Live
################ BEGIN RED HAT init info #######################
# Provides: marvin-live
# Required-Start: $local_fs $remote_fs $network
# Required-Stop: $local_fs $remote_fs $network
# Should-Start: $named
# Should-Stop: $named
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Start Marvin Live.
# Description: Start the Marvin Live nodejs application and frontend.
#
################ END RED HAT init info #######################
################## BEGIN Debian/Ubuntu init info ##################
# Provides: marvin-live
# Required-Start: $remote_fs $named $syslog
# Required-Stop: $remote_fs $named $syslog
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Debian initscript for marvin-live
# Description: Start the Marvin Live nodejs application and frontend.
#
################## END Debian/Ubuntu init info ##################
name=
"Marvin Live"
nodejs_bin=
"/usr/bin/nodejs"
dir_home=
"/home/user/app/"
app_home=
"$dir_home/marvin-live"
file_log=
"$dir_home/log/marvin-live.log"
dir_tmp=
"$dir_home/tmp"
user=user
date
=$(
date
"+%Y-%m-%d %H:%M:%S"
)
f_get_pid(){
if
pid=$(pgrep -f
/node_modules/marvin-live
);
then
echo
"PID: $pid"
else
echo
"$name is not running"
fi
}
case
$1
in
start)
echo
"Starting $name"
su
-s
/bin/bash
$user -c
"echo $date -- Starting $name"
>> $file_log
su
-s
/bin/bash
$user -c
"$nodejs_bin $app_home/node_modules/marvin-live/ -c $app_home/config.json >>$file_log 2>&1 &"
f_get_pid
;;
stop)
echo
"Stopping $name"
f_get_pid
kill
$pid
su
- $user -c
"echo $date -- Stopping $name >> $file_log"
;;
restart)
$0 stop
sleep
2
$0 start
;;
status)
f_get_pid
;;
*)
echo
"Usage: $0 {start|stop|restart|status}"
exit
1
esac
Converter and cleaner web services, optional
Marvin Live can forward HTTP requests made by Marvin JS to a converter web service. Your license includes the use of JChem Web Services as that converter, so please follow the JChem Web Services installation guide to set it up - to make things simpler, you may skip all database related installation steps. Once done, you can point Marvin Live to it in the configuration’s converterService option.
Setting up local authentication
Marvin Live supports a very simple local authentication intended for personal testing or evaluation purposes. This enables all features depending on tracking users and storing profiles, without having to setup identity provider connections. Accounts are read from a list specified in config.json. Below you can find a sample:
{
"port"
: 80,
"hostname"
:
"example.com"
,
"tls"
: {
"key"
:
"../certs/example-com-key.pem"
,
"cert"
:
"../certs/example-com-cert.pem"
},
"secretKey"
:
"lalilulelo"
,
"authentication"
: {
"test"
: {
"type"
:
"local"
,
"label"
:
"Test Ltd"
,
"accounts"
: [
{
"username"
:
"demo"
,
"password"
:
"demo"
},
{
"username"
:
"demo2"
,
"password"
:
"demo2"
}
]
}
}
}
Setting up LDAP authentication
The application supports LDAP and LDAPS authentication, which works with Active Directory as well. The most common configuration options are supported. Below you can find a sample configuration and a full list of options:
{
"port"
: 80,
"hostname"
:
"example.com"
,
"tls"
: {
"key"
:
"../certs/example-com-key.pem"
,
"cert"
:
"../certs/example-com-cert.pem"
},
"secretKey"
:
"lalilulelo"
,
"authentication"
: {
"corporate"
: {
"type"
:
"ldap"
,
"label"
:
"ACME Inc"
,
"url"
:
"ldaps://ipa.acme.com:636"
,
"bindDn"
:
"uid=serviceaccount,cn=accounts,dc=acme"
,
"bindCredentials"
:
"BF95KPnVD9FxyGPh"
,
"searchBase"
:
"cn=accounts,dc=acme"
,
"searchFilter"
:
"(uid={{username}})"
}
}
}
LDAP specific configuration options
Name |
Type |
Description |
url |
string |
full URL of LDAP server, including protocol and port, e.g: ldaps://ldap.company.tld:636/ |
bindDn |
string |
DN of user permitted to search the LDAP server within the defined search base |
bindCredentials |
string |
password for bindDn |
searchBase |
string |
part of the directory to search in for the user, e.g: cn=users,dc=company |
searchFilter |
string |
search filter that should match the user with either 1 or 0 entries. Use literal {{username}} to add the given username to the search, e.g: (uid={{username}}) |
firstName |
string |
LDAP attribute that holds the display name of the user |
Setting up SAML authentication
This application uses HTTP Redirect Binding for its AuthnRequests, and expects to receive the messages back via the HTTP POST binding.
Configuration
First, you’ll need to configure the application with a host. You can do this by setting port, and hostname. Next, it’s strongly recommended to setup HTTPS with the tls settings, to make sure any login details are only transmitted over a secure channel.
{
"port"
: 80,
"hostname"
:
"example.com"
,
"tls"
: {
"key"
:
"../certs/example-com-key.pem"
,
"cert"
:
"../certs/example-com-cert.pem"
}
}
Next, add a secretKey and configure your identity provider in authentication:
{
"port"
: 80,
"hostname"
:
"example.com"
,
"tls"
: {
"key"
:
"../certs/example-com-key.pem"
,
"cert"
:
"../certs/example-com-cert.pem"
},
"secretKey"
:
"lalilulelo"
,
"authentication"
: {
"internal"
: {
"type"
:
"saml"
,
"label"
:
"Example"
,
"entryPoint"
:
"http://idp.example.com/oam/SSORedirect/metaAlias/apps/idp"
}
}
}
Registering as Service Provider
Using the domain chosen in the authentication settings, in this example "internal", you can now register the Marvin Live service with your SAML provider. A service metadata descriptor is available if you open:
https://example.com/login/internal/metadata
The service’s issuer / entity ID is marvin-live-app and the callback URL is generated from the tls, hostname, port and domain name options.
<?
xml
version
=
"1.0"
?>
<
EntityDescriptor
xmlns
=
"urn:oasis:names:tc:SAML:2.0:metadata"
xmlns:ds
=
"http://www.w3.org/2000/09/xmldsig#"
entityID
=
"marvin-live-app"
>
<
SPSSODescriptor
protocolSupportEnumeration
=
"urn:oasis:names:tc:SAML:2.0:protocol"
>
<
KeyDescriptor
/>
<
NameIDFormat
>urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified</
NameIDFormat
>
<
AssertionConsumerService
index
=
"1"
isDefault
=
"true"
Binding
=
"urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
Location
=
"https://example.com:8888/login/internal/callback"
/>
</
SPSSODescriptor
>
</
EntityDescriptor
>
SAML specific parameters
Name |
Type |
Description |
entryPoint |
string |
URL for the identity provider. Required: yes |
cert |
string |
Path to the identity provider’s certificate used to validate any SAML authorization responses. |
privateCert |
string |
Path to the certificate used to sign any SAML authentication requests. |
decryptionPvk |
string |
Path to the private key of the identity provider, used to decrypt any encrypted assertions that are received |
decryptionCert |
string |
Path to the certificate used to attach to the service metadata. |
identifierFormat |
string |
Name ID format to request from the identity provider. The use of unspecified and transient are not recomennded to enable private room usage. Default: urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress |
callbackUrlBase |
string |
Alternative Marvin Live server URL to use when generating metadata, and in SAML requests. Used when the application is behind a reverse proxy. |
Further options are available, please see this third-party module’s options.
Marvin Live behind a proxy
Marvin Live uses a persistent websocket connection between each client and the server for messaging. If you deploy the application behind a proxy, you need to make sure the proxy doesn't interfere with websockets. In case of nginx, you should review the websocket module’s configuration options .
Persistent storage
Marvin Live includes an embedded database that keeps a history of all meeting rooms and their content - chemical structures drawn and comments. The purpose of this database is to prevent data loss during upgrades or configuration changes, but it’s used to store session information as well. To support typical data retention policies, Marvin Live can be configured to automatically delete unused meeting rooms with all included data, see deleteUnusedRooms.
A separate database instance is created per authentication domain - stored in a folder named db-name. If no authentication domain is specified, all meeting content is stored in a db-app folder. Session store is located in sessiondb. The location of these database folders can be changed with the databaseLocation setting.
Installing a plugin
As described in the developer guides (see listing in the documentation index), Marvin Live comes with an ecosystem of plugins for a variety of uses. These plugins are static files stored in the servicesDirectory as defined in config.json and since the plugins are NodeJS modules, they can define their own dependencies, independent from what Marvin Live might provide and how that might change over time. For this reason, plugin dependencies need to be installed in the servicesDirectory. Installation goes exactly like with Marvin Live itself: npm install
user:~/app/$ grep
"servicesDirectory"
config.json
"servicesDirectory"
:
"../services/"
,
user:~/app/$ cd ../services/
user:~/services/$ ls -al
drwxr-xr-x
78
user group
2496
Nov
23
09
:
54
.
drwxr-xr-x
75
user group
2400
Nov
16
12
:
39
..
-rw-rw-r--
1
user group
63
Nov
22
18
:
40
cc.credentials.json
-rw-r--r--
1
user group
1574
Nov
23
09
:
53
compliancechecker.realtime.js
-rw-r--r--
1
user group
587
Oct
6
13
:
00
compliancechecker.template.html
-rw-r--r--
1
user group
2772
Aug
28
16
:
41
knimerest.realtime.js
-rw-r--r--
1
user group
633
Mar
10
2017
knimerest.template.html
-rw-r--r--
1
user group
2819
Oct
6
13
:
02
ml-utils.js
-rw-r--r--
1
user group
575
Oct
6
12
:
54
package
.json
-rw-r--r--
1
user group
484
Nov
23
16
:
37
smiles.export.js
user:~/services/$ less
package
.json #inspect dependencies
user:~/services/$ npm install