Blog: Hosting fullstack apps on CentOS VPS
Published: 2023-05-15 22:33:07

**// This is an ongoing blog and will be updated regularly**

My goal is to host projects on my own CentOS VPS hosted on DigitalOcean. During my learning i was always recommended to use services from Heroku, Netlify and Render to host my backend and GitHub Pages for my frontend - i never liked splitting my apps.
_I think i heard Next.js can resolve this with serverless options?_

I also wanted to easily edit my projects without the hassle of `npm run build` and uploading. I'd thought of FTP/SSH extensions for VSCode but there must be a better way?

This is my journey...

---

## Server Installations

I installed **Node Version Manager (NVM)** to my server for **Node and NPM**. I updated the bash commands and checked the versions to ensure they were installed correctly.
```
# curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.37.2/install.sh | bash
# source ~/.bashrc
# node --version
~ v14.15.4
# npm --version
~ 6.14.4
```

I needed my apps to stay live when terminal was closed so i globally installed the **daemon process manager 'PM2' **and again checked the version to ensure they were installed correctly. This manager will run the dev environment on the live server without needing to create a build package.
```
# npm i -g pm2
# pm2 --version
~ 5.3.0
```

Firstly i created a subdomain (forecast.literecords.com) so my app would have it's own address. Using the **Git Version Control plugin within my cPanel (v110)** i created a repo and pointed the directory to the subdomain so edits go live as easily as possible.

`# git remote add <local-name> <cpanel-repo-url>`
```
# git remote add cpanel ssh://root@literecords.com/home/litereco/public_html/forecast.literecords.com
# git push -u cpanel main
```

_My project is already remotely connected to a GitHub repo so i added my cPanel repo as a second remote (not 'origin')._

The original ssh user received 'Permission Denied" errors so i changed the user to 'root' which worked. Later i found a solution to the permissions by changing ownership of the directory to the user 'litereco'.
```
# chown -R litereco. /home/litereco/.ssh
```

This project is build using React-Vite so i set the server port and allowed host in 'vite.config.js', this can be done in command line when starting the service too.
```
export default defineConfig({
  plugins: [react()],
  server: {
    port: 4444,
    host: true,
  },
});
```

### Problem
I originally thought there was a problem with permissions on my server but i now think it's something else. While the initial upstream set works, further push attempts show an error.

` ! [remote rejected] main -> main (Working directory has unstaged changes)
error: failed to push some refs to 'ssh://literecords.com/home/litereco/public_html/forecast.literecords.com'`.

I tested replacing files through SFTP and the changes are instantly live so i see no reason why `# git push` wouldn't do the same once my remote GIT issue is resolved.

---

## Starting Services

To run the process with PM2 i SSH connected to my server and navigated to the subdomain directory where the app is located. I then started the service with `npm run dev` and gave it a name.
```
# cd home/litereco/public_html/forecast.literecords.com
# pm2 start "npm run dev" --name "Forecast App"
```

---

## Nginx

Right now this runs from any part of the parent domain so long as it includes the port `:4444` so installed Nginx and configured it to listen on port `:4567` because `:4444` was already in use and direct the default to my app location.
`/etc/nginx/nginx.config`

```
server {
        listen       4567;
        listen       [::]:4567;
        server_name  forecast.literecords.com;
        root         /home/litereco/public_html/forecast.literecords.com;

        # Load configuration files for the default server block.
        include /etc/nginx/default.d/*.conf;

        error_page 404 /404.html;
        location = /404.html {
        }

        error_page 500 502 503 504 /50x.html;
        location = /50x.html {
        }
```

I created my proxy file in `/etc/nginx/sites-available/forecast.literecords.com`
```
server {
    server_name  forecast.literecords.com;
    index index.html index.htm;
    access_log /var/log/nginx/nodeapp.log;
    error_log  /var/log/nginx/nodeapp-error.log error;

    location / {
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header Host $http_host;
        proxy_pass http://165.232.78.74:4444;
        proxy_redirect off;
    }
}
```

Tested the NGinx config.
```
# nginx -t
~ nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
~ nginx: configuration file /etc/nginx/nginx.conf test is successful
```

Restarted Nginx service.
`# sudo systemctl restart nginx.service`

Navigated to forecast.literecords.com, **blank page**!