Getting an app to run on a fresh VPS takes an afternoon. Keeping it safe, observable and recoverable takes a checklist. This playbook is that checklist for your own KVM VPS: the operating system baseline, secrets, the web gateway and TLS, process management, logs and metrics, backups and a short incident runbook. Each section links to a detailed guide where you need one.
Everything here needs root access, so it applies to a VPS or server you manage. On Domain India shared hosting (cPanel, DirectAdmin, Webuzo) the server configuration is managed for you and cannot be changed by customers. Domain India VPS plans are self-managed: these steps are yours to carry out.
Start from a supported OS, log in with SSH keys only as a sudo user, allow only ports 22, 80 and 443, and turn on automatic security updates. Keep secrets in a root-readable environment file loaded by systemd, put Nginx or Caddy in front of your app with Let's Encrypt and sensible security headers, and run each service under exactly one process manager. Ship logs and basic metrics from day one, copy backups off the server and test a restore, and write down the first five things to check when something breaks.
1. Operating system and access baseline
- Use a supported release.Ubuntu 24.04 LTS, Debian 12 or 13, or AlmaLinux or Rocky Linux 9 or later. Avoid CentOS and Ubuntu 20.04, which no longer get standard security updates.
- Update, then create a sudo user.Run the package upgrade, reboot if the kernel changed, and create a normal user with sudo rights.
- Keys only.Add an ed25519 public key for that user, then set
PermitRootLogin noandPasswordAuthentication noin the SSH configuration. Test a second login before you close the first session. - Firewall.Allow 22, 80 and 443 and deny everything else inbound, with ufw on Ubuntu or Debian or firewalld on AlmaLinux and Rocky Linux.
- Brute-force protection.Install fail2ban with the
sshdjail enabled. - Automatic security updates.
unattended-upgradeson Ubuntu or Debian,dnf-automaticon AlmaLinux or Rocky Linux. - Time.Keep chrony (or systemd-timesyncd) running and set the time zone, for example
sudo timedatectl set-timezone Asia/Kolkata.
The details, with commands for each distribution, are in essential security and optimisation tips for your VPS, the SSH hardening checklist and setting up a firewall on your VPS.
2. Secrets and configuration
- Keep configuration in an environment file such as
/etc/myapp/app.env, owned by root with permissions600, and load it with systemd'sEnvironmentFile=. Never commit it to Git or place it inside the web root. - Use separate files, databases and storage buckets for staging and production.
- If you want configuration in Git, encrypt it with a tool such as sops with age keys.
- Rotate a secret straight away when someone with access leaves or when it may have leaked, not only on a calendar.
3. Gateway, TLS and security headers
Put a reverse proxy in front of your app so it handles TLS, compression and static files. A simple rule: Caddy for one to a few services, because it obtains and renews Let's Encrypt certificates automatically with almost no configuration; Nginx when you need detailed caching, rate limits or fine control. The comparison, with full configurations, is in Nginx vs Caddy for app gateways.
A Caddy site with automatic HTTPS and baseline headers:
example.com {
encode zstd gzip
reverse_proxy 127.0.0.1:3000
header {
Strict-Transport-Security "max-age=31536000"
X-Content-Type-Options "nosniff"
Referrer-Policy "strict-origin-when-cross-origin"
Content-Security-Policy "frame-ancestors 'self'"
-Server
}
}Build a full Content-Security-Policy gradually, starting in report-only mode. Add includeSubDomains or preload to HSTS only when every subdomain serves HTTPS, because preload is hard to undo.
Behind Cloudflare or another CDN, trust the forwarded client IP only from the CDN's published address ranges, and keep that list current. For WebSockets through Nginx, pass the Upgrade and Connection headers and raise proxy_read_timeout for long-lived connections.
4. One process manager per service
Pick one supervisor per service and don't wrap one in another:
- Node.js: systemd, or PM2 if you want its clustering. Not both.
- Python: Gunicorn (with Uvicorn workers for async apps) under systemd.
- Go or Rust: the single binary under systemd, with graceful shutdown on SIGTERM.
- Anything in containers: Docker or Podman with a restart policy.
A systemd unit with basic sandboxing:
[Unit]
Description=My app
After=network-online.target
Wants=network-online.target
[Service]
User=app
WorkingDirectory=/srv/myapp
EnvironmentFile=/etc/myapp/app.env
ExecStart=/usr/bin/node server.js
Restart=on-failure
RestartSec=3
NoNewPrivileges=true
ProtectSystem=full
PrivateTmp=true
[Install]
WantedBy=multi-user.targetEnable it with sudo systemctl enable --now myapp and follow its log with journalctl -u myapp -f. For a full walk-through per stack, see from zero to production: VPS setup for popular stacks.
5. Logs, metrics and alerts
- Logs: write structured (JSON) logs from your app, let journald or logrotate cap their size, and ship them somewhere central if you run more than one server.
- Metrics: node_exporter with Prometheus and Grafana covers CPU, memory, disk and network; add your app's own metrics as you grow.
- Alerts: at minimum, alert on disk above 85%, a service that keeps restarting, and a certificate that expires within 14 days.
- Outside checks: use an external uptime monitor, because a server cannot report its own outage.
A single-VPS setup is covered in production observability with Prometheus, Grafana and Loki.
6. Backups and disaster recovery
Follow the 3-2-1 rule: three copies, on two kinds of storage, one of them off the server. Use the right tool for each database (pg_dump or pgBackRest for PostgreSQL, mysqldump or Percona XtraBackup for MySQL and MariaDB, mongodump for MongoDB), plus your uploaded files and configuration.
Restore to a spare server or a local machine at least once a month and time it. Write down how much data you can afford to lose and how long you can be down, and check that your schedule meets both. Snapshots of the same VPS are useful, but they are not a substitute for an off-server copy.
Step-by-step off-site backups are in automated backups with cron and rclone and VPS backups to Amazon S3.
7. Performance quick wins
- Turn on HTTP/2 and keep-alive at the proxy, and compress text responses (gzip everywhere; zstd or Brotli where your proxy supports it).
- Give static assets content-hashed file names and long
Cache-Controllifetimes. - Add database indexes early and read the slow-query log before you tune anything else.
- Keep caches and queues (Redis, RabbitMQ) on their own instances when they matter, with persistence settings chosen deliberately.
- Measure before and after each change; most gains come from caching and indexes, not kernel tuning.
8. Runbook: the first five minutes
When something breaks, check these in order and write down what you find:
systemctl --failed # services that crashed
journalctl -p err -b --no-pager | tail -50
df -h && free -m # full disk or no memory
curl -sI https://example.com # does the site answer, and with what?
echo | openssl s_client -connect example.com:443 -servername example.com 2>/dev/null | openssl x509 -noout -enddateKeep a documented rollback (the previous release tag or container image), and after any incident write a short review with actions and owners.
Reboot with sudo reboot when you need to. Running poweroff or shutdown -h leaves the VPS switched off, and you will need a support ticket to start it again.
9. Data protection
If your app stores personal data of people in India, read up on the Digital Personal Data Protection Act, 2023: collect only what you need, keep a retention schedule and a way to erase data on request, and encrypt sensitive fields at rest. This is general information, not legal advice. Know where your data is stored: the live VPS page lists Domain India VPS servers as located in Germany, so check what that means for your users and your contracts.
10. Running this on a Domain India VPS
Domain India VPS plans use KVM virtualization with NVMe storage and full root access, and they are self-managed. At checkout you can choose no control panel, CyberPanel, Webuzo or DirectAdmin; cPanel is not offered on a VPS. There is no VPS control page in the client area: reboot from inside over SSH, and for a power start or stop, reinstall, console access, resize or snapshot restore, open a ticket and support will do it. Ask support before you rely on outbound mail on port 25 or a custom reverse DNS (PTR) record.
If you would rather not run a server at all, the App Platform builds and runs Node.js apps automatically (other stacks with a Dockerfile) and includes PostgreSQL and SSL.
Frequently asked questions
What should I do first on a new VPS?
Update the operating system, create a sudo user, add an SSH key, turn off root and password login over SSH, allow only ports 22, 80 and 443 through the firewall, and turn on automatic security updates.
Should I use Nginx or Caddy in front of my app?
Caddy for one to a few services, because it handles Let's Encrypt certificates automatically with little configuration. Nginx when you need detailed caching, rate limiting or fine-grained control.
Should I run my Node.js app with PM2 or systemd?
Either works, but use only one. systemd is built into the OS and needs no extra software; PM2 adds clustering and its own tooling. Running PM2 under a separate systemd service for the same app is fine, but don't manage the same process from both.
Are VPS snapshots enough as a backup?
No. Snapshots live with the same provider and server. Keep an off-server copy of your databases and files as well, and test a restore regularly.
Does Domain India manage security on my VPS?
No. Domain India VPS plans are self-managed, so updates, firewall rules, backups and the software you install are your responsibility. Shared hosting keeps server security on our side.
How do I restart a Domain India VPS?
Log in over SSH and run sudo reboot. For a power start or stop, reinstall or console access, open a support ticket. Don't run poweroff from inside, because the VPS stays off until support starts it.
Can I apply this playbook on shared hosting?
No. It needs root access. On shared hosting the server configuration is managed for you; use a VPS for these steps.
Ready to go to production? Compare VPS plans, consider the App Platform if you'd rather not manage a server, or open a support ticket with questions about your setup.
KVM virtualization, NVMe storage and full root access, with your choice of no panel, CyberPanel, Webuzo or DirectAdmin.
See VPS plans