Christopher Ferrari

My Website Stack: How I Built, Deployed, and Manage My Personal Site

Published on May 11, 2025

This is the full stack I use to run my personal website. I had never built or deployed a full site from scratch before this. Most of my previous experience was limited to making small edits or working locally. I wanted full control this time—not just over the code, but over the server, the deployment process, and the structure. What I have now is a reliable setup that I understand end-to-end.


The site is hosted on a Debian VPS through Vultr. I chose Vultr because I wanted complete root access without relying on platforms that abstract the backend away. I installed and configured Nginx as my web server, and I used Certbot to set up HTTPS. I followed a straightforward and well-documented tutorial by Luke Smith on landchad.net which walked through the process step-by-step, including setting up a basic firewall and SSL. Since Vultr disables the firewall by default, I had to explicitly allow ports 80 and 443 using ufw allow 80,443. I also created a cronjob to handle SSL certificate renewal automatically once a year using this command:


0 0 1 * * certbot --nginx renew

For the frontend, I used Next.js with React. Originally, I was just updating a static index.html page using Git fetch and a simple deploy alias. But I knew I wanted something more dynamic and scalable, so I rebuilt the site using Next.js. I used Google's fullstack workspace to assist with some of the initial React and Next.js setup. Since I am still learning React, it was an invaluable tool. It helped me get familiar with layout patterns, routing, and component logic, and gave me the flexibility to test, revise, and expand without constantly having to dig through documentation or start from scratch.


The actual code lives in a private GitHub repository. I work on the project locally in Visual Studio Code, commit changes, and push them to the repo. From there, I SSH into my VPS and run a script I aliased as deploy. This script handles the full deployment process in a consistent and repeatable way. Here is what it does:


Navigates to the root directory of the project

Resets any local changes using git reset --hard

Pulls the latest version of the code from the master branch

Stops any running instance of the site using PM2

Deletes all old PM2 processes to avoid conflicts

Installs the latest dependencies using npm install

Fixes execution permissions on the Next.js binary with chmod

Ensures the correct ownership of files using chown

Builds the application from scratch using npm run build


Each step includes a fallback or error trap to make sure the script exits immediately if something breaks. This ensures that partial updates or broken builds do not make it to the live site. I prefer this level of control because I want the environment to be consistent and clean with every deployment.


Although it may seem like overkill to some, this deployment method has proven extremely reliable. I only need to SSH into the server and type deploy. Everything else takes care of itself. It is simple, fast, and dependable.


This stack has taught me how to manage my own server, secure it properly, and deploy a real frontend framework from scratch. More importantly, it has shown me the value of owning the full process. I am not relying on third-party automation or managed services. I know exactly what each part of the stack is doing, and I can fix it if something breaks. As I continue developing the site, I plan to expand the features, improve the styling, and possibly integrate a backend or database, but for now I have a solid foundation that works.