Nikola Brežnjak blog - Tackling software development with a dose of humor
  • Home
  • Daily Thoughts
  • Ionic
  • Stack Overflow
  • Books
  • About me
Home
Daily Thoughts
Ionic
Stack Overflow
Books
About me
  • Home
  • Daily Thoughts
  • Ionic
  • Stack Overflow
  • Books
  • About me
Nikola Brežnjak blog - Tackling software development with a dose of humor
NodeJS, Servers

How to host multiple Node.js applications with multiple different domains on one VPS with Nginx

First things first, if you bought your domain elsewhere then you first need to point that domain to your server. You basically have two options here

  • installing, setting up and running a DNS on your VPS and pointing the DNS (from the control panel where you bought a domain) records to your VPS
  • setting your DNS Zone file A record (in the control panel where you bought a domain) to the VPS IP
  • this posts explain what are the pros and cons

Now, if you do that for multiple domains they will all point to your server’s IP and show the same thing, essentially the thing which is running on port 80 (and that, in our main Nginx installation, will be a default Nginx welcome screen). If you have multiple Node.js applications, which are running on different ports, and you want to pinpoint the domains to that particular applications, then this is where the Nginx comes in so that it takes the requests for each domain and routes it to an appropriate port where the appropriate Node.js application is running. Basically, what Nginx does in this case is called reverse proxying.

Useful links:

  • this StackOverflow question
  • http://blog.grabeh.net/Digital-Ocean-VPS-Nginx-Express-apps
  • https://www.digitalocean.com/community/tutorials/how-to-host-multiple-node-js-applications-on-a-single-vps-with-nginx-forever-and-crontab
  • http://ludovf.net/blog/configure-nginx-to-proxy-virtual-hosts-to-apache/
  • http://kbeezie.com/apache-with-nginx/
  • https://www.digitalocean.com/community/tutorials/how-to-set-up-nginx-virtual-hosts-server-blocks-on-centos-6

Use forever:

  • npm install forever -g
  • forever start –spinSleepTime 10000 yourApp.js
  • if the app crashes, forever starts it up again

Lets start:

  • sudo vim /etc/nginx/conf.d/example.com.conf:
    server {
        listen 80;
    
        server_name your-domain.com;
    
        location / {
            proxy_pass http://localhost:{YOUR_PORT};
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection 'upgrade';
            proxy_set_header Host $host;
            proxy_cache_bypass $http_upgrade;
        }
    }
  • to reference multiple domains for one Node.js app (like www.example.com and example.com) you need to add the following code to the file /etc/nginx/nginx.conf in the http section: server_names_hash_bucket_size 64;
  • but, as it always is, the upper statement didn’t work for me, so I ended up using this solution from StackOverflow:
    server {
        #listen 80 is default
        server_name www.example.com;
        return 301 $scheme://example.com$request_uri;
    }
  • sudo service nginx restart

Forever keeps your application running when it crashes but if VPS is rebooted it won’t start anymore. Simple cronjob solves this issue. Create starter.sh in your application’s home folder and copy the following code:

#!/bin/sh

if [ $(ps -e -o uid,cmd | grep $UID | grep node | grep -v grep | wc -l | tr -s "\n") -eq 0 ]
then
export PATH=/usr/local/bin:$PATH
forever start --sourceDir /path/to/your/node/app main.js >> /path/to/log.txt 2>&1
fi

where main.js is your application’s main script. Add to crontab the following line: @reboot /path/to/starter.sh.

Servers

Installing MEN NPP stack (MongoDB, Express, Node.js, Nginx, PostgreSQL, PHP) on CentOS 7 from scratch

I’ve been playing with my VPS that I bought from WeLoveServers.net and I previously wrote about how to set up your VPS from scratch. Here I’ll show just brief commands for installing a MEN NPP stack (MongoDB, Express, Node.js, Nginx, PostgreSQL, PHP) on my CentOS machine.

