1
Prerequisites
Why Fastify?
- Benchmarked as one of the fastest Node.js frameworks available
- Built-in JSON Schema validation for request/response
- Powerful plugin system with encapsulation
- TypeScript support out of the box
- Automatic logging with Pino
- Low memory footprint and efficient request handling
Requirements
- A RamNode VPS with at least 1GB RAM (2GB recommended)
- Ubuntu 22.04 or 24.04 LTS installed
- Root or sudo access to the server
- A domain name pointed to your server's IP address
- Basic familiarity with Linux command line and Node.js
Recommended RamNode Plans
| Plan | RAM | CPU | Use Case |
|---|---|---|---|
| Premium KVM | 2GB | 2 cores | Small to medium APIs |
| Premium KVM | 4GB | 2 cores | Production applications |
| Premium KVM | 8GB | 4 cores | High-traffic services |
2
Initial Server Setup
Connect and update system
ssh root@your-server-ip
# Update system packages
apt update && apt upgrade -yCreate a Non-Root User
Create dedicated user
adduser fastify
usermod -aG sudo fastify
su - fastifyConfigure Firewall
Set up UFW
sudo ufw allow OpenSSH
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enable
sudo ufw status3
Installing Node.js
Add NodeSource and install Node.js
# Add NodeSource Repository
curl -fsSL https://deb.nodesource.com/setup_22.x | sudo -E bash -
# Install Node.js and npm
sudo apt install -y nodejs
node --version
npm --version
# Install PM2 globally
sudo npm install -g pm24
Creating Your Fastify Application
Initialize project
mkdir -p /var/www/fastify-app
cd /var/www/fastify-app
npm init -y
# Install Fastify and dependencies
npm install fastify @fastify/cors @fastify/helmet @fastify/rate-limit
npm install --save-dev pino-prettyCreate Application Entry Point
app.js
'use strict'
const fastify = require('fastify')({
logger: {
level: process.env.LOG_LEVEL || 'info',
transport: process.env.NODE_ENV !== 'production'
? { target: 'pino-pretty' }
: undefined
},
trustProxy: true
})
// Register plugins
fastify.register(require('@fastify/cors'), {
origin: process.env.CORS_ORIGIN || true,
credentials: true
})
fastify.register(require('@fastify/helmet'), {
contentSecurityPolicy: {
directives: {
defaultSrc: ["'self'"],
styleSrc: ["'self'", "'unsafe-inline'"],
scriptSrc: ["'self'"],
imgSrc: ["'self'", "data:", "https:"]
}
}
})
fastify.register(require('@fastify/rate-limit'), {
max: 100,
timeWindow: '1 minute'
})
// Health check endpoint
fastify.get('/health', async (request, reply) => {
return {
status: 'healthy',
timestamp: new Date().toISOString(),
uptime: process.uptime()
}
})
// Root route
fastify.get('/', async (request, reply) => {
return {
message: 'Welcome to Fastify on RamNode!',
version: '1.0.0'
}
})
// API routes example
fastify.get('/api/info', {
schema: {
response: {
200: {
type: 'object',
properties: {
server: { type: 'string' },
nodeVersion: { type: 'string' },
environment: { type: 'string' }
}
}
}
}
}, async (request, reply) => {
return {
server: 'Fastify',
nodeVersion: process.version,
environment: process.env.NODE_ENV || 'development'
}
})
// Metrics endpoint
fastify.get('/metrics', async (request, reply) => {
const memUsage = process.memoryUsage()
return {
uptime: process.uptime(),
memory: {
rss: Math.round(memUsage.rss / 1024 / 1024) + 'MB',
heapTotal: Math.round(memUsage.heapTotal / 1024 / 1024) + 'MB',
heapUsed: Math.round(memUsage.heapUsed / 1024 / 1024) + 'MB'
},
cpu: process.cpuUsage(),
pid: process.pid
}
})
// Start server
const start = async () => {
try {
const port = process.env.PORT || 3000
const host = process.env.HOST || '127.0.0.1'
await fastify.listen({ port, host })
fastify.log.info(`Server running at http://${host}:${port}`)
} catch (err) {
fastify.log.error(err)
process.exit(1)
}
}
start()Test the Application
Verify it works
node app.js
# In another terminal, test endpoints:
curl http://localhost:3000/health
curl http://localhost:3000/api/info5
PM2 Process Management
PM2 ensures your Fastify application runs continuously, restarts on crashes, and starts automatically on server boot.
ecosystem.config.js
module.exports = {
apps: [{
name: 'fastify-app',
script: 'app.js',
instances: 'max',
exec_mode: 'cluster',
env_production: {
NODE_ENV: 'production',
PORT: 3000,
HOST: '127.0.0.1'
},
max_memory_restart: '500M',
error_file: '/var/log/pm2/fastify-error.log',
out_file: '/var/log/pm2/fastify-out.log',
log_date_format: 'YYYY-MM-DD HH:mm:ss Z',
merge_logs: true,
watch: false,
max_restarts: 10,
restart_delay: 4000
}]
}Start with PM2
# Create log directory
sudo mkdir -p /var/log/pm2
sudo chown fastify:fastify /var/log/pm2
# Start application
pm2 start ecosystem.config.js --env production
pm2 save
pm2 startupPM2 Management Commands
| Command | Description |
|---|---|
| pm2 status | View all running processes |
| pm2 logs fastify-app | View application logs |
| pm2 restart fastify-app | Restart the application |
| pm2 reload fastify-app | Zero-downtime reload |
| pm2 monit | Real-time monitoring dashboard |
6
Nginx Reverse Proxy
Install Nginx
sudo apt install -y nginx/etc/nginx/sites-available/fastify
upstream fastify_backend {
server 127.0.0.1:3000;
keepalive 64;
}
server {
listen 80;
server_name yourdomain.com www.yourdomain.com;
# Redirect HTTP to HTTPS
location / {
return 301 https://$server_name$request_uri;
}
}
server {
listen 443 ssl http2;
server_name yourdomain.com www.yourdomain.com;
# SSL configuration (configured by Certbot)
ssl_certificate /etc/letsencrypt/live/yourdomain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/yourdomain.com/privkey.pem;
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:50m;
ssl_session_tickets off;
# Modern SSL configuration
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256;
ssl_prefer_server_ciphers off;
# HSTS
add_header Strict-Transport-Security "max-age=63072000" always;
# Gzip compression
gzip on;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_types text/plain text/css text/xml application/json application/javascript;
location / {
proxy_pass http://fastify_backend;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_cache_bypass $http_upgrade;
proxy_read_timeout 60s;
proxy_connect_timeout 60s;
}
# Health check endpoint (bypass rate limiting)
location /health {
proxy_pass http://fastify_backend;
proxy_http_version 1.1;
proxy_set_header Host $host;
access_log off;
}
}Enable configuration
sudo ln -s /etc/nginx/sites-available/fastify /etc/nginx/sites-enabled/
sudo rm /etc/nginx/sites-enabled/default
sudo nginx -t
sudo systemctl restart nginx7
SSL/TLS with Let's Encrypt
Install Certbot and obtain certificate
sudo apt install -y certbot python3-certbot-nginx
# Obtain SSL certificate
sudo certbot --nginx -d yourdomain.com -d www.yourdomain.com
# Verify auto-renewal
sudo systemctl status certbot.timer
sudo certbot renew --dry-run8
Security Hardening
SSH Hardening
/etc/ssh/sshd_config settings
PermitRootLogin no
PasswordAuthentication no
PubkeyAuthentication yes
MaxAuthTries 3
ClientAliveInterval 300
ClientAliveCountMax 2Apply and install Fail2Ban
sudo systemctl restart sshd
# Install Fail2Ban
sudo apt install -y fail2ban
sudo systemctl enable fail2ban
sudo systemctl start fail2banApplication Security Best Practices
- Use @fastify/helmet for security headers (already configured)
- Implement rate limiting with @fastify/rate-limit (already configured)
- Validate all input using JSON Schema
- Keep dependencies updated regularly
- Use environment variables for secrets
- Enable CORS with specific origins in production
9
Monitoring & Logging
PM2 monitoring commands
# Real-time dashboard
pm2 monit
# JSON status output
pm2 jlist
# Memory and CPU info
pm2 show fastify-appLog Rotation
/etc/logrotate.d/pm2-fastify
/var/log/pm2/*.log {
daily
rotate 14
compress
delaycompress
missingok
notifempty
}Performance Optimization
System tuning
# Increase file descriptor limits
echo "fastify soft nofile 65535" | sudo tee -a /etc/security/limits.conf
echo "fastify hard nofile 65535" | sudo tee -a /etc/security/limits.conf10
Troubleshooting
| Issue | Solution |
|---|---|
| Application won't start | Check logs: pm2 logs fastify-app |
| 502 Bad Gateway | Verify app is running: pm2 status |
| High memory usage | Adjust max_memory_restart in PM2 config |
| Slow response times | Check PM2 cluster instances and Nginx upstream |
| SSL certificate errors | Verify paths and run certbot renew |
Fastify Deployed Successfully!
You now have a production-ready Fastify application with SSL encryption, process management with automatic restarts, reverse proxy configuration, and security hardening. RamNode's reliable infrastructure combined with Fastify's exceptional performance provides an excellent foundation for building scalable web applications and APIs.
