Meteor and Plesk do not know each other very well. This is not inherently bad but it makes things a bit more complicated, when it comes to deploy a Meteor app on a server that is managed mainly via Plesk. This post gets to the bottom of it and shows an easy reproducable way to manually install your Meteor bundle on your server using Plesk Onyx.

An Important Note: This guide is still incomplete and since the current Meteor release 1.6 uses new versions of Node and Mongo it will be updated soon.



If you are in the position of not using one of the handy hosting services that are specially designed for Meteor applications, then you may end up using a virtual or dedicated server with an administration environment like Plesk.

This has also many advantages when it comes to host a Meteor app in combination with some static webpages or a php based cms, such as WordPress, Drupal or Joomla.

The dev-team at Plesk has also implemented an extension to easily install and run Node.js applications using Fusion Passenger under the hood. However, because of Meteor being a (great) non-conformist among the modern js frameworks, we have of course to do some extra work to get the job done.

The system I am about to describe in this guide consists of a Ubuntu 16.04.2 LTS Server with Plesk Onyx 17.5.3 installed.


Prerequisites and Notes

The Meteor application I am about to deploy is a simple default app, created via meteor create and then built by meteor build.  Skip this part, if you intend to deploy your existing build. If you are totally new to deployment and have just been in the realm of dev, then you may read the deployment section of the official Meteor guide first.

Sometimes I will refer to node or node application, which is just a shorthand for Node.js application.

A Dollar character at the start of a line indicates command line input


1. Prepare your environment (optional)

As already mentioned, you can skip this step if your environment is already prepared for your productive app.


1.1 Create the application and the tarball
$ meteor create my app
$ (cd ./myapp && meteor build ../)

You just created a full running Node.js application ready for takeoff. In your current directory should be a folder named myapp and a tarball archive named myapp.tar.gz.


Further readings for this step


1.2 Create a new domain in your Plesk panel

Plesk allows you to manage your different apps and cms on one server via domains (which are basically namespaces with some Apache Virtualhosts in the backend running).

In order to create a new domain for our app do the following:

Go to Websites and Domains -> + Add Domain -> Enter your domain credentials

You have created a default domain, which will serve your Meteor app. It will currently display some static html default using apache. Here is how to switch that off.

Go to Websites and Domains  -> On your created Domain click 'Hosting Settings' -> Webscripting and Statistics -> Turn all web scripts off besides statistics protection

It should then look like the following:

image on plesk domain webscipting and statistics


1.3 Upload the archive to your server

The newly created domain should provide you an FTP upload section. Alternatively you can also use SFTP if you have serious concerns about your wires.

Go to Websites and Domain -> on your Domain click on "File Manager" -> make sure you are in the folder of the current domain and not any sub- or parent directory -> upload your tarball

After you uploaded your tarball you create a new folder, named app in the same directory next to the archive. I will later explain the reasons. For now you are done with the first step. Now let’s install a Meteor compatible Node.js version.


2. Install Node.js Extension in Plesk

First, you need to install the Node.js extension for Plesk in order to comfortably run node applications. A compiled Meteor production app bundle (as the one created on the step before) is basically a node application. After this guide it will run like any other node application on your server. This part uses basically the content from the official Plesk blog article about setting up and using Node.Js.

Go to Extensions -> Web Development -> Node.js -> Install

Alternatively, you can also install it as described in the official blog article:

Go to Tools & Settings -> Updates and Upgrades -> Add/Remove Components -> Find “Node.js support” -> select it -> continue with the installation.



3. Install the required Node.js in order to run Meteor with Plesk

Meteor deployment involves, that the production app requires the exact same node version in order tun run without unpredictable behavior. To find out your current version you can type in your terminal the following command:

$ meteor node -v

$ 8.9.4

Our default Node.js extension in Plesk may not support this exact version. We therefore need to install another specific version  on our server. Fortunately, there is a Plesk forum post, that already solved this issue for us. The next steps are based on this post.

3.1. SSH into your server from terminal
$ ssh yourPleskUser@yourServerIp
$ Enter your password:


3.2. Download your node binaries from node source.

Tere is a list of all binary packages for several versions of node. Note, that you have to choose the one that fits your required node version and your server’s architecture. To install the package you can use the new apt install command. It allows to auto install a .deb package while also resolving dependencies. The following example installs node 8.9.4 on a 64 bit Ubuntu:

