striker78
By:
striker78

Need help deploying meteor app on a DO droplet with ubuntu 16.04 with nginx

November 6, 2016 264 views
Applications DigitalOcean Nginx Node.js Ubuntu 16.04

My Meteor app is not working in Ubuntu 16.04.
I'm stuck and would really appreciate any help.

I created a systemd service config for my Meteor app.
My app appears to start but I get a 502 in the browser.

It appears that my service is running

root@ubuntu# journalctl -f -u mymeteorapp
    Nov 06 22:33:52 ubuntu systemd[1]: Started mymeteorapp.service.

root@ubuntu:~# systemctl status mymeteorapp
    Nov 05 12:48:42 ubuntu systemd[1]: Started Meteor.js (NodeJS) mymeteorapp application.
    root@ubuntu:~#

But I get this nginx error

root@ubuntu:/lib/systemd/system# tail -f /var/log/nginx/error.log
    2016/11/06 22:34:29 [error] 13486#13486: *248 connect() failed (111: Connection refused) while connecting to upstream, client: 84.23.134.181, server: 36.102.142.66, request: "GET / HTTP/1.1", upstream: "http://127.0.0.1:8080/", host: "36.102.142.66"

Running netstat shows this:

root@ubuntu:/lib/systemd/system# netstat -plnt
    Active Internet connections (only servers)
    Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
    tcp 0 0 0.0.0.0:443 0.0.0.0:* LISTEN 4849/nginx -g daemo
    tcp 0 0 127.0.0.1:27017 0.0.0.0:* LISTEN 17393/mongod
    tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 4849/nginx -g daemo
    tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 1467/sshd
    tcp6 0 0 :::80 :::* LISTEN 4849/nginx -g daemo
    tcp6 0 0 :::22 :::* LISTEN 1467/sshd

But I should see something here for 8080?

Nginx config is below:

    root@ubuntu:~# cat /etc/nginx/sites-available/mymeteorapp
    ================
    server_tokens off; # for security-by-obscurity: stop displaying nginx version

    # this section is needed to proxy web-socket connections
    map $http_upgrade $connection_upgrade {
    default upgrade;
    '' close;
    }

    # HTTP
    server {
    listen 80 default_server; # if this is not a default server, remove "default_server"
    listen [::]:80 default_server ipv6only=on;
    #listen 80;

    root /usr/share/nginx/html; # root is irrelevant
    index index.html index.htm; # this is also irrelevant

    server_name 36.102.142.66; # the domain on which we want to host the application. Since we set "default_server" previously, nginx will answer all hosts anyway.

    # redirect non-SSL to SSL
    location / {
    rewrite ^ https://$server_name$request_uri? permanent;
    }
    }

    # HTTPS server
    server {
    listen 443 ssl spdy; # we enable SPDY here
    server_name 36.102.142.66; # this domain must match Common Name (CN) in the SSL certificate

    root html; # irrelevant
    index index.html; # irrelevant

    ssl_certificate /etc/nginx/ssl/mymeteorapp.pem; # full path to SSL certificate and CA certificate concatenated together
    ssl_certificate_key /etc/nginx/ssl/mymeteorapp.key; # full path to SSL key

    # performance enhancement for SSL
    ssl_stapling on;
    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 5m;

    # safety enhancement to SSL: make sure we actually use a safe cipher
    ssl_prefer_server_ciphers on;
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:ECDHE-RSA-RC4-SHA:ECDHE-ECDSA-RC4-SHA:RC4-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!3DES:!MD5:!PSK';

    # config to enable HSTS(HTTP Strict Transport Security) https://developer.mozilla.org/en-US/docs/Security/HTTP_Strict_Transport_Security
    # to avoid ssl stripping https://en.wikipedia.org/wiki/SSL_stripping#SSL_stripping
    add_header Strict-Transport-Security "max-age=31536000;";

    # If your application is not compatible with IE <= 10, this will redirect visitors to a page advising a browser update
    # This works because IE 11 does not present itself as MSIE anymore
    if ($http_user_agent ~ "MSIE" ) {
    return 303 https://browser-update.org/update.html;
    }

    # pass all requests to Meteor
    location / {
    proxy_pass http://127.0.0.1:8080 ;
    #proxy_pass http://0.0.0.0:8080;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade; # allow websockets
    proxy_set_header Connection $connection_upgrade;
    proxy_set_header X-Forwarded-For $remote_addr; # preserve client IP

    # this setting allows the browser to cache the application in a way compatible with Meteor
    # on every applicaiton update the name of CSS and JS file is different, so they can be cache infinitely (here: 30 days)
    # the root path (/) MUST NOT be cached
    if ($uri != '/') {
    expires 30d;
    }
    }
    }
    ================

