11 Β· Git, Servers & Deployment β shipping it yourself
The final phase, saved deliberately for last: version control, a real Linux server, and
the full path from a code change on your machine to a live app on the internet β the exact skills
your Restaurants app on DigitalOcean needs from you. Done means: you ship a change and
restore a backup with zero help.
1. Git β you've been doing version control by hand all along
Your own evidence
index-phase2-js.html β a frozen copy you made before the TS conversion, "to keep the
JS as revision history." The commented-out graveyard you keep in app.ts "as history." That
instinct is CORRECT β and Git is the tool that does it properly: every version of every file kept,
with a note of what changed and why, instantly recoverable, with none of the clutter living in
your working files. Once Git holds the history, the graveyard can finally be deleted β nothing is
ever lost again.
Where it comes from
Written by Linus Torvalds in 2005 (in ten days) to manage Linux β the largest collaborative code
project on Earth. "Git" is British slang for an unpleasant person; Linus joked he names projects
after himself. It won so completely that "version control" and "git" are near-synonyms now.
2. The core loop β snapshot, describe, repeat
git init # once per project: start tracking this folder
git status # what changed since the last snapshot?
git add . # stage: choose what goes in the next snapshot
git commit -m "Add loan fines" # snapshot, with a message
git log --oneline # the history, newest first
git diff # exact line-by-line changes, unstaged
A commit is a save point, not a backup of files
Each commit records the ENTIRE project state plus a message β like your PROGRESS.md session log,
but for code, and machine-restorable. The staging step (add) exists so one commit =
one logical change ("add fines") even when your folder also contains unrelated half-done edits.
Good messages say WHY: future-you debugging at midnight reads git log like a diary.
.gitignore β what never gets committed
node_modules/ (regenerable β the npm notes rule), build output (dist/,
your compiled app.js), and secrets (.env with DB passwords/JWT keys β
a secret pushed to GitHub is public forever, even after deleting; assume harvested in minutes).
3. Branches β parallel timelines
git switch -c add-fines # new branch: a safe copy of the timeline
# ...commits on the branch; main is untouched and always working...
git switch main
git merge add-fines # fold the finished work back in
Why branches exist
So the working version and the experiment never fight. Your Restaurants app has prod + test β
same idea. A half-finished feature never blocks an urgent fix: fix on main, ship, switch back.
When both timelines touched the same lines, Git asks you to resolve the conflict β it
marks both versions in the file and you pick; looks scary, is routine.
4. Undoing β the reason Git exists
| Oops | Cure | Danger |
| messed up a file, not committed | git restore file.ts | your edits are gone β that's the point; be sure |
| bad commit, want it undone publicly | git revert <id> β a new commit that cancels it | safe, history preserved |
| want the project as it was last Tuesday | git checkout <id> β look around, come back | read-only visit |
| throw away commits entirely | git reset --hard | β οΈ actually destroys β the one command to respect |
5. GitHub β the shared copy
git remote add origin https://github.com/you/library.git
git push -u origin main # upload your commits
git pull # download new ones (on the server: this IS deployment)
GitHub is not Git
Git is the tool on your machine; GitHub is a hosting service for repositories (Microsoft-owned).
It's your off-site backup, your collaboration point β and crucially for Phase 10, the
bridge to the server: you push from your machine, the server pulls. Code never travels by
copy-paste or FTP again.
6. A real server β a computer you rent
A "droplet" (DigitalOcean's word for a small virtual machine) is a Linux computer in a datacenter,
yours for a few dollars a month, with a public IP address. You control it through
SSH β an encrypted remote terminal:
ssh root@165.22.14.101 # your terminal is now ON the server
apt update && apt install nodejs postgresql nginx
adduser deploy # never work as root day-to-day
ufw allow 22,80,443/tcp # firewall: SSH + web only, every other port closed
Everything you practiced locally was practice for this
The terminal skills (Phase 4), the two-servers idea (Fastify + Postgres), ports, localhost β the
server is the same setup on someone else's hardware with the whole internet able to knock.
That's also why the firewall and non-root user aren't optional: bots scan every new IP within
minutes of it existing.
7. The serving stack β who does what
internet β nginx (:80/:443) β¬β React build (static files, served directly)
ββ /api/* β Fastify (:3000) β Postgres (:5432)
| Piece | Job | Why it exists |
| nginx | the front door: serves the React files, forwards /api to Fastify, handles HTTPS | battle-hardened at facing the raw internet; Node apps hide behind it (a "reverse proxy") |
| PM2 (or systemd) | keeps the Fastify process alive: restarts on crash, starts on reboot, keeps logs | on your PC, YOU restart after Ctrl+C; on a server at 3am, nobody's there β PM2 is the somebody |
| Postgres | same as Phase 5, now on the server | data lives next to the API |
8. Domain & HTTPS
DNS in one line, certificates in two
A domain is a name pointing at your IP β an A record (library.example.com β
165.22.14.101) in your DNS settings, plus patience while it spreads. HTTPS encrypts
browserβserver traffic (without it, logins cross the network readable, and browsers shame the
padlock). Certificates prove you own the domain β Let's Encrypt issues them free,
and certbot --nginx installs AND auto-renews them. Two commands, permanent padlock.
9. Shipping a new version β the loop you'll run forever
# on your machine
git add . && git commit -m "Fix fine rounding" && git push
# on the server
ssh deploy@library.example.com
cd library && git pull
npm install # only if dependencies changed
npx prisma migrate deploy # only if the schema changed
npm run build # rebuild the React frontend
pm2 restart library-api # pick up the new backend code
Rollback β decided BEFORE you deploy
If the new version breaks: git log β git checkout <last-good-id> β
rebuild β restart. Calm, two minutes, because every working version is a commit. The pros' rule:
never ship a version you don't know how to walk back from. (Database migrations are the tricky
part β which is why backups come next.)
10. The ops routine β boring on purpose
| Task | Command family | The rule |
| DB backup | pg_dump library > backup-2026-08-30.sql (cron it nightly) | an untested backup is a hope, not a backup β practice restoring into a scratch DB until it's boring |
| Restore | psql library < backup.sql | the phase's final exam is doing this calmly |
| App logs | pm2 logs | first stop when "the site is down" |
| Web logs | tail -f /var/log/nginx/error.log | second stop β nginx sees what Fastify never received |
| Disk/memory | df -h / free -h | full disks cause the weirdest bugs β check before debugging code |
Reading a production error β same skill, bigger stage
Site down β is nginx up? β is the API up (pm2)? β what do its logs say? β is Postgres up? β disk
full? This is your error-reading habit from Task 2.1, walking down a stack instead of a stack
trace. The habit you've been drilled on since day one β observe, don't guess β is the entire job
here.
11. Done when
The graduation test (from the plan, verbatim)
A code change travels from your machine β git push β live on the server, AND you
restore a DB backup β with zero help from Claude. After this phase, the
Restaurants migration from Utho to DigitalOcean is something you can do yourself β that's the
point of saving this for last.
12. The mental model to keep
| Idea | One line to remember |
| Commit | a described save point of the whole project β your frozen-copy instinct, done right |
| Branch | a parallel timeline; main always works |
| GitHub | the shared copy β you push, the server pulls; deployment = pull |
| SSH | your terminal, on their computer |
| nginx / PM2 | the front door / the 3am babysitter |
| HTTPS | certbot, free, auto-renewing β no excuse for no padlock |
| Backups | only real once you've restored one |
| Never commit | node_modules, build output, secrets |
β Prev: Desktop & Mobile Β·
Back to contents