$ cd /tmp
$ wget
$ apt install nodejs_8.9.4-1nodesource1_amd64.deb
3.3. Link this version with plesk

The previous installed node version needs to be registered to your plesk installation:

$ plesk sbin nodding register /usr/bin/node

2.4. Verify your installation linking:
$ plesk sbin nodemng versions
v8.9.4 /usr/bin/node
v6.9.1 /opt/plesk/node/6/bin/node
v7.4.0 /opt/plesk/node/7/bin/node


3.5. Refresh on your plesk panel:
Extensions -> Node.js -> Go to Extension -> Refresh

Your result should look like on the image, listing also your installed binaries (in the image you see the old 4.8.4 version being installed):

Once you have reached this point, you are good to continue to the next step and setup your application.


4. Setting up your Meteor Application

This part covers an entire manual setup. Better replace these steps with scripts to minimize errors and maximize productivity. Anyway, after this step you know what is going on with installing a Meteor bundle correctly and reproduce this step in whichever way you like.

There are some factors, that influence the way we structure the setup:

A – The Meteor bundle contains a structure, that differs from common node applications

B – Plesk uses Phusion Passenger to run the app

C – Plesk requires an application root directory, a document root directory and an application startup file.

D – Ownership and permissions need to be set correctly in order to install run the app with our errors


4.0 Backup existing app bundle

If you have already installed an app bundle (for instance after this guide), you may want to back it up for the case, where the installation fails.

4.1 Untar your Meteor bundle

If not already logged on to your root console, do it now. Go to your hosts directory. Mostly this is located as a subdirectory of /var/www/. If you have a vserver, there may be some folder called vhosts.

$ cd /path/to/hosts/yourhost

Do not cd into the app folder yet.


4.4 Softlink to main.js and set startupfile

If the configuration seems reasonable, the Node.js extension automatically starts your app with the passenger server. This includes to link to the main.js file in the bundle directory. Because the bundle is a parent of our application directory, we need to link it with a soft link:

$ cd /path/to/app/bundle/programs/server
$ ln -s ../../main.js phusion.js

You can, of course, also name it main.js if the naming confuses you. Note, that this whole step 3 is very error prone and you should definitely find a way to automate it. Otherwise you will one day find yourself in the hell of updating tasks.


4.5 Install NPM Dependencies:

Click the NPM install button to install your packages. Note, that this may take a while, depending on number of packages and native bindings, such as node-gyp-based bcrypt. Unfortunately it does not give you an output on the UI.

If it takes really too long and you have the feeling, that it does complete or has error, you may run your root console and check the application directory, which should now contain a node_modules folder. (/domainname/bundle/programs/server/node_modules) You can cd into this folder and check the installed packages via npm ls and look for entries, such as error or missing.

Another crucial issue is permission. Check, if your bundle directory and it’s subdirectories are owned by the current vhost user. If not set the ownership recursively to the same settings as the parent directory of /bundle.



5. Running your Meteor App from the Plesk Panel

A last configuration before the final takeoff is about environment variables. Plesk offers you a comfortable way to edit these variables directly without the need of scripts or command line use. You have to enter the environment variables, as required by your application and Meteor. A complete description on environment variable can be viewed in the official docs.

5.1 Enable Fusion Passenger (if not already enabled)
Tools & Settings -> Apache Webserver -> passenger

And look for Passenger to be enabled.

5.2. Link your installed app with passenger

This step assumes, that you successfully built your Meteor application, as described in the official guide. Note, that all paths are relative to the domain’s home directory, which is just named /apphere as a replacement.

While a regular node app has it’s app.js and it’s package.json in it’s root directory, a Meteor bundle contains these files under /app/bundle/programs/server which represents the Meteor server application. Thus we need to link this path as our application directory and set our document directory to /domainname/bundle/programs/server/path/to/assets Beware, that if you have no assets folder in your Meteor dev project, you need to create one as child of your application directory. Mostly the problem will be of incorrect permissions. Check, that your current plesk user has permissions for this directory.




The plesk nodes extension automatically recognizes  the package.json file and displays some buttons like “NPM install” and “Run script”. If you do not see these buttons, then there is an issue with your path configurations.

