tconroy
By:
tconroy

Installing LEMP and MEAN stacks on single droplet?

March 8, 2015 3.1k views
DigitalOcean Configuration Management MEAN LEMP Node.js PHP Nginx Ubuntu

Howdy all,

I'm switching from a shared host to Digital Ocean, but want to try the waters with the 5$ plan for a bit first.

I will just be porting over my personal portfolio/blog (PHP, AnchorCMS) so I will need the LEMP stack.

I also hav a couple of small side projects I am working on using Node.JS / MEAN stack, which I would love to host with the same 5$ droplet.

Is it possible/simple to configure both stacks to operate on the same droplet without breaking anything? Are there any guides or tutorials for this?

Thanks for any help!

1 Answer

It should be fine to have both set ups on a single droplet. We have tutorials going through both setups:

You can either start with a fresh Ubuntu base install and follow those tutorials or start with one of the "applications" and install the other along side it.

The one thing to keep in mind is that only one process can bind to port 80 at a time. So in order to run both sites, you'll need to set up your MEAN app to run behind an Nginx reverse proxy.

You Nginx configuration might look something like this:

server {
    listen 80 default_server;
    listen [::]:80 default_server ipv6only=on;

    root /var/www/html;
    index index.php index.html index.htm;

    server_name example.com;

    location / {
        # First attempt to serve request as file, then
        # as directory, then fall back to displaying a 404.
        try_files $uri $uri/ =404;
    }

    error_page 404 /404.html;
    error_page 500 502 503 504 /50x.html;
    location = /50x.html {
        root /usr/share/nginx/html;
    }

    location ~ \.php$ {
        try_files $uri =404;
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass unix:/var/run/php5-fpm.sock;
        fastcgi_index index.php;
        include fastcgi_params;
    }
}

upstream mean_app{
  server 127.0.0.1:3000;
}

server{
    listen 80;
    listen [::]:80 ipv6only=on;

    server_name meanapp.example.com;

    location / {
      proxy_set_header X-Real-IP $remote_addr;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header Host $http_host;
      proxy_set_header X-NginX-Proxy true;

      proxy_pass http://mean_app/;
      proxy_redirect off;
    }
}

A couple things to note here. This assumes the MEAN app is running on port 3000. Update that as needed. Also, the server_name directive is important here. It's how Nginx know how to route requests to the correct app.

Let us know how it goes!

by Justin Ellingwood
A LEMP stack (Linux, Nginx, MySQL, and PHP) is a powerful set of software that can be configured to serve dynamic sites and web apps from your server. In this guide, we will discuss how to install a LEMP stack on an Ubuntu 14.04 server.
  • Hey there,
    thanks for the great info!! I've gone ahead and built out my LEMP and MEAN stacks by hand (as opposed to one of the pre-configured droplet options). I just had a question regarding the server_name directive -- in the server{} config for LEMP, I've just plugged my server IP directly into server_name. For the MEAN configuration, can I just have server_name meanapp.{server IP address}, or does it have to be a domain name?

    Currently, when I try and restart nginx after including your additions, I'm getting the following error:

    a duplicate default server for 0.0.0.0:80 in /etc/nginx/sites-enabled/default:59
    

    and line 59 on sites-enabled/default is:

    listen 80 default_server;
    

    located inside the mean server block.

    Any help appreciated!

    EDIT: here is my complete /etc/nginx/sites-enabled/default.conf file (delicates removed :) ):

    server {
        listen 80 default_server;
        listen [::]:80 default_server ipv6only=on;
    
        root /usr/share/nginx/html;
        index index.php index.html index.htm;
    
        # Make site accessible from http://localhost/
        server_name {DIGITAL OCEAN IP ADDRESS HERE};
    
        location / {
            # First attempt to serve request as file, then
            # as directory, then fall back to displaying a 404.
            try_files $uri $uri/ =404;
            # Uncomment to enable naxsi on this location
            # include /etc/nginx/naxsi.rules
        }
    
        # Only for nginx-naxsi used with nginx-naxsi-ui : process denied requests
        #location /RequestDenied {
        #   proxy_pass http://127.0.0.1:8080;    
        #}
    
        error_page 404 /404.html;
    
        # redirect server error pages to the static page /50x.html
        #
        error_page 500 502 503 504 /50x.html;
        location = /50x.html {
            root /usr/share/nginx/html;
        }
    
        # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
        #
        location ~ \.php$ {
            try_files $uri =404;
            fastcgi_split_path_info ^(.+\.php)(/.+)$;
            #fastcgi_pass 127.0.0.1:9000;
            fastcgi_pass unix:/var/run/php5-fpm.sock;
            fastcgi_index index.php;
            fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
            include fastcgi_params;
        }
    
        # deny access to .htaccess files, if Apache's document root
        # concurs with nginx's one
        #
        #location ~ /\.ht {
        #   deny all;
        #}
    }
    
    
    upstream mean_app {
        server 127.0.0.1:3000;
    }
    
    server {
        listen 80 default_server;
        listen [::]:80 default_server ipv6only=on;
        server_name meanapp.{DIGITAL OCEAN IP ADDRESS HERE};
        location / {
          proxy_set_header X-Real-IP $remote_addr;
          proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
          proxy_set_header Host $http_host;
          proxy_set_header X-NginX-Proxy true;
          proxy_pass http://mean_app/;
          proxy_redirect off;
        }
    }
    
    
    # another virtual host using mix of IP-, name-, and port-based configuration
    #
    #server {
    #   listen 8000;
    #   listen somename:8080;
    #   server_name somename alias another.alias;
    #   root html;
    #   index index.html index.htm;
    #
    #   location / {
    #       try_files $uri $uri/ =404;
    #   }
    #}
    
    
    # HTTPS server
    #
    #server {
    #   listen 443;
    #   server_name localhost;
    #
    #   root html;
    #   index index.html index.htm;
    #
    #   ssl on;
    #   ssl_certificate cert.pem;
    #   ssl_certificate_key cert.key;
    #
    #   ssl_session_timeout 5m;
    #
    #   ssl_protocols SSLv3 TLSv1 TLSv1.1 TLSv1.2;
    #   ssl_ciphers "HIGH:!aNULL:!MD5 or HIGH:!aNULL:!MD5:!3DES";
    #   ssl_prefer_server_ciphers on;
    #
    #   location / {
    #       try_files $uri $uri/ =404;
    #   }
    #}
    
    
  • @tconroy You won't be able to use subdomains without setting setting up DNS.

    And regarding the "duplicate default server" error. default_server is used to pick the what the fall back is if none of the conditions match. I've updated the above to remove it from one block as it shouldn't be repeated in both.

Have another answer? Share your knowledge.