Introduction: From Development to Production on VPS
Deploying a TypeScript application on a VPS (Virtual Private Server) is a key stage in the lifecycle of any web project. Unlike simple shared hosting, a VPS gives you full control over the environment, which is critical for modern TypeScript applications working with Node.js, Express, NestJS, or Next.js.
In this article, we will cover the advanced deployment process: from compiling TypeScript to setting up a production environment with automatic restart, load balancing, and monitoring. You will learn how to turn raw code into a stably running service.
1. Preparing the TypeScript Application for Production
1.1. Configuring Build and Configuration
The first step is to ensure your tsconfig.json is optimized for production. Here is the recommended configuration:
{ "compilerOptions": { "target": "ES2020", "module": "commonjs", "lib": ["ES2020"], "outDir": "./dist", "rootDir": "./src", "strict": true, "esModuleInterop": true, "skipLibCheck": true, "forceConsistentCasingInFileNames": true, "resolveJsonModule": true, "declaration": true, "declarationMap": true, "sourceMap": true }, "include": ["src/**/*"], "exclude": ["node_modules", "dist", "tests"]}Add build and start scripts to package.json:
{ "scripts": { "build": "tsc", "start": "node dist/index.js", "dev": "ts-node src/index.ts", "clean": "rm -rf dist" }}1.2. Managing Environment Variables
Use .env files with the dotenv library. For production, create a separate .env.production file:
NODE_ENV=productionPORT=3000DB_HOST=localhostDB_PORT=5432DB_NAME=myapp_prodDB_USER=app_userDB_PASSWORD=secure_password_hereREDIS_URL=redis://localhost:6379Load the configuration based on the environment:
import dotenv from 'dotenv';import path from 'path';
const envFile = process.env.NODE_ENV === 'production' ? '.env.production' : '.env.development';
dotenv.config({ path: path.resolve(__dirname, `../${envFile}`) });
export const config = { port: parseInt(process.env.PORT || '3000', 10), db: { host: process.env.DB_HOST || 'localhost', port: parseInt(process.env.DB_PORT || '5432', 10), name: process.env.DB_NAME || 'myapp', user: process.env.DB_USER || 'user', password: process.env.DB_PASSWORD || '', }, redis: { url: process.env.REDIS_URL || 'redis://localhost:6379', }, isProduction: process.env.NODE_ENV === 'production',};2. Setting Up the VPS and Deploying the Application
2.1. Basic Server Setup
After purchasing a VPS (we recommend Ubuntu 22.04 LTS), perform the initial setup:
- Update packages:
sudo apt update && sudo apt upgrade -y - Install Node.js 20 LTS:
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash - && sudo apt install -y nodejs - Install Git:
sudo apt install git -y - Create a user:
sudo adduser deployer && sudo usermod -aG sudo deployer
2.2. Cloning and Building the Project
Connect to the server via SSH and execute:
# Switch to the usersudo -i -u deployercd ~
# Clone the repositorygit clone https://github.com/your-username/your-app.gitcd your-app
# Install dependenciesnpm ci --only=production
# Build TypeScriptnpm run build
# Create .env file for productionnano .env.production2.3. Configuring PM2 for Process Management
PM2 is a