Nginx

  • high performance web server that is much more flexible and lightweight than Apache
  • SELinux – if you run into issues change the SELinux mode to permissive or disabled
  • sudo rpm -Uvh http://nginx.org/packages/centos/7/noarch/RPMS/nginx-release-centos-7-0.el7.ngx.noarch.rpm
  • sudo yum install nginx
  • sudo systemctl start nginx.service or sudo service nginx start
  • sudo systemctl enable nginx.service (no alternative with sudo service)
  • default server root directory /usr/share/nginx/html defined /etc/nginx/conf.d/default.conf
  • server blocks (known as Virtual Hosts in Apache) are created in /etc/nginx/conf.d. Files that end with .conf in that directory will be loaded when Nginx is started
  • main Nginx configuration file is located at /etc/nginx/nginx.conf
  • sudo vi /etc/nginx/conf.d/default.conf looks like:
    server {
        listen       80;
        server_name  localhost;
    
        location / {
            root   /usr/share/nginx/html;
            index  index.html index.htm;
        }
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   /usr/share/nginx/html;
        }
    }

    change to:

    server {
        listen       80;
        server_name  server_domain_name_or_IP;
    
        root   /usr/share/nginx/html;
        index index.php index.html index.htm;
    
        location / {
            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_pass unix:/var/run/php-fpm/php-fpm.sock;
            fastcgi_index index.php;
            fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
            include fastcgi_params;
        }
  • sudo systemctl restart nginx
  • sudo nginx -t
    nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
    nginx: configuration file /etc/nginx/nginx.conf test is successful

Node.js

  • just a side note for Mac: brew install node
  • sudo yum install epel-release
  • sudo yum install node
  • sudo yum install npm

Express

  • npm install express

PHP

  • sudo yum install php php-mysql php-fpm
  • sudo vi /etc/php.ini – in order to secure it do cgi.fix_pathinfo=0
  • sudo vi /etc/php-fpm.d/www.conf set line to listen = /var/run/php-fpm/php-fpm.sock
  • sudo systemctl start php-fpm
  • sudo systemctl enable php-fpm.service to start from boot

 

PostgreSQL

  • exclude the CentOS version of postgres in order to get the most recent version from the project’s website
  • sudo vim /etc/yum.repos.d/CentOS-Base.repo
    At the bottom of the [base] and [updates] sections, add a line that excludes the postgres packages: exclude=postgresql*
  • Find the link for your version of the OS here
  • curl -O http://yum.postgresql.org/9.4/redhat/rhel-7-x86_64/pgdg-centos94-9.4-1.noarch.rpm
  • rpm -ivh pgdg*
  • yum list postgres*
  • install the -server package: sudo postgresql94-server.x86_64
  • sudo /usr/pgsql-9.4/bin/postgresql94-setup initdb
  • chkconfig postgresql-9.3 on
  • service postgresql-9.3 start
  • postgres creates a user and a database called postgres
  • sudo su – postgres
  • psql
  • \?: Get a full list of psql commands, including those not listed here
  • \h: Get help on SQL commands. You can follow this with a specific command to get help with the syntax
  • \q: Quit the psql program and exit to the Linux prompt
  • \d: List available tables, views, and sequences in current database
  • \du: List available roles
  • \dp: List access privileges
  • \dt: List tables
  • \l: List databases
  • \c: Connect to a different database. Follow this by the database name
  • \password: Change the password for the username that follows
  • \conninfo: Get information about the current database and connection
    CREATE TABLE new_table_name (
        table_column_title TYPE_OF_DATA column_constraints,
        next_column_title TYPE_OF_DATA column_constraints,
        table_constraint
        table_constraint
    ) INHERITS existing_table_to_inherit_from;

     

MongoDB

  • Instructions from here
  • sudo vim /etc/yum.repos.d/mongodb.repo:
    [mongodb]
    name=MongoDB Repository
    baseurl=http://downloads-distro.mongodb.org/repo/redhat/os/x86_64/
    gpgcheck=0
    enabled=1
  • sudo yum install -y mongodb-org
  • to prevent unintended upgrades, add to /etc/yum.conf file:
    exclude=mongodb-org,mongodb-org-server,mongodb-org-shell,mongodb-org-mongos,mongodb-org-tools
  • sudo service mongod start
  • sudo chkconfig mongod on

 

Servers

How to set up your own VPS from scratch

I bought a VPS on a sale on WeLoveServers.net for a crazy 48$ a year with 2GB of RAM. If you know a cheaper one, please share it in the comments. Anyways, since this is a barebones setup, I had to set it up myself and this is how I did it.

I followed a great tutorial from DigitalOcean: https://www.digitalocean.com/community/tutorials/initial-server-setup-with-centos-7

Login

  • login as root
  • change root’s password with passwd command
  • add new user – useradd myuser
  • change user’s password – passwd myuser
  • on CentOS 7, users who belong to the “wheel” group are allowed to use the sudo command: gpasswd -a myuser wheel or use a normal route of editing with /usr/sbin/visudo and add a line leuser ALL(ALL) ALL
  • ssh-keygen – you get id_rsa and id_rsa.pub files which you upload (only public one OFC!) to .ssh/ folder in your home directory (you should do chmod 700 .ssh after mkdir-ing it)
  • create file authorized_keys and paste the contents of the id_rsa.pub file in it and restrict the access to it by doing chmod 600 .ssh/authorized_keys

SSH settings

  • sudo vi /etc/ssh/sshd_config
    • Port 25000
      Protocol 2
      PermitRootLogin no
      UseDNS no
      AllowUsers myuser
  • systemctl reload sshd.service or service sshd restart

Firewall

  • my version of CentOS ships with iptables, but in the article he works with a firewall called firewalld (yum install firewalld to install it)
  • lock down everything that you do not have a good reason to keep open
  • sudo systemctl start firewalld
  • uses the concept of “zones” to label the trustworthiness of the other hosts
  • sudo firewall-cmd –permanent –add-service=ssh
  • if you use a different port for SSH then
    • sudo firewall-cmd –permanent –remove-service=ssh
      sudo firewall-cmd –permanent –add-port=4444/tcp
  • sudo firewall-cmd –permanent –add-service=http
  • sudo firewall-cmd –permanent –add-service=https
  • sudo firewall-cmd –permanent –add-service=smtp
  • all the services that you can enable: sudo firewall-cmd –get-services
  • list exceptions: sudo firewall-cmd –permanent –list-all
  • sudo firewall-cmd –reload
  • start firewall at boot: sudo systemctl enable firewalld

Timezone

  • sudo timedatectl list-timezones
  • sudo timedatectl set-timezone Europe/Zagreb
  • confirm the change has been done: sudo timedatectl

NTP

  • sudo yum install ntp
  • sudo systemctl start ntpd
  • sudo systemctl enable ntpd

swap

  • allows the system to move the less frequently accessed information of a running program from RAM to a location on disk, especially useful if you plan to host any databases on your system
  • amount equal to or double the amount of RAM on your system is a good starting point
  • sudo fallocate -l 4G /swapfile
  • sudo chmod 600 /swapfile
  • sudo mkswap /swapfile
  • sudo swapon /swapfile
  • in case after the last command you get an error like this: “swapon: /swapfile: swapon failed: Operation not permitted“, that basically means that you’re most probably on openvz and that you can’t create a swap file (more on serverfault.com)
  • if you didn’t get an error then do: sudo sh -c ‘echo “/swapfile none swap sw 0 0” >> /etc/fstab’ to start it at boot

fail2ban

  • it scans through log files and reacts to offending actions such as repeated failed login attempts
  • EPEL (Extra Packages for Enterprise Linux)
  • wget http://dl.fedoraproject.org/pub/epel/7/x86_64/e/epel-release-7-2.noarch.rpm
  • sudo rpm -ivh epel-release-7-2.noarch.rpm
  • sudo yum install fail2ban
  • default configuration file at /etc/fail2ban/jail.conf but copy it
    cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
  • vi /etc/fail2ban/jail.local
  • sudo chkconfig fail2ban on
Books

Strong fathers strong daughters – Meg Meeker

My favourite quotes from the book Strong fathers strong daughters by Meg Meeker:
Believe it or not, the most important factor for girls growing up into competent, well-adjusted woman is a strong father would conservative values.
Don’t let your daughter have a TV or computer in her room. Safe TV for family time – when you or your wife can decide what to watch.
Your daughter doesn’t want to see you as equal, she wants you to be her hero. Someone who is wiser and steadier and stronger than she is.
Authority is not a threat to your relationship with your daughter – it is what will get you closer with your daughter and what will make her respect you even more.
Lead by example and don’t back down from your principles!
Women in magazines aren’t the best role models. People who judge everyone on their looks probably have terrible self-esteem issues. It’s not important how thin someone is but what her character is.
Don’t comment frequently on how she looks. Don’t comment on your own needs the diet. Appearance is not a high-priority – what matters is her, and not what she wears. Give her attention naturally. If you talk about something often she will follow.
Be confident. Defend her and be supportive. And don’t back away from hugging her. Don’t allow fashion trends mold your daughter – seven-year-old learns from commercials that being sexy is good – you have to intervene.
Teach her to wait!
Teach self-respect early. At every age tell her her body is special and that she needs to keep it special.
Don’t let your daughter grow up to be a victim of life. Too much of our popular culture teaches us to love victims. So, we create people who are helpless, incapable and terribly needy. But you, as a father, can prevent that. You can teach your daughter to do, not just want. Action engages the will and gives energy and momentum. Action means that your daughter will know that she, not others, will determine her fate.
Constant pursuit of more leads to dissatisfaction. When we realize that we don’t need more, then we can be happy. Contempt comes from who we are and what we have today.
It is a great strength knowing that if you lost every material possesion that you would still have life worth living for by sharing it with your loved ones.
To be a good father is to be a good instructor about God.
My dad has a really strong faith. That’s why he got up every morning to pray and read the Bible. Sometimes he would talk about God, but mostly he would like to just live what he read in the Bible. I was happy because I knew he prayed for me.
There is a void in every man’s heart that only God can fill.
Don’t leave your teenage daughter shopping alone because it only makes it easier for the pop-culture to sell them shit.
Search for that something, but the more we search for it the more distant it becomes. Because what you’re searching for sits right there. It’s not your job, or more money, your hobbies or more sex – it’s your family, your children, your spouse and God.
NodeJS

How to get all of your own Facebook posts and parse them with JavaScript

So, first you need to download all the data that Facebook has stored for you (well, and what it’s willing to give you :)). You can do that by going to https://www.facebook.com/settings when you’re logged in, and you will see the following screen:FacebookDataDownload2