Below is the script for systemd service:

root@ubuntu:~# cat /lib/systemd/system/mymeteorapp.service

    [Unit]
    Description=Meteor.js (NodeJS) mymeteorapp application
    # start the service after mongodb starts
    Requires=mongodb.service
    After=mongodb.service

    [Service]
    Type=forking
    # Automatically restart process if crashed
    Restart=on-failure
    RestartSec=10 5
    ##Restart=always
    StandardOutput=syslog
    StandardError=syslog
    SyslogIdentifier=mymeteorapp
    # drop root proviliges and switch to mymetorapp user
    User=mymeteorapp
    Group=mymeteorapp
    Environment=PATH=/opt/local/bin:/opt/local/sbin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
    Environment=NODE_PATH=/usr/lib/nodejs:/usr/lib/node_modules:/usr/share/javascript
    # set to home directory of the user Meteor will be running as
    Environment=PWD=/home/mymeteorapp
    Environment=HOME=/home/mymeteorapp
    # leave as 127.0.0.1 for security
    Environment=BIND_IP=127.0.0.1
    # the port nginx is proxying requests to
    Environment=PORT=8080
    # this allows Meteor to figure out correct IP address of visitors
    Environment=HTTP_FORWARDED_COUNT=1
    # MongoDB connection string using mymeteorapp as database name
    Environment=MONGO_URL=mongodb://localhost:27017/mymeteorapp
    # The domain name as configured previously as server_name in nginx
    Environment=NODE_ENV=production
    Environment=ROOT_URL=https://36.102.142.66
    # optional JSON config - the contents of file specified by passing "--settings" parameter to meteor command in development mode
    #Environment=METEOR_SETTINGS='{ "somesetting": "someval", "public": { "othersetting": "anothervalue" } }'
    # this is optional: http://docs.meteor.com/#email
    # commented out will default to no email being sent
    # you must register with MailGun to have a username and password there
    # export MAIL_URL=smtp://postmaster@mymetorapp.net:password123@smtp.mailgun.org
    # alternatively install "apt-get install default-mta" and uncomment:
    # export MAIL_URL=smtp://localhostEnvironment=statedir=/var/cache/foo
    ExecStart=/usr/bin/node /home/mymeteorapp/bundle/main.js

    [Install]
    WantedBy=multi-user.target

Some refs I have used:
how-to-deploy-a-meteor-js-application-on-ubuntu-14-04-with-nginx

run-your-meteor-app-on-production.html - purportedly an update for 16.04 on the 14.04 ref above though it still has the Upstart config instead of systemd.

run-meteor-app-as-a-service-on-ubuntu

how-to-deploy-node-js-applications-using-systemd-and-nginx

SystemdForUpstartUsers

initial-server-setup-with-ubuntu-16-04

how-to-install-node-js-on-ubuntu-16-04

1 comment
  • Worth adding that service shows as inactive

    root@ubuntu:~# systemctl status mymetorapp
    ● mymetorapp.service
       Loaded: loaded (/lib/systemd/system/mymetorapp.service; enabled; vendor preset: enabled)
       Active: inactive (dead) since Mon 2016-11-07 00:45:46 UTC; 15h ago
     Main PID: 17018 (code=exited, status=0/SUCCESS)
    
    Nov 07 00:45:45 ubuntu-512mb-fra1-01 systemd[1]: Stopped mymetorapp.service.
    Nov 07 00:45:45 ubuntu-512mb-fra1-01 systemd[1]: Starting mymetorapp.service...
    Nov 07 00:45:46 ubuntu-512mb-fra1-01 systemd[1]: Started mymetorapp.service.
    root@ubuntu:~#
    
2 Answers

Hi,
You can get more info on why you process is dead by doing so :
in a first terminal :

journalctl -f -u mymeteorapp

and then in another window

systemctl start mymeteorapp

