VPS & Web Hosting series part 2: Configuration¶
In the previous part, we presented the project, installed required packages and even pulled the source code of our incredible app ITRocks into its own folder.
The thing is... the real work hasn't been done yet. Be sure that serious stuff will happen in this second part, so stay with me. This is when it starts to be very interesting! Don't worry, though... it's not that hard, I promise
We must configure our tools and our VPS to put our app in production. So go grab a cup of warm coffee, open a new terminal and follow me into that really exciting phase!
Warning
This is the second part of a series:
- VPS & Web Hosting series part 1: Installation
- VPS & Web Hosting series part 2: Configuration
- VPS & Web Hosting series part 3: Maintenance & additional notes
If you didn't read the VPS & Web Hosting series part 1: Installation, considere doing it before reading what follows
Configuration¶
So... let's start to configure apache2
, certbot
, systemctl
, logrotate
, iptables
and itrocks
to get a fully operational production server.
For security sakes, we will create a specific user and a specific group to restrain our server ability to access the file system:
Some permissions must be set up for itrocks
to be able to access the folder and run node
:
Wait! o+x
? Isn't it insecure?
The o
permission is for others
and means literally all the operating system users will be able to execute
a folder or a file.
nvm
installs a NodeJS version in the current user home directory. It doesn't install it globally for all users.
One of the easiest things to do to make that node version available for everyone is to give everyone the permission to execute it.
But why? Why do we want other users to be able to run NodeJS?
For our itrocks
user. This user doesn't need any home directory, and we want him to only have access to the /home/ubuntu/ITRocks
directory
and to be able to start the server with the node
command. Note that it has no read/write permissions in /home/ubuntu/.nvm
,
only execute
.
If you later install a new version of node using nvm, don't forget to add the o+x
permission to the newly installed NodeJS version!
Now, we need to add our main user ubuntu
to the newly created group itrocks
, because it's ubuntu
that will perform updates:
Before continuing, you MUST run the exit
command and reconnect through SSH for this change to take effects.
For git to automatically set up right permissions/ownership to all files when we pull/checkout, let's create a script in /home/ubuntu/tools
:
Then, past this content to the editor:
/home/ubuntu/tools/gitHook.sh | |
---|---|
Type Ctrl+S to save and Ctrl+X to exit.
Then give the execution permission to the script:
Now, we will create two hooks in /home/ubuntu/ITRocks/.git/hooks
by symlinking our script:
Test it by checkout to the main
branch and checkout back to the release
branch, then use ls
to check all files and folders belongs to the itrocks
group:
The ls -al
command should print something like this:
Apache2¶
Let's start by enabling required modules:
Then, we will create the file /etc/apache2/sites-available/app.itrocks.com.conf
:
For now, SSL-related config is ignored, Certbot will edit this file for us. We just need to provide him a working config on an insecure VirtualHost.
Now we want to enable our website:
But before running Certbot, we need a running server.
ITRocks¶
Not only ITRocks is an awesome cutting-edge technology with no rival out there, but it follows best practices too when it comes to security!
As such, there is no sensitive configuration information in the git repository. It means that we have to store those configurations
in a safe place... that will be a conf.env
config file.
Safe config storage¶
Let's start by creating a folder and our conf.env
file in ~/.config
:
In the editor, we'll paste our configuration:
~/.config/itrocks/conf.env | |
---|---|
Type Ctrl+S to save and Ctrl+X to exit.
In order to protect it, we need to set up right permissions:
Now, the file belongs to the ubuntu
user and is read only, so the itrocks
user itself can't
read it. This way, we ensure that even if an exploit can be used in the ITRocks app to try to read/change the conf.env
file that stores
sensitive data (credentials, api keys, etc.), it won't be able to access it anyway.
As a reminder, within our configuration, the itrocks
user will only have access to two things:
- The
/home/ubuntu/ITRocks
folder (recursively) containing sources with read, write and execute permissions. - The
/home/ubuntu/.nvm
folder (recursively) with only the execute permission to be able to run node.
About /home/ubuntu/ITRocks
permissions
Since ITRocks is fictive, we don't know what it must be able to do with its own source code.
But as a rule of thumb, it should not be able to write. And if it should be able to read/write files,
you should provide a working directory path in conf.env
file, and set up all permissions to this
directory somewhere else in the system.
It can work because it's systemd
that will read this file and provide declared environment
variables to the app. It will read it with root
privileges.
Systemctl¶
This is a service manager used to manage the lifecycle of our itrocks
instance. We will create two files in /etc/systemd/system/
:
itrocks@.service
: a template unit that will allow us, later, to run multiple instances of ITRocks on the same server. When we would need to horizontally scale later.itrocks.target
: the service unit that will decide how much instances to run at a time and manage them for us. Systemd will ensure ITRocks is running from the server startup to the server shutdown and relaunch it if it crashes.
Why not using PM2
or nodemon
instead ?
Some people like to use something like PM2 or Nodemon to daemonize a NodeJS application. But I'll not stand with them, because I do find them useless. Since we still need some init system to make sure they start on boot and restart if they crash. And that's without saying that any init system shipped with any Linux distro will give you as many (if not more) features than those NodeJS based process managers.
IMHO, they are a useless additional layer that we should get ride off in a vast majority of use-cases Keeping our (already) huge tech stacks as tiny as possible is probably one of the most underrated efforts in our field nowadays (at least for Web Development).
That was my 2 cents about it.
Let's start by /etc/systemd/system/itrocks@.service
.
We will need to know the path to the node
binaries:
Should print something like /home/ubuntu/.nvm/versions/node/v18.14.2/bin/node
. We will use it to define the first systemctl unit in ExecStart
. So, do not forget to replace this path if it is different in your environment.
Then create the file by typing sudo nano /etc/systemd/system/itrocks@.service
and pasting the following content into the editor:
Type Ctrl+S to save and Ctrl+X to exit.
Then we will create /etc/systemd/system/itrocks.target
by typing sudo nano /etc/systemd/system/itrocks.target
:
/etc/systemd/system/itrocks.target | |
---|---|
Again, type Ctrl+S to save and Ctrl+X to exit.
Our services are ready, we just need to activate them:
To manage ITRocks now, you can:
- run
sudo systemctl start itrocks.target
- run
sudo systemctl status itrocks.target
- run
sudo systemctl stop itrocks.target
- run
sudo systemctl restart itrocks.target
But you can also use those commands to manage each instance individually (if there is several instances in the future):
- run
sudo systemctl start itrocks@1
- run
sudo systemctl status itrocks@1
- run
sudo systemctl stop itrocks@1
- run
sudo systemctl restart itrocks@1
Logrotate¶
Logrotate will rotate our logs to compress them and remove them automatically after some delay.
To configure it, just run:
And paste the following content in the editor:
/etc/logrotate.d/itrocks | |
---|---|
Then, type Ctrl+S to save and Ctrl+X to exit.
This configuration will rotate itrocks logs daily and keep them 14 days before cleaning them up.
Certbot¶
Now, we want to enable SSL for our proxy.
Just run:
Type the maintainer's mail address, select all domains and accepts terms and conditions.
Once certbot executed, we must edit the SSL config to ensure our websockets will be proxied too.
In our case, the apache file was /etc/apache2/sites-available/app.itrocks.com.conf
, so Certbot will generate a file named /etc/apache2/sites-available/app.itrocks.com.conf-le-ssl.conf
:
You should see something like this:
Then, type Ctrl+S to save and Ctrl+X to exit.
And this is the end of it! ITRocks is now reachable on the url https://app.itrocks.com/
Iptables¶
Now that we have a running server, let's secure it with ubuntu's iptables
firewall.
We will create a file in /home/ubuntu/tools
called ìptables.config.sh
:
Past this content into the editor:
Danger
Modifying this file may lock you out the server, as well as using some iptables
command like iptables flush
.
Since by default the policy is to reject all, if you flush all configurations, the server will reject everything the
instant the command is executed, cutting your SSH connection too.
This is still temporary at this step, because those changes only happen in memory. If you mess it up, restart the server by using your provider's admin panel.
If restart doesn't work because the restart command sent by your provider use a blocked port, you'll need to rely on your provider support, or on an emergency or recovery procedure he planned.
Then, type Ctrl+S to save and Ctrl+X to exit.
Give execution permission to this newly created file and run it to apply:
Danger
Before persisting those rules in the next step, it is very important to test that everything is working fine:
- Exit and reconnect in
SSH
to ensure it is still possible - Try to reach ITRocks and make it send an email to one of your addresses (ensure that you receive it)
- Login to ITRocks and check that your websocket is successfully connected.
- Try to run
sudo apt-get update
andsudo apt-get upgrade
to ensure that the firewall rules do not prevent those commands to execute.
Once all is ok, we can persist iptables
configuration:
Check that iptables-persistent
is running:
Should print something like:
If it is not running, you must enable it by hand:
Fail2ban¶
Fail2ban is a tool to prevent intrusions by watching different services logs. We will use it to watch apache
logs and
to protect our SSH
from brute force attacks.
We must start by enabling it:
Now we need to create a local jail and start editing it:
Starts by uncommenting the following lines (to find them quickly type Ctrl+W, then type the string you search, then type Enter):
bantime.increment = true
bantime.multipliers = 1 2 4 8 16 32 64
ignoreip = 127.0.0.1/8 ::1
Now, we will enable some jails.
A jail looks like this:
By default, they are disabled. To enable a jail, just add enabled = true
after the last parameter:
There is the list of jails we want to enable:
[sshd]
[apache-auth]
[apache-badbots]
[apache-botsearch]
[apache-fakegooglebot]
[apache-modsecurity]
When you're done, type Ctrl+S to save and Ctrl+X to exit.
Then you need to reload fail2ban for those changes to take effect:
Now that our server is fully configured, we need to have a talk about maintenance and additional notes, tips and advices in the third and last part for this series