Skip to content

Linux VPS Production Deployment — 0 to Pro ​

A complete, progressive guide to taking a fresh Ubuntu 24.04 VPS and turning it into a secure, monitored, backed-up production server running a real Nuxt 4 + NestJS + PostgreSQL + Redis application, deployed automatically via CI/CD.

No prior Linux knowledge is assumed. Every command is explained. Every configuration file's location is given. Every chapter ends with a production checklist.

Who this is for ​

You can write application code but have never owned a server. Or you have deployed by hand a few times and want to know what "production-ready" actually means, as opposed to "it responds to a browser".

The reference stack ​

LayerTechnology
Server OSUbuntu 24.04 LTS
ProviderHetzner Cloud (concepts apply to any provider)
FirewallUFW + provider cloud firewall
Intrusion preventionfail2ban
RuntimeNode.js LTS via NVM, pnpm via Corepack
FrontendNuxt 4 + Vue 3 + TypeScript
BackendNestJS + TypeScript + Prisma + Socket.IO
DatabasePostgreSQL 16
Cache / pub-subRedis 7
ContainersDocker + Docker Compose
Reverse proxyNginx
Process managerPM2
TLSCertbot + Let's Encrypt
CI/CDGitHub Actions and GitLab CI

The journey ​

Table of Contents ​

Foundations ​

LevelChapterWhat you learn
0Fundamental ConceptsVPS, Linux, processes, ports, IP, TCP/UDP, DNS, HTTP/HTTPS, reverse proxy
1Creating & Connecting to a VPSProvisioning, SSH, key pairs, ~/.ssh, debugging connections
2Linux Basics for DevelopersFilesystem layout, 30 essential commands, permissions, octal modes
3Users, sudo & PermissionsRoot vs sudo, deploy users, groups, least privilege

Securing the Server ​

LevelChapterWhat you learn
4Initial Server SecurityFull hardening checklist, SSH config, unattended upgrades
5FirewallUFW, inbound/outbound, which ports to never expose

Application Runtime ​

LevelChapterWhat you learn
6NVM & Node.jsNode versions, LTS policy, pnpm via Corepack, non-interactive shells
7Git & Repository DeploymentDeploy keys, branches, safe.directory, ownership
8Environment Variables & Secrets.env files, build-time vs runtime, GitHub/GitLab secrets, rotation

Data Layer ​

LevelChapterWhat you learn
9PostgreSQLRoles, databases, connection strings, pg_hba.conf, native vs Docker
10RedisCache, sessions, queues, Socket.IO adapter, persistence, auth
11Docker & Docker ComposeImages, containers, volumes, networks, production compose files

Running in Production ​

LevelChapterWhat you learn
12Building the ApplicationNuxt .output, NestJS dist, Prisma generate & migrate deploy
13PM2Process management, cluster mode, ecosystem.config.cjs, startup
14NginxReverse proxy, server blocks, WebSocket upgrade, static caching
15DNSRecords, TTL, propagation, dig debugging
16SSL / HTTPS / CertbotACME, HTTP-01, renewal, TLS hardening

Automation ​

LevelChapterWhat you learn
17CI/CD ConceptsPipelines, gates, artifacts, rollback thinking
18GitHub ActionsFull production workflow, line by line, plus every common error
19GitLab CI & Runner.gitlab-ci.yml, runner install, executors, comparison with Actions
20Deployment StrategiesSimple, zero-downtime, blue-green, rolling, container-based

Operations ​

LevelChapterWhat you learn
21Logging & Monitoringjournald, Nginx logs, PM2 logs, resource metrics, alerting
22Backupspg_dump, automation, 3-2-1, off-site, restore drills
23Advanced Server SecurityThreat scenarios with prevent/detect/recover playbooks

Putting It Together ​

LevelChapterWhat you learn
24Production ArchitectureThe final design and what is public vs private
25Complete From-Zero DeploymentOne executable runbook, fresh VPS to live HTTPS app
26Troubleshooting Handbook30 failures with causes, diagnostics, fixes, prevention
27Production ChecklistsNew VPS, pre-production, post-deployment

Reference ​

Conventions used in this guide ​

Commands that run on your own laptop are marked:

bash
# LOCAL
ssh deploy@203.0.113.10

Commands that run on the server are marked:

bash
# SERVER
sudo apt update

DANGEROUS COMMAND

Blocks like this precede any command that can destroy data or lock you out. Read them before pressing Enter.

PRODUCTION BEST PRACTICE

Blocks like this mark what experienced operators actually do.

COMMON MISTAKE

Blocks like this mark the traps that cost people a weekend.

Throughout, the example domain is example.com, the frontend lives at app.example.com, the API lives at api.example.com, and the server's public IP is 203.0.113.10 (a documentation-reserved address — replace it with yours).

"Working" vs "production-ready" ​

This distinction runs through the entire guide, so define it now.

WorkingProduction-ready
ProcessStarted with pnpm start in an SSH sessionManaged by PM2/systemd, restarts on crash and reboot
ExposureApp on port 3000, open to the internetBound to 127.0.0.1, only Nginx reachable
TLSNone, or self-signedLet's Encrypt with automatic renewal, verified
SecretsHard-coded or committedInjected from .env with 600 perms, rotatable
DatabaseDefault password, port openStrong password, localhost-only, backed up nightly
DeploysManual SSH and git pullPipeline with lint, typecheck, build, migrate, reload
FailureYou find out from a userYou find out from an alert
Recovery"I'll rebuild it"Documented, tested restore under an hour

Anything can be made to work in an afternoon. The rest of this guide is about the right-hand column.