Perhaps giving us the output of the first window will help...

  • Hi @victorp Thanks for the reply. Excuse delay but my laptop got fried in meantime. Prior to this event I had rebuilt my app and updated node to version 4.4.7 using https://www.npmjs.com/package/n.
    When I start this redeployed app I get a different error

    journalctl -f -u mymeteorapp
    
    Nov 09 23:03:37 ubuntu systemd[1]: Starting mymeteorapp.service...
    Nov 09 23:03:38 ubuntu mymeteorapp[32679]: /home/mymeteorapp/bundle/programs/server/node_modules/fibers/future.js:280
    Nov 09 23:03:38 ubuntu mymeteorapp[32679]:                                                 throw(ex);
    Nov 09 23:03:38 ubuntu mymeteorapp[32679]:                                                 ^
    Nov 09 23:03:38 ubuntu mymeteorapp[32679]: Error: $MONGO_OPLOG_URL must be set to the 'local' database of a Mongo replica set
    Nov 09 23:03:38 ubuntu mymeteorapp[32679]:     at Error (native)
    Nov 09 23:03:38 ubuntu mymeteorapp[32679]:     at OplogHandle._startTailing (packages/mongo/oplog_tailing.js:218:13)
    Nov 09 23:03:38 ubuntu mymeteorapp[32679]:     at new OplogHandle (packages/mongo/oplog_tailing.js:76:8)
    Nov 09 23:03:38 ubuntu mymeteorapp[32679]:     at new MongoConnection (packages/mongo/mongo_driver.js:222:25)
    Nov 09 23:03:38 ubuntu mymeteorapp[32679]:     at new MongoInternals.RemoteCollectionDriver (packages/mongo/remote_collection_driver.js:4:16)
    Nov 09 23:03:38 ubuntu mymeteorapp[32679]:     at Object.<anonymous> (packages/mongo/remote_collection_driver.js:38:10)
    Nov 09 23:03:38 ubuntu mymeteorapp[32679]:     at Object.defaultRemoteCollectionDriver (packages/underscore.js:784:19)
    Nov 09 23:03:38 ubuntu mymeteorapp[32679]:     at new Mongo.Collection (packages/mongo/collection.js:103:40)
    Nov 09 23:03:38 ubuntu mymeteorapp[32679]:     at meteorInstall.lib.collections.js (lib/collections.js:1:14)
    Nov 09 23:03:38 ubuntu mymeteorapp[32679]:     at fileEvaluate (packages/modules-runtime.js:181:9)
    Nov 09 23:03:38 ubuntu systemd[1]: mymeteorapp.service: Main process exited, code=exited, status=1/FAILURE
    Nov 09 23:03:38 ubuntu systemd[1]: Failed to start mymeteorapp.service.
    Nov 09 23:03:38 ubuntu systemd[1]: mymeteorapp.service: Unit entered failed state.
    Nov 09 23:03:38 ubuntu systemd[1]: mymeteorapp.service: Failed with result 'exit-code'.
    
    
    root@ubuntu-512mb-fra1-01:~# mongod --version
    db version v2.6.10
    2016-11-09T23:10:53.391+0000 git version: nogitversion
    2016-11-09T23:10:53.391+0000 OpenSSL version: OpenSSL 1.0.2g  1 Mar 2016
    

    From systemd start script -> /lib/systemd/system/mymeteorapp.service

    Environment=MONGO_OPLOG_URL=mongodb://127.0.0.1:27017/local
    
    

    If I comment out the MONGOOPLOGURL line in the systemd script, my app starts and loads data to db but I still get a 502 in browser.

    
    Nov 09 23:46:28 ubuntu systemd[1]: Starting mymeteorapp.service...
    Nov 09 23:46:29 ubuntu mymeteorapp[520]: colections.js - category count:  0
    Nov 09 23:46:30 ubuntu mymeteorapp[520]: startup.js - inserted categories:  7
    
    • Getting 502 error still

      root@ubuntu:/lib/systemd/system# tail -f /var/log/nginx/error.log
          2016/11/06 22:34:29 [error] 13486#13486: *248 connect() failed (111: Connection refused) while connecting to upstream, client: 84.23.134.181, server: 36.102.142.66, request: "GET / HTTP/1.1", upstream: "http://127.0.0.1:8080/", host: "36.102.142.66"
      

      Think I'm missing the nginx and meteor app connection in that its unclear to me.

      Based on

      root@ubuntu:# cat /home/mymeteorapp/bundle/README
      This is a Meteor application bundle. It has only one external dependency:
      Node.js 4.4.7 or newer. To run the application:
      
        $ (cd programs/server && npm install)
        $ export MONGO_URL='mongodb://user:password@host:port/databasename'
        $ export ROOT_URL='http://example.com'
        $ export MAIL_URL='smtp://user:password@mailhost:port/'
        $ node main.js
      
      Use the PORT environment variable to set the port where the
      application will listen. The default is 80, but that will require
      root on most systems.
      
      Find out more about Meteor at meteor.com.
      

      I set the port to 3000 then back to 8080 but unclear on what to do next ???

      export PORT=8080
      
      • netstat shows node running on port 3000 so I reset PORT to 3000 and I can see app on http://<ip>:3000 but on https://<ip> I still get a 502.

        root@ubuntu-:~# sudo netstat -plutn
        Active Internet connections (only servers)
        Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
        tcp        0      0 0.0.0.0:3000            0.0.0.0:*               LISTEN      11307/node
        tcp        0      0 0.0.0.0:443             0.0.0.0:*               LISTEN      11296/nginx: worker
        tcp        0      0 127.0.0.1:27017         0.0.0.0:*               LISTEN      916/mongod
        tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      11296/nginx: worker
        tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      1356/sshd
        tcp6       0      0 :::80                   :::*                    LISTEN      11296/nginx: worker
        tcp6       0      0 :::22                   :::*                    LISTEN      1356/sshd
        
        root@ubuntu-512mb-fra1-01:~# export PORT=3000
        

        This article helped
        502 Bad Gateway after setting up Meteor on Ubuntu 14.04

        • Not getting issue any more. Can get to https://<ip> now. Switched port to 3000 in nginx config (was 8080).