Important note: In the image, the startup file is named phusion.js but it should be named main.js which is the file, we soft-linked in the last section. I just named it that way in a former step but it caused confusion so keep it main.js.



6. Proxy Settings and Websocket

If you reached this point and your app is running it is already time for a small “hooray”. Unfortunately there is by default no web socket passthrough by the nginx configuration, that Plesk auto generated. However, if you think this is exhausting, you may check out (only readymade!!!) some files on your server at /etc/nginx/ and it’s subfolders. Considering, that all these nginx conf files are auto generated to make our app run out-of-the-box, the next steps are just a tiny bit of work that is left.

There is an official nginx guide on how to create a web socket proxy for Node.js applications. Unfortunately, this does not 100% work out for our Plesk system, since most of the configuration is not writable by your nginx domain settings. You are only allowed to add another location directive. This is the point with another “aha” effect: you need to provide another location than / because this is already in use by the default configuration. Therefore we installed our bundle under /app and bypassed this issue.

Anyway, we will make use of that guide to test our web socket connection.


6.1. Install wscat on your local machine
Enter the following command on your client machine outside of your meteor project directory. This installs the wscat npm module as a global module and lets you test the web socket connection to your production app.
meteor npm install -g wscat
Note, that this guide assumes, that you have npm not globally installed but only as part of your meteor distribution.


6.2. Initial web socket connection test

Enter in your terminal

meteor wscat --connect ws://yourapplication.tld/websocket

which should return by default

error: Error: unexpected server response (400)

This is normal behavior. You app is running via passenger and nginx does not know how to pass the web socket request to your passenger app.


6.3. Gather information for your nginx directives

Before you can set your nginx proxy pass to passenger, you need to check how your internals of private ip and ports are set. You can make use of netstat to get the most important information on that.

Type on your terminal (server) the following command:

netztet -tulpn

Which generates a list of your active connections:

Active Internet connections (only servers)

Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name


tcp        0      0 172.x.x.x:443*               LISTEN      1114/nginx


tcp        0      0 172.x.x.x:80*               LISTEN      1114/nginx


As you can see, the example settings use a private B class IP of the 172 subnet. Copy or note that ip because you need it for the next step.


6.4. Create a nginx proxy pass for your app

After a long search I found a post on the plesk forum, that solved my nginx proxy settings in order to enable web socket connections.

Go to Websites and Domains -> your domain -> Apache & nginx Settings

Disable or uncheck the proxy mode checkbox to exclude apache. We will not use apache for our app at all.

Scroll to the bottom and put the following nginx directives into the field, named Additional nginx directives:

location /app { 
    proxy_pass http://PRIVATE_IP:APP_PORT;
    proxy_http_version 1.1;
    proxy_read_timeout 36000s; 
    proxy_send_timeout 36000s;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_set_header Host $host;

Where PRIVATE_IP equals the private ip you copied in the former step and APP_PORT equals the port number you passed to your Meteor app as environment variable. You can read a  detailed explanation of what these directives do in the nginx documentation.

Some note on security: This does not include any XSS preventions and other important security settings. Those will be added soon.

Click “Apply” and check your web socket connection again via wscat.

meteor wscat --connect ws://yourapplication.tld/websocket
connected (press CTRL+C to quit)

This is a sign, that it should have established a successful web socket handshake. However, this test connection also can make your http headers fall to http 1.0. Click “Apply” again to recover your proxy settings. The web socket related error in your client console should also disappear now. If you can’t still establish a connection you have to check various settings. If you have multiple Node.js applications on the same server, make sure you have set the proxy settings for all of them. Also check, that there is proxying to Apache being disabled.


Some last words

This guide describes my findings during the setup I created. Depending on your setup, problems and errors may occur, that this guide does not cover. If you experience issues apart from those in the guide, feel free to leave a comment. This also improves the quality of the guide.

Jan Küster

I have graduated in Digital Media (M.Sc.) at the University of Bremen. After working as a consultant I am now developing the next level of leaning software with Meteor.

1 Comment

MasterecoFf · 2018/09/22 at 20:10

It’s always a good idea to use SSL for Meteor applications (see the Security Article to find out why). Once you have a registered domain name, you’ll need to generate an SSL certificate with a certificate authority for your domain. If you deploy to Galaxy, you can generate a free SSL certificate with a single click (courtesy of Let’s Encrypt!).

Leave a Reply