Using a VPS to deploy a node js web app
Contabo Ubuntu VPS: SSH, MariaDB, Node.js, systemd Service
This guide assumes:
- You have a new Contabo VPS with Ubuntu (latest LTS).
- You have the VPS IP and initial
rootpassword. - You will create a non-root user, install MariaDB and Node.js, upload your Node app, and run it as a systemd service.
YOUR_SERVER_IP, youruser, yourdb, user1, StrongPasswordHere, /opt/app, server.js
with your actual values.
1. Local machine: tools you need
1.1 On Windows (PowerShell)
- Install Git for Windows from the official site.
- During setup, allow it to add
git,sshto your PATH. - You can use either:
- PowerShell (recommended) or
- Git Bash (also fine)
1.2 On local Ubuntu
If you also have an Ubuntu laptop/desktop:
sudo apt update sudo apt install -y openssh-client git
2. Generate SSH key (Windows or Ubuntu)
Run this in PowerShell (Windows) or a terminal (Ubuntu):
ssh-keygen -t ed25519 -C "your_email@example.com"
Press Enter for default file location (~/.ssh/id_ed25519), set a passphrase if you like.
Show the public key:
type $env:USERPROFILE\.ssh\id_ed25519.pub # PowerShell # OR on Ubuntu: cat ~/.ssh/id_ed25519.pub
Copy the full line starting with ssh-ed25519.
3. First login to the Contabo VPS (root)
From PowerShell or Ubuntu terminal:
ssh root@YOUR_SERVER_IP
Enter the root password from Contabo. Once in:
apt update apt upgrade -y
4. Create a non-root sudo user
Inside the VPS as root:
adduser youruser usermod -aG sudo youruser
Create SSH directory for this user and add your public key:
su - youruser mkdir -p ~/.ssh chmod 700 ~/.ssh nano ~/.ssh/authorized_keys
Paste your copied id_ed25519.pub line into authorized_keys, save and exit.
chmod 600 ~/.ssh/authorized_keys
Open a second terminal on your local machine and test:
ssh youruser@YOUR_SERVER_IP
5. Harden SSH (basic)
Back as root or with sudo:
sudo nano /etc/ssh/sshd_config
Change or add:
PermitRootLogin no PasswordAuthentication no
Then restart SSH:
sudo systemctl restart ssh
Test again from local: you should now only be able to log in using your SSH key:
ssh youruser@YOUR_SERVER_IP
6. Basic firewall (UFW)
sudo apt install -y ufw sudo ufw default deny incoming sudo ufw default allow outgoing sudo ufw allow OpenSSH sudo ufw allow 80/tcp sudo ufw allow 443/tcp sudo ufw enable
7. Install MariaDB
sudo apt update sudo apt install -y mariadb-server mariadb-client
Secure the installation:
sudo mysql_secure_installation
Answer the prompts (set a strong root password, remove test DB, etc.).
7.1 Create database and user
Log in to MariaDB:
sudo mysql -u root -p
Inside the MariaDB shell:
CREATE DATABASE yourdb CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; CREATE USER 'user1'@'localhost' IDENTIFIED BY 'StrongPasswordHere'; GRANT ALL PRIVILEGES ON yourdb.* TO 'user1'@'localhost'; FLUSH PRIVILEGES; EXIT;
StrongPasswordHere.
8. Install Node.js and npm
Example using NodeSource (Node 22 LTS style). Run as youruser with sudo:
curl -fsSL https://deb.nodesource.com/setup_22.x | sudo -E bash - sudo apt install -y nodejs
Check versions:
node -v npm -v
9. Create an app directory and user
Create a dedicated user for your Node app (no shell login):
sudo useradd -r -m -d /opt/app -s /usr/sbin/nologin appuser
Create app directory and set permissions:
sudo mkdir -p /opt/app sudo chown appuser:appuser /opt/app
10. Upload or clone your Node.js code
10.1 From Windows using PowerShell (SCP)
From your local machine, assuming your app files are in C:\myapp:
scp -r C:\myapp\* youruser@YOUR_SERVER_IP:/home/youruser/myapp
10.2 Move code into app directory
On the server:
sudo rsync -a /home/youruser/myapp/ /opt/app/ sudo chown -R appuser:appuser /opt/app
11. Install Node dependencies and test run
Switch to appuser:
sudo -u appuser -s cd /opt/app
Install dependencies from package.json:
npm install
Optional: create/update .env with DB credentials etc:
nano .env # Example content: DB_HOST=localhost DB_NAME=yourdb DB_USER=user1 DB_PASS=StrongPasswordHere PORT=3000
Test the app (adjust for your entry file):
node server.js
Check in your browser: http://YOUR_SERVER_IP:3000 (if you expose that port) or behind a reverse proxy later.
Stop the test with Ctrl+C.
12. Create a systemd service for Node.js
Exit from appuser shell back to sudo user if needed, then:
sudo nano /etc/systemd/system/myapp.service
Example service file:
[Unit] Description=My Node.js App After=network.target [Service] Type=simple User=appuser WorkingDirectory=/opt/app EnvironmentFile=/opt/app/.env ExecStart=/usr/bin/node /opt/app/server.js Restart=on-failure RestartSec=5 StandardOutput=journal StandardError=journal [Install] WantedBy=multi-user.target
Reload systemd and start the service:
sudo systemctl daemon-reload sudo systemctl start myapp.service sudo systemctl status myapp.service
Enable on boot:
sudo systemctl enable myapp.service
View logs:
sudo journalctl -u myapp.service -f
13. Basic hardening checklist
- Use a strong password for
user1and all system users. - Keep
apt updateandapt upgraderun regularly. - Only open ports you need (SSH, HTTP/HTTPS, DB not exposed publicly).
- Optionally add
fail2banto block brute-force SSH attempts:sudo apt install -y fail2ban
- Do not run your Node app as
root; useappuseras shown.
14. Using local Ubuntu instead of Windows
On a local Ubuntu machine everything is similar:
- Generate SSH key:
ssh-keygen -t ed25519 - Connect:
ssh youruser@YOUR_SERVER_IP - Upload:
scp -r ./myapp youruser@YOUR_SERVER_IP:/home/youruser/
Then follow the same steps on the VPS (create appuser, move app to /opt/app, npm install, systemd service, etc.).
- Log in to post comments