My Meteor app now runs ok in my DO Droplet running on Ubuntu 16.04 with ningx.
Thought I would share the detailed config in case it helps anyone.

root@ubuntu:~# journalctl -f -u mymeteorapp
-- Logs begin at Sat 2016-10-29 23:05:30 UTC. --
Nov 11 01:16:30 ubuntu systemd[1]: Started mymeteorapp.service.
Nov 11 01:16:32 ubuntu mymeteorapp[11060]: colections.js - category count:  7
Nov 11 01:20:06 ubuntu systemd[1]: Stopping mymeteorapp.service...
Nov 11 01:20:06 ubuntu systemd[1]: Stopped mymeteorapp.service.
Nov 11 01:20:18 ubuntu systemd[1]: Started mymeteorapp.service.
Nov 11 01:20:19 ubuntu mymeteorapp[11196]: colections.js - category count:  7
Nov 11 01:30:21 ubuntu systemd[1]: Stopping mymeteorapp.service...
Nov 11 01:30:21 ubuntu systemd[1]: Stopped mymeteorapp.service.
Nov 11 01:30:34 ubuntu systemd[1]: Started mymeteorapp.service.
Nov 11 01:30:35 ubuntu mymeteorapp[11307]: colections.js - category count:  7
root@ubuntu:~# systemctl status mymeteorapp
● mymeteorapp.service
   Loaded: loaded (/lib/systemd/system/mymeteorapp.service; enabled; vendor preset: enabled)
   Active: active (running) since Fri 2016-11-11 01:30:34 UTC; 4 days ago
 Main PID: 11307 (node)
    Tasks: 9
   Memory: 58.8M
      CPU: 2min 51.174s
   CGroup: /system.slice/mymeteorapp.service
           └─11307 /usr/local/bin/node /home/mymeteorapp/bundle/main.js

Nov 11 01:30:34 ubuntu systemd[1]: Started mymeteorapp.service.
Nov 11 01:30:35 ubuntu mymeteorapp[11307]: colections.js - category count:  7
root@ubuntu:~#

root@ubuntu:~# netstat -plnt
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
tcp        0      0 0.0.0.0:3000            0.0.0.0:*               LISTEN      11307/node
tcp        0      0 0.0.0.0:443             0.0.0.0:*               LISTEN      14308/nginx: worker
tcp        0      0 127.0.0.1:27017         0.0.0.0:*               LISTEN      916/mongod
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      14308/nginx: worker
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      1356/sshd
tcp6       0      0 :::80                   :::*                    LISTEN      14308/nginx: worker
tcp6       0      0 :::22                   :::*                    LISTEN      1356/sshd
root@ubuntu:~#

