Node.js + Nginx + Redis + MySQL + PM2 configuration on DigitalOcean
Install LEMP stack
Overwrite /etc/nginx/nginx.conf
# /etc/nginx/nginx.conf
user www-data;
worker_processes auto;
pid /run/nginx.pid;
include /etc/nginx/modules-enabled/*.conf;
events {
worker_connections 768;
}
http {
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
server_tokens off;
include /etc/nginx/mime.types;
default_type application/octet-stream;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # Dropping SSLv3, ref: POODLE
ssl_prefer_server_ciphers on;
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
charset utf-8;
log_not_found off;
add_header X-XSS-Protection 1;
add_header X-Content-Type-Options nosniff;
add_header Referrer-Policy "no-referrer-when-downgrade" always;
add_header Content-Security-Policy "default-src * data: 'unsafe-eval' 'unsafe-inline'" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header Last-Modified $date_gmt;
add_header Cache-Control 'no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0';
if_modified_since off;
expires off;
etag off;
client_body_buffer_size 1K;
client_header_buffer_size 1k;
client_max_body_size 50k;
large_client_header_buffers 2 1k;
client_body_timeout 20;
client_header_timeout 10;
send_timeout 10;
proxy_no_cache 1;
proxy_cache_bypass 1;
limit_conn_zone $binary_remote_addr zone=addr:5m;
gzip on;
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
}
Add new server block in /etc/nginx/sites-available/default
# /etc/nginx/sites-available/default
server {
listen 80;
server_name localhost;
limit_conn addr 5;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header X-Forwarded-Host $remote_addr;
proxy_http_version 1.1;
# First reverse proxy
location /api/ {
proxy_pass http://localhost:8080;
}
# Second reverse proxy
location / {
proxy_pass http://localhost:3000;
}
# Allowed http methods
if ($request_method !~ ^(GET|HEAD|POST|DELETE|PUT|PATCH)$ ){
return 405;
}
# Redirect server error pages to the static page /50x.html
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
Create symbolic link between previously created server block and sites-enabled:
sudo ln -s /etc/nginx/sites-available/default /etc/nginx/sites-enabled/
Install Node.js and NPM
curl -sL https://deb.nodesource.com/setup_10.x -o nodesource_setup.sh
sudo bash nodesource_setup.sh
sudo apt install nodejs
nodejs -v
npm -v
Install Redis
sudo apt install redis-server
Open Redis configuration file and set settings
# /etc/redis/redis.conf
supervised systemd
bind 127.0.0.1 ::1
requirepass <SOME STRONG PASSWORD>
maxmemory 100mb
maxmemory-policy volatile-ttl
Restart and test Redis service
systemctl restart redis.service
redis-cli
auth <SOME STRONG PASSWORD>
set test 1234
get test
Install PM2 and setup autostart on reboot
npm install pm2 -g
pm2 startup systemd
systemctl status pm2-<username>
Add new user with less privledges
adduser <username>
Apply security fixes on MySQL
sudo mysql_secure_installation
Set MySQL root password
mysql
ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY '<ROOT_PASSWORD>';
Add new non-root user
CREATE USER '<USERNAME>'@'localhost' IDENTIFIED BY '<PASSWORD>';
Add user privledges
GRANT ALL PRIVILEGES ON *.* TO 'rohs'@'localhost' WITH GRANT OPTION;
Flush and check MySQL credentials
FLUSH PRIVILEGES;
SELECT user,authentication_string,plugin,host FROM mysql.user;
Install phpMyAdmin
sudo apt update
sudo apt install phpmyadmin
# PRESS TAB (Nginx isn't on the list, so choose OK)
# Select YES
# Type password for new phpmyadmin user
# Confirm password
Configure Nginx - create new snippet
sudo nano /etc/nginx/snippets/phpmyadmin.conf
Paste inside
# /etc/nginx/snippets/phpmyadmin.conf
location /phpmyadmin {
root /usr/share/;
index index.php index.html index.htm;
location ~ ^/phpmyadmin/(.+\.php)$ {
try_files $uri =404;
root /usr/share/;
fastcgi_pass unix:/run/php/php7.2-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include /etc/nginx/fastcgi_params;
}
location ~* ^/phpmyadmin/(.+\.(jpg|jpeg|gif|css|png|js|ico|html|xml|txt))$ {
root /usr/share/;
}
}
Include snippet in server block
# /etc/nginx/sites-available/default
include snippets/phpmyadmin.conf;
Upgrade phpMyAdmin - create backup
sudo mv /usr/share/phpmyadmin/ /usr/share/phpmyadmin.bak
sudo mkdir /usr/share/phpmyadmin/
cd /usr/share/phpmyadmin/
sudo wget https://files.phpmyadmin.net/phpMyAdmin/4.8.5/phpMyAdmin-4.8.5-all-languages.tar.gz
sudo tar xzf phpMyAdmin-4.8.5-all-languages.tar.gz
ls
sudo mv phpMyAdmin-4.8.5-all-languages/* /usr/share/phpmyadmin
Open vendor_config.php and change phpMyAdmin settings
# /usr/share/phpmyadmin/libraries/vendor_config.php
# ...
define('TEMP_DIR', '/var/lib/phpmyadmin/tmp/');
# ...
define('CONFIG_DIR', '/etc/phpmyadmin/');
Cleanup and remove useless phpMyAdmin files
sudo rm /usr/share/phpmyadmin/phpMyAdmin-4.8.5-all-languages.tar.gz
sudo rm -rf /usr/share/phpmyadmin/phpMyAdmin-4.8.5-all-languages