An Ubuntu based server that runs ruby and nodejs apps
November 24, 2013This post is based on my latest setup of a fresh build of Ubuntu Server 13.10 on Linode. What I wanted was a server that is able to run and host Ruby and Nodejs based applications. In my case this is a Padrino app for my personal site, Ghost blogging platform for my blog and Ruby on Rails side projects quotesofstewie.com. In the past I’ve used Phussion Passenger and Apache and it has worked very well and has been very easy to configure.
After looking at the requirements and my needs I’ve choosen to go with Nginx and Thin for the Ruby apps, the main reason for this is that it seems to be easier to configure Nginx and Nodejs together than Apache and Nodejs, this is something I haven’t researched thoroughly though. I also wanted to try out something different than Phussion Passenger for running the Ruby apps.
When rebuilding a node on Linode you choose a root password and when the build is done you can login with ssh as the root user. The initial setup, administration and deployment user will be made using the root user and further configuration will be done with the administration and deployment user.
First thing is to change the hostname so that it is easy to identify the machine.
# Change the hostname
echo “ruby-server" > /etc/hostname
hostname -F /etc/hostname
# Edit the host file of the system
nano /etc/hosts
127.0.0.1 localhost.localdomain localhost
xxx.xxx.xxx.xxx ruby-server.example.com ruby-server
Something that you always should do on a fresh Ubuntu server installation and I guess this goes for all Debian based distributions. Is to update the package manager information and upgrade the currently installed software and install common used header files, compilers and utility scripts.
# Update the package manager information and upgrade the packages to the latest version.
apt-get update
apt-get upgrade
# Install the basic utilities we need to build and install other packages
apt-get install build-essential python-software-properties
As mentioned earlier, the server should use Nginx and Nodejs. Both of these are available via the Ubuntu package manager, but the versions are outdated. By adding the proper PPA:s it is possible to use the latest builds availble by the communtiy.
# The proper PPA repositories to get the latest builds from the community
add-apt-repository ppa:chris-lea/node.js
add-apt-repository ppa:nginx/stable
# Run the update command again to retrieve the package information.
apt-get update
Time to install some of the packages before creating the administration and deployment user and use these two for rest of the configuration.
# Install the packages we need
apt-get install postgresql nodejs nginx git imagemagick libpq-dev
Postgres - We need to store our data somewhere
Nginx - The choosen web server
Nodejs - To power the Ghost blog but also used by Rails
Git - Is needed for both RVM and Capistrano when deploying our apps
ImageMagick - Handle image manipulation in our apps. This might not be needed for everyone, but images are so common these days that it is almost a must.
libpq-dev - Is used by the PG gem in order to build correctly
Now when the generic installation is completed lets add the administration and deployment users called Sysop and Deployer
#Add the administration and deployment users and fill out the information prompted for.
adduser sysop
# Add Sysop to the sudo group, this user is used to carry out all administration tasks.
usermod -a -G sudo sysop
adduser deployer
# Add Deployer to the www-data group since it will share folders with the web server.
usermod -a -G www-data deployer
Next on the list is to close down the access to the server.
# Restricting SSH access by editing the sshd config file
nano /etc/ssh/sshd_config
# Change and add the following settings
Port 5632
PermitRootLogin no
PasswordAuthentication no
UseDNS no
AllowUsers deployer sysop
With this configuration only deployer and sysop will be able to login to the server using ssh keys. If you don’t know how to use ssh keys, do not change PasswordAuthentication.
Before restarting the sshd service, make sure only the ports that are needed is accessible, in this case it is port 80 for the web and port 5632 used for the sshd.
# Enable UFW
ufw allow 5632
ufw allow 80
ufw enable
Last thing before switching user is to add the proper ssh keys for them so that they can login. Since the build is completly fresh there are .ssh folders or auhtenticated_keys files availble for Sysop and Deployer. Upload your public key, most likely id_rsa.pub to Sysops home directory, you can use either an SFTP program, the SCP command or if you are lucky ssh-copy-id.
# Add ssh key for Sysop
mkdir mkdir /home/sysop/.ssh
mv id_rsa.pub /home/sysop/.ssh/authorized_keys
# Add the ssh key for Deployer
mkdir mkdir /home/deployer/.ssh
cp /home/sysop/.ssh/authorized_keys /home/deployer/.ssh/authorized_keys
# Set the correct ownership
chown -R sysop:sysop /home/sysop/.ssh
chown -R sysop:sysop /home/deployer/.ssh
# Restrice the access to the .ssh directory and authorized_keys file
chmod 600 /home/sysop/.ssh/authorized_keys
chmod 700 /home/sysop/.ssh
chmod 600 /home/deployer/.ssh/authorized_keys
chmod 700 /home/deployer/.ssh
# If this wasn't a fresh build you would normally just append your key to an existing system user or your setup a private user of your own the same way.
Open up two new terminals and login with the created users to verify that it works. If it all checks out, restart the sshd service, but don’t log out the root user just yet.
# Resarting the SSH service to restric access to the server
service ssh restart
Log out Sysop and Deployer and make sure you can log in with them again. If it works, log out the root user. From now on Sysop and Deployer will be used to finish of the configuration.
First task is for Sysop to set a root password for the postgres database.
# Set a new password for the postgres root user 'postgres'
sudo -u postgres psql template1
ALTER USER postgres with encrypted password 'YOURPASSWORD';
# To quit the Postgres shell
\q
# Restart postgres
sudo service postgresql restart
Next up it is time for Deployer to install RVM. RVM is a great tool to manage Ruby versions and keep isolated rubygems between apps and projects using Gemsets.
# Use the deployer user and install RVM
\curl -L https://get.rvm.io | bash -s stable --without-gems="rvm rubygems-bundler”
# The Deployer user does not have sudo access, therefor it is essential to disable autolibs
rvm autolibs disable
# Find out the requirements for RVM to build Ruby
rvm requirements
Copy the list of requirements and use Sysop to install them. Some of the packages might already be installed.
# Install the packages required by RVM with the Sysop user
sudo apt-get install openssl libreadline6 libreadline6-dev curl git-core zlib1g zlib1g-dev libssl-dev libyaml-dev libsqlite3-dev sqlite3 libxml2-dev libxslt-dev autoconf libc6-dev ncurses-dev automake libtool bison pkg-config
Use Deployer to install the latest Ruby version or the version you need or want.
# Deployer installs the latest stable version of Ruby 2.0
rvm install 2.0.0
When finished run the version commands for Ruby and Rubygems to verify that it all works
# Check the Ruby and Rubygems versions
Ruby -v => ruby 2.0.0p353 (2013-11-22 revision 43784) [x86_64-linux]
gem -v => 2.1.11
Finally start Nginx and make sure you can see the “welcome / it works” page
# Start Nginx as Sysop
sudo service nginx start
Thats it! The server is now fully configured for my current needs. There is of course a few bits and bobs left, but the foundation is there. In an upcoming blog post I’ll show how to configure Nginx for Padrino and Nodejs to make it possible to run the presentation site and blog.