Here you can just click on the Download a copy of your Facebook data and after they process your request you will get the download link on your email.

The download package looks contains 3 folders (videos, photos, html) and a index.html file. In order to take a look at your posts you have to open up the html folder where you’ll find the file named wall.htm. This is a simple HTML file whose contents is put inside the <div class=”comment”> elements.

In order to parse this with JavaScript (you’ll need to have Node.js installed) you can use the following snippet:

function getMatches(string, regex, index) {
    index || (index = 1); // default to the first capturing group
    var matches = [];
    var match;
    while (match = regex.exec(string)) {
        matches.push(match[index]);
    }
    return matches;
}

fs = require('fs');
fs.readFile('wall.htm', 'utf8', function(err, data){
	if (err){
	    return console.log(err);
	}

	var regex = /comment">([\s\S]*?)<\/div>/g
	var matches = getMatches(data, regex, 1);

	var output = '';
	for(var i=0; i<matches.length; i++){
		output += matches[i] + '\n';
	}

	fs.writeFile('parsed.txt', output, 'utf8', function(){
		console.log('done!');
	});
});

What this does is that it reads the wall.html file and outputs just simple text of the posts in a parsed.txt file.

Few of the challenges here we’re the multiline regex matching which I solved with this link on StackOverflow, and another one was getting access to matched groups of a regex in JavaScript.

Quick tips, Windows

Grep GUI on a Windows machine with AstroGrep

I had to find some string inside one of the files, and I couldn’t remember in which file it was, classic 🙂

In linux, simple grep command would help, but on Windows there’s no such thing, or at least I thought… After some googling I came up with AstroGrep and I think it’s awesome, and it also comes with a GUI if you fancy that:

AstroGrep

You can download it freely from their site.

Stack Overflow

NodeJS code executes differently when run via browser and when run via curl in terminal

profile for Nikola at Stack Overflow, Q&A for professional and enthusiast programmers
I’m a big fan of Stack Overflow and I tend to contribute regularly (am currently in the top 0.X%). In this category (stackoverflow) of posts I will will be posting my top rated questions and answers. This, btw, is allowed as explained in the meta thread here.

My quesiton was:

I have the following simple NodeJS code:

var http = require("http");

http.createServer(function(request, response){
    response.writeHead(200);
    setTimeout(function(){
        response.write("This printed 3 secs later, ait?");
        response.end();},3000);

    response.write("This will be printed before.\n");}).listen(8080);

If I run the script with node scriptname.js and then access it via curl in terminal like this:

curl http://localhost:8080

I get an output as expected, first it prints This will be printed before., then after 3 seconds it prints This printed 3 secs later, ait?.

However, when I open http://localhost:8080 in my browser (newest versions of Chrome, Firefox) page loads for 3 seconds and it prints the text This will be printed before. This printed 3 secs later, ait? all at once. Why does this happen and how could I make the same behavior in the browser?

edit: So, as Ken stated in his answer

…this is simply due to the behavior of the browser rendering engine to render the contents. The rendering engine cashes the contents until response.end();

and advised to go and check out Socket.IO, I came up with this working example which uses expressand Socket.IO:

//timeoutTest.js
var express = require('express'),
    app = express(),
    server = require('http').createServer(app),
    io = require('socket.io').listen(server);

server.listen(8080);

app.use(express.static(__dirname +'/'));

app.get('/',function(req, res){
   res.sendfile(__dirname +'/timeoutTest.html');});

io.sockets.on('connection',function(client){
   client.emit('msg',"This prints right now on connection.");

   setTimeout(function(){
      client.emit('msg',"This prints out after 3 secs.");},3000);});
//timeoutTest.html
<!DOCTYPE html><html><head><script src="/socket.io/socket.io.js"></script><script src="jquery.js"></script><script>
    $(document).ready(function(){var server = io.connect('http://localhost');
        server.on('msg',function(data){
            $('body').append(data +"<br/>");});});</script></head><body></body></html>

 

The answer, by Ken OKABE, was:

I think this is simply due to the behavior of the browser rendering engine to render the contents. The rendering engine cashes the contents until response.end(); arrives, then renders whole.

Basically, HTML contents in the browser are never updated automatically by incremental server pushsuch as response.write. You must pull data from the server to the browser client by Ajax and DHTML/js technique. curl in terminal is completely different story in terms of the mere output of the node server.

If you seek more interactive behavior between node server and browser client, if you want server push feature, websocket is the way to go, and also investigate node stream stuff. Socket.IO is famous, and for node stream https://github.com/substack/stream-handbook should be interesting to you.

I personally do this on my own project: http://kenokabe.github.io/MarkdownLive/. I write stuff using Markdown and needed a streaming preview, so I created by myself. The preview screen is a Browser HTML page, and the HTML contents rendered and updated incrementally in streaming manner.

MEAN

MEAN T-shirt graphic, presentation and video

Since I’m all into MEAN stack lately, I made a custom graphic for a MEAN T-shirt. Also, I made the presentation and a talk for hack.hands().

I’m giving the image here freely without any restrictions, yada, yada, use it whatever way you like, just don’t sue me if someone will tell you you’re a mean person :P. You can send the image to your local T-shirt makers, or you can order it from my SpreadShirt store.

The T-shirt looks like this on me:

IMG_2617

Desktop background version can be downloaded here (Right click, Save Image As):MEAN_1_black

And a transparent PNG version ideal for a black T-shirt can be downloaded here (Right click, Save Image As):

MEAN_1

I got a t-shirt made at a reasonable price here in Croatia at t-shirtmania.hr.

The video of the talk in full on youtube below, and the two posts in a series of getting started on a MEAN stack are here:

  • https://hackhands.com/how-to-get-started-on-the-mean-stack/
  • https://hackhands.com/delving-node-js-express-web-framework/

Stack Overflow

How to pass GET parameters to jsFiddle

profile for Nikola at Stack Overflow, Q&A for professional and enthusiast programmers
I’m a big fan of Stack Overflow and I tend to contribute regularly (am currently in the top 0.X%). In this category (stackoverflow) of posts I will will be posting my top rated questions and answers. This, btw, is allowed as explained in the meta thread here.

My quesiton was:

How to pass GET parameters to jsFiddle? I tried http://jsfiddle.net/mKwcF/?id=123 but all I get ishttp://fiddle.jshell.net/mKwcF/show/

My example js is simple on a given link above:

alert(window.location.href);

The (updated) answer, by Jack Miller, was:

As of October 2014 it is a little more complicated than it used to be:

If your jsfiddle url is:

http://jsfiddle.net/u7G7n/41

Some code to make stackoverflow happy. Ignore this.

use instead (including some url parameters):

http://fiddle.jshell.net/u7G7n/41/show/light/?lat1=52&lng1=9&lat2=50&lng2=1

AND send the same url (including parameters) as referer. You can use Referer Control as Chrome plugin: https://chrome.google.com/webstore/detail/referer-control/hnkcfpcejkafcihlgbojoidoihckciin

And configure like this: enter image description here

Now the second link (including parameters) should work.

Stack Overflow

phpMyAdmin Class ‘PMA_Message’ not found in /usr/share/ phpMyAdmin/libraries/ Error.class.php

profile for Nikola at Stack Overflow, Q&A for professional and enthusiast programmers
I’m a big fan of Stack Overflow and I tend to contribute regularly (am currently in the top 0.X%). In this category (stackoverflow) of posts I will will be posting my top rated questions and answers. This, btw, is allowed as explained in the meta thread here.

My quesiton was:

I just got this error (no errors in phpMyAdmin for the last 2 years):

PHP Fatal error: Class ‘PMA_Message’ not found in /usr/share/phpMyAdmin/libraries/Error.class.php on line 24

I tried searching the net and links like

  • http://gnuwhatimsaying.com/phpmyadmin-error-class-pma_message-not-found/ (changing the ownership of /var/lib/php/session/ folder to apache:apache – it’s already set like that)
  • http://rakesh.sankar-b.com/2012/05/20/phpmyadmin-pma-message-class-not-found/ (quote: “I got a weird idea to see if the space is available for PHP to create sessions – gotcha, that is where my problem was. I cleaned up some unnecessary items and all went well.” – to be honest I don’t know what the author meant by this)

but none solved my issues, and strangely enough – these are only two links which pop up in the first 50 links of google search for this error. So, please shed some light on this.

Btw, the site which is hosted on this server works fine, DB works fine (mysql, login via SSH).

The answer, by Chris Muench, was:

I fixed this issue by restarting apache.

My comment on this answer was:

Thanks, in my case the reload was enough (service httpd reload)

Page 43 of 51« First...102030«42434445»50...Last »

Recent posts

  • When espanso Breaks on Long Replacement Strings (and How to Fix It)
  • 2024 Top Author on dev.to
  • Hara hachi bun me
  • Discipline is also a talent
  • Play for the fun of it

Categories

  • Android (3)
  • Books (114)
    • Programming (22)
  • CodeProject (36)
  • Daily Thoughts (78)
  • Go (3)
  • iOS (5)
  • JavaScript (128)
    • Angular (4)
    • Angular 2 (3)
    • Ionic (61)
    • Ionic2 (2)
    • Ionic3 (8)
    • MEAN (3)
    • NodeJS (27)
    • Phaser (1)
    • React (1)
    • Three.js (1)
    • Vue.js (3)
  • Leadership (1)
  • Meetups (8)
  • Miscellaneou$ (78)
    • Breaking News (8)
    • CodeSchool (2)
    • Hacker Games (3)
    • Pluralsight (7)
    • Projects (2)
    • Sublime Text (2)
  • PHP (6)
  • Quick tips (41)
  • Servers (8)
    • Heroku (1)
    • Linux (3)
  • Stack Overflow (81)
  • Unity3D (9)
  • Windows (8)
    • C# (2)
    • WPF (3)
  • Wordpress (2)

"There's no short-term solution for a long-term result." ~ Greg Plitt

"Everything around you that you call life was made up by people that were no smarter than you." ~ S. Jobs

"Hard work beats talent when talent doesn't work hard." ~ Tim Notke

© since 2016 - Nikola Brežnjak