Note that mymeteorapp now runs on port 3000. Initially had it configured to 8080. Presumably I could switch back to 8080 without too much hassle but know of no reason not to run it on 3000.

Nginx config is below:


root@ubuntu:~# cat /etc/nginx/sites-available/mymeteorapp
server_tokens off; # for security-by-obscurity: stop displaying nginx version

# this section is needed to proxy web-socket connections
map $http_upgrade $connection_upgrade {
    default upgrade;
    ''      close;
}

# HTTP
server {
#    listen 80 default_server; # if this is not a default server, remove "default_server"
     listen 0.0.0.0:80;
     listen [::]:80 default_server ipv6only=on;
#listen 80;

    root /usr/share/nginx/html; # root is irrelevant
    index index.html index.htm; # this is also irrelevant

    #server_name todos.net; # the domain on which we want to host the application. Since we set "default_server" previously, nginx will answer all hosts anyway.
    server_name 36.102.142.66; # the domain on which we want to host the application. Since we set "default_server" previously, nginx will answer all hosts anyway.

    # redirect non-SSL to SSL
    location / {
        rewrite     ^ https://$server_name$request_uri? permanent;
    }
}

# HTTPS server
server {
    listen 443 ssl spdy; # we enable SPDY here
    #server_name todos.net; # this domain must match Common Name (CN) in the SSL certificate
    server_name 36.102.142.66; # this domain must match Common Name (CN) in the SSL certificate

    root html; # irrelevant
    index index.html; # irrelevant

    ssl_certificate /etc/nginx/ssl/mymeteorapp.pem; # full path to SSL certificate and CA certificate concatenated together
    ssl_certificate_key /etc/nginx/ssl/mymeteorapp.key; # full path to SSL key

    # performance enhancement for SSL
    ssl_stapling on;
    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 5m;

    # safety enhancement to SSL: make sure we actually use a safe cipher
    ssl_prefer_server_ciphers on;
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:ECDHE-RSA-RC4-SHA:ECDHE-ECDSA-RC4-SHA:RC4-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!3DES:!MD5:!PSK';

    # config to enable HSTS(HTTP Strict Transport Security) https://developer.mozilla.org/en-US/docs/Security/HTTP_Strict_Transport_Security
    # to avoid ssl stripping https://en.wikipedia.org/wiki/SSL_stripping#SSL_stripping
    add_header Strict-Transport-Security "max-age=31536000;";

    # If your application is not compatible with IE <= 10, this will redirect visitors to a page advising a browser update
    # This works because IE 11 does not present itself as MSIE anymore
    if ($http_user_agent ~ "MSIE" ) {
        return 303 https://browser-update.org/update.html;
    }

    # pass all requests to Meteor
    location / {
        proxy_pass http://127.0.0.1:3000;
        #proxy_pass http://0.0.0.0:8080;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade; # allow websockets
        proxy_set_header Connection $connection_upgrade;
        proxy_set_header X-Forwarded-For $remote_addr; # preserve client IP

        # this setting allows the browser to cache the application in a way compatible with Meteor
        # on every applicaiton update the name of CSS and JS file is different, so they can be cache infinitely (here: 30 days)
        # the root path (/) MUST NOT be cached
        if ($uri != '/') {
            expires 30d;
        }
    }
}
root@ubuntu:~#

Below is the script for systemd service:

root@ubuntu:~# cat /lib/systemd/system/mymeteorapp.service
[Service]
Type=simple
ExecStart=/usr/local/bin/node /home/mymeteorapp/bundle/main.js
Restart=no
#RestartSec=10 5
#Restart=always
StandardOutput=syslog
StandardError=syslog
SyslogIdentifier=mymeteorapp
User=root
Group=root
Environment=NODE_ENV=production
Environment=PWD=/home/mymeteorapp/
Environment=PORT=3000
Environment=HTTP_FORWARDED_COUNT=1
Environment=MONGO_URL=mongodb://localhost:27017/mymeteorapp
#Environment=MONGO_OPLOG_URL=mongodb://127.0.0.1:27017/local
Environment=ROOT_URL=https://36.102.142.66
Environment='METEOR_SETTINGS={"someSetting": "someValue"}'

[Install]
WantedBy=default.target
root@ubuntu:~#
Have another answer? Share your knowledge.