Asia/Kolkata
Posts

Cloud & Self-Hosting Guide

February 12, 2025
Deploying your own applications can feel like a maze when you start out. The industry defaults to AWS, GCP, and Kubernetes for everything. While this makes sense for enterprise workloads, it is overkill for a developer hosting personal projects, utility scripts, or hobby databases. Commercial cloud providers get expensive fast. Self-hosting, whether on a cheap VPS or an old PC in your closet, gives you complete control over your data, teaches you real systems administration, and keeps your monthly bill predictable. Here is a practical guide to how I set up my own deployments, from choosing where to host all the way to securing and monitoring the services. You don't need a large cluster to run a web app. Pick your setup based on what you actually need:
  • Cheap VPS (Hetzner, DigitalOcean, Linode): The best starting point for personal projects. For $4 to $6 a month, you get a dedicated public IP, solid uptime, and a clean Linux OS (Ubuntu Server or Debian).
  • Home Lab (Raspberry Pi, mini PC, old laptop): Good for media servers, local database backups, and private tools. It runs for free (aside from power costs) and has large storage potential, though you need to manage dynamic DNS and home router port forwarding safely.
  • Hyperscalers (AWS, Azure, GCP): Overkill for basic hosting. Use them only if you specifically want to learn their services, like AWS S3 or GCP's serverless tools. Otherwise, the pricing models make it easy to rack up unexpected bills.
Installing services directly on your host machine causes dependency conflicts. If you upgrade Node.js for one app, you can break three others. Docker fixes this. By containerizing your applications, you package the code with its exact environment. Rather than writing verbose docker run commands, use Docker Compose. It lets you define your entire multi-container stack in a single docker-compose.yml file. A basic template for running a Node.js web app behind an Nginx reverse proxy: Running docker-compose up -d starts your app and the web server in the background. If the server reboots, Docker restarts your containers automatically. Never expose a fresh server to the public internet without hardening it first. Botnets scan public IP ranges constantly.
  • SSH Keys Only: Disable password-based authentication. Edit /etc/ssh/sshd_config, set PasswordAuthentication no, and add your public SSH key to ~/.ssh/authorized_keys.
  • Set Up a Firewall: Limit incoming traffic. If you use Ubuntu, ufw makes this straightforward:
  • Automate SSL Certificates: Use Certbot (Let's Encrypt) to generate free HTTPS certificates. Nginx or Caddy can handle automatic renewals.
  • Install Fail2ban: This service monitors log files for repeated failed login attempts and temporarily bans those IP addresses at the firewall level.
If a container crashes or a disk fills up, you want to know before your users do.
  • Status Checks: For a simple setup, a cron job that pings your site and sends a Telegram or Discord webhook on a non-200 response works fine.
  • Log Management: Docker writes logs to JSON files on the host. Set log rotation limits in /etc/docker/daemon.json to prevent storage from filling with debug logs:
  • Backups: Code lives in Git, but databases and user uploads need active backup plans. A nightly cron job that runs pg_dump (for PostgreSQL) or copies raw mount directories, compresses them, and uploads them to a cloud bucket (Backblaze B2 or AWS S3) is the baseline.
If you host from home, avoid exposing your home IP address directly. Instead, run a lightweight VPS as a gateway and set up a secure tunnel (WireGuard or Tailscale) between your VPS and your home machine. Cloudflare Tunnels can also route traffic directly to your local containers without opening ports on your home router.