Skip to main content
    Back to all articles

    Self-Hosting Your Applications: A Complete Guide

    DevOps
    16 min read
    By Bahaj abderrazak
    Featured image for "Self-Hosting Your Applications: A Complete Guide"

    Self-hosting your applications offers unparalleled control, flexibility, and often, cost-effectiveness compared to managed services. This comprehensive guide will walk you through the essential steps to set up and manage your own web applications on a Virtual Private Server (VPS), leveraging Docker Compose for easy deployment and Nginx as a powerful reverse proxy.

    ---

    Why Self-Host?

    • Full Control: You dictate the environment, software versions, and security configurations.
    • Cost Savings: Often cheaper than comparable managed services, especially for multiple applications.
    • Learning Experience: Deepen your understanding of server management, networking, and DevOps.
    • Data Privacy: Keep your data on servers you control.

    ---

    Step 1: Choosing a VPS Provider

    Select a reliable VPS provider that fits your budget and performance needs. Popular options include:

    • DigitalOcean
    • Linode
    • Vultr
    • Hetzner Cloud
    • OVHcloud

    Start with a basic plan (e.g., 1 CPU, 1-2 GB RAM) and scale up as needed. Choose an Ubuntu Server LTS (Long Term Support) version for stability.

    ---

    Step 2: Initial Server Setup and Security

    After provisioning your VPS, immediately secure it.

    1. SSH Access and Root Login

    • Disable Root Login: Create a new user with sudo privileges and disable direct root SSH access.
    •         sudo adduser yourusername
              sudo usermod -aG sudo yourusername
              sudo nano /etc/ssh/sshd_config
              # Change PermitRootLogin to no
              # Change PasswordAuthentication to no (if using SSH keys)
              sudo systemctl restart sshd
    • SSH Key Authentication: Always use SSH keys for login; it's more secure than passwords.
    •         # On your local machine:
              ssh-keygen -t rsa -b 4096
              ssh-copy-id yourusername@your_vps_ip

    2. Firewall (UFW)

    Configure UFW (Uncomplicated Firewall) to allow only necessary traffic.

          sudo ufw allow OpenSSH
          sudo ufw allow 'Nginx Full' # We'll install Nginx later
          sudo ufw enable
          sudo ufw status verbose

    3. Update System

    Keep your system up-to-date.

          sudo apt update && sudo apt upgrade -y

    ---

    Step 3: Installing Docker and Docker Compose

    Docker will containerize your applications, and Docker Compose will manage multi-container applications.

          # Install Docker
          sudo apt install docker.io -y
          sudo systemctl start docker
          sudo systemctl enable docker
          sudo usermod -aG docker yourusername # Add your user to the docker group
          newgrp docker # Apply group changes
    
          # Install Docker Compose
          sudo apt install docker-compose -y
          # Verify installation
          docker --version
          docker-compose --version

    ---

    Step 4: Deploying Your Application with Docker Compose

    Create a directory for your application (e.g., /var/www/my-app) and place your docker-compose.yml file there.

    Example docker-compose.yml for a simple web app (e.g., a Node.js API with a database)

          version: '3.8'
    
          services:
            web:
              build: . # Build Dockerfile in current directory, or use image: your-image/name
              container_name: myapp_web
              restart: always
              environment:
                NODE_ENV: production
                DATABASE_URL: postgres://user:password@db:5432/mydb
              ports:
                - "3000:3000" # Expose internal app port, Nginx will proxy to this
              networks:
                - myapp_network
    
            db:
              image: postgres:13
              container_name: myapp_db
              restart: always
              environment:
                POSTGRES_USER: user
                POSTGRES_PASSWORD: password
                POSTGRES_DB: mydb
              volumes:
                - db_data:/var/lib/postgresql/data
              networks:
                - myapp_network
    
          volumes:
            db_data:
    
          networks:
            myapp_network:
              driver: bridge

    Navigate to your application directory and start the services:

          cd /var/www/my-app
          docker-compose up -d

    Your application should now be running internally on the specified port (e.g., port 3000 for the web service).

    ---

    Step 5: Setting up Nginx as a Reverse Proxy

    Nginx will handle incoming HTTP/HTTPS requests and forward them to your Docker containers.

    1. Install Nginx

          sudo apt install nginx -y
          sudo systemctl start nginx
          sudo systemctl enable nginx

    2. Configure Nginx for Your Application

    Create a new Nginx server block configuration file:

          sudo nano /etc/nginx/sites-available/my-app.conf

    Add the following content (replace your-domain.com and 3000 with your details):

          server {
              listen 80;
              listen [::]:80;
              server_name your-domain.com www.your-domain.com;
    
              location / {
                  proxy_pass http://localhost:3000; # Or http://172.17.0.1:3000 for Docker's default bridge
                  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;
              }
          }

    Enable the Nginx site and test the configuration:

          sudo ln -s /etc/nginx/sites-available/my-app.conf /etc/nginx/sites-enabled/
          sudo nginx -t
          sudo systemctl restart nginx

    Ensure your domain's DNS A record points to your VPS IP address. You should now be able to access your application via HTTP.

    ---

    Step 6: Securing with SSL (HTTPS) using Certbot

    HTTPS is essential for security. Certbot automates obtaining and renewing free SSL certificates from Let's Encrypt.

          sudo snap install core; sudo snap refresh core
          sudo snap install --classic certbot
          sudo ln -s /snap/bin/certbot /usr/bin/certbot
    
          sudo certbot --nginx -d your-domain.com -d www.your-domain.com

    Certbot will automatically modify your Nginx configuration, set up redirects from HTTP to HTTPS, and configure automatic renewals.

    ---

    Step 7: Monitoring and Logging

    • Basic Monitoring: Use htop for process monitoring, df -h for disk space, free -h for memory.
    • Docker Logs: docker-compose logs -f for real-time application logs.
    • Nginx Access/Error Logs: /var/log/nginx/access.log and /var/log/nginx/error.log.
    • Tools: For more advanced monitoring, consider self-hosting tools like Grafana with Prometheus, or using simple uptime monitoring services.

    ---

    Step 8: Backups

    Regular backups are critical.

    • Database Backups: Use pg_dump (PostgreSQL) or mysqldump (MySQL) to create scheduled database dumps.
    •         # Example for PostgreSQL
              sudo docker exec myapp_db pg_dump -U user mydb > /path/to/backups/mydb_$(date +%F).sql
    • Application Code Backups: Use rsync or simply ensure your code is always in a Git repository.
    • VPS Snapshots: Many VPS providers offer snapshot features for full server backups.
    • Offsite Storage: Store backups on a different server or cloud storage (e.g., S3, Backblaze B2).

    ---

    Step 9: Maintenance and Updates

    • Regular Updates: Periodically run sudo apt update && sudo apt upgrade -y to keep your OS updated.
    • Docker Image Updates: Keep your base Docker images updated.
    • Application Updates: Pull the latest code and restart your Docker containers.
    •         cd /var/www/my-app
              git pull origin main # Or your deployment method
              docker-compose down && docker-compose up -d

    ---

    Conclusion

    Self-hosting your applications on a VPS using Docker and Nginx provides a powerful, flexible, and cost-effective hosting solution. While it requires more hands-on management, the learning and control gained are invaluable. By following these steps, you'll be well-equipped to deploy, secure, and maintain your web applications efficiently.

    Tags

    Self-Hosting
    VPS
    Docker
    Nginx
    SSL
    Server Management