Web Server Guide

    Caddy Web Server

    Deploy Caddy, the modern web server with automatic HTTPS, on RamNode VPS. Zero-config TLS certificates, HTTP/3 support, and intuitive configuration.

    Ubuntu/Debian
    Auto HTTPS
    ⏱️ 15-20 minutes

    Prerequisites & VPS Selection

    Small Sites

    • • 512MB RAM
    • • 1 vCPU
    • • Static sites

    Recommended

    • • 2GB RAM
    • • 2 vCPU
    • • Multiple sites

    High Traffic

    • • 4GB+ RAM
    • • 4 vCPU
    • • PHP + proxy

    💡 Tip: Caddy automatically obtains TLS certificates from Let's Encrypt. Ensure your domain's DNS A/AAAA records point to your server before starting Caddy.

    2

    Install Caddy

    Install Caddy from the official repository for the latest stable version:

    Install Caddy on Ubuntu/Debian
    # Install required packages
    sudo apt update
    sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https curl
    
    # Add Caddy GPG key
    curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg
    
    # Add Caddy repository
    curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | sudo tee /etc/apt/sources.list.d/caddy-stable.list
    
    # Install Caddy
    sudo apt update
    sudo apt install caddy
    Verify installation
    # Check Caddy version
    caddy version
    
    # Check service status
    sudo systemctl status caddy

    Configure the firewall to allow HTTP and HTTPS traffic:

    Configure firewall
    # Allow HTTP and HTTPS
    sudo ufw allow 80/tcp
    sudo ufw allow 443/tcp
    sudo ufw reload
    3

    Basic Configuration

    Caddy uses the Caddyfile for configuration, located at /etc/caddy/Caddyfile:

    Simple website configuration
    # /etc/caddy/Caddyfile
    
    example.com {
        root * /var/www/example.com
        file_server
    }
    Multiple sites with redirect
    # Site 1
    example.com {
        root * /var/www/example.com
        file_server
    }
    
    # Site 2
    blog.example.com {
        root * /var/www/blog
        file_server
    }
    
    # WWW redirect
    www.example.com {
        redir https://example.com{uri} permanent
    }
    Apply configuration
    # Validate configuration
    caddy validate --config /etc/caddy/Caddyfile
    
    # Format and reload (zero-downtime)
    caddy fmt --overwrite /etc/caddy/Caddyfile
    sudo systemctl reload caddy
    4

    Static File Server

    Serve static files with compression and custom error pages:

    Static site with compression
    example.com {
        root * /var/www/html
        file_server
        
        # Enable compression
        encode gzip zstd
        
        # Custom error pages
        handle_errors {
            @404 {
                expression {http.error.status_code} == 404
            }
            rewrite @404 /404.html
            file_server
        }
    }
    Single Page Application (SPA)
    example.com {
        root * /var/www/spa
        encode gzip zstd
        
        # Try files, fallback to index.html for SPA routing
        try_files {path} /index.html
        file_server
    }
    File downloads with directory listing
    files.example.com {
        root * /var/www/files
        file_server browse
        
        # Basic authentication for private directory
        basicauth /private/* {
            admin $2a$14$hashedpassword
        }
    }
    5

    Reverse Proxy

    Proxy requests to backend applications with automatic HTTPS:

    Basic reverse proxy
    # Proxy to local application
    app.example.com {
        reverse_proxy localhost:3000
    }
    
    # Proxy with custom headers
    api.example.com {
        reverse_proxy localhost:8080 {
            header_up Host {upstream_hostport}
            header_up X-Real-IP {remote_host}
            header_up X-Forwarded-For {remote_host}
            header_up X-Forwarded-Proto {scheme}
        }
    }
    Path-based routing
    example.com {
        # API requests to backend
        handle /api/* {
            reverse_proxy localhost:8080
        }
        
        # Static assets
        handle /static/* {
            root * /var/www/static
            file_server
        }
        
        # Default to frontend
        handle {
            reverse_proxy localhost:3000
        }
    }
    WebSocket support
    ws.example.com {
        reverse_proxy localhost:8080 {
            # WebSocket support is automatic
            # Optimize connection handling
            flush_interval -1
        }
    }
    6

    Load Balancing

    Distribute traffic across multiple backend servers:

    Round robin load balancing
    app.example.com {
        reverse_proxy 10.0.0.1:8080 10.0.0.2:8080 10.0.0.3:8080 {
            lb_policy round_robin
        }
    }
    Load balancing with health checks
    app.example.com {
        reverse_proxy {
            to 10.0.0.1:8080
            to 10.0.0.2:8080
            to 10.0.0.3:8080
            
            # Load balancing policy
            lb_policy least_conn
            
            # Active health checks
            health_uri /health
            health_interval 10s
            health_timeout 5s
            health_status 200
            
            # Passive health checks (circuit breaker)
            fail_duration 30s
            max_fails 3
            unhealthy_status 500 502 503 504
        }
    }

    Load Balancing Policies

    round_robin

    Distributes requests evenly across servers. Default policy.

    least_conn

    Sends to server with fewest active connections.

    ip_hash

    Routes based on client IP for session persistence.

    cookie

    Sticky sessions using a cookie.

    Sticky sessions with cookie
    app.example.com {
        reverse_proxy {
            to 10.0.0.1:8080
            to 10.0.0.2:8080
            
            lb_policy cookie {
                name sticky_session
                ttl 24h
            }
        }
    }
    7

    PHP Applications

    Configure Caddy to serve PHP applications via FastCGI:

    Install PHP-FPM
    sudo apt install php-fpm php-mysql php-curl php-gd php-mbstring php-xml php-zip
    Basic PHP configuration
    example.com {
        root * /var/www/html
        encode gzip
        
        php_fastcgi unix//run/php/php8.2-fpm.sock
        file_server
    }
    WordPress configuration
    wordpress.example.com {
        root * /var/www/wordpress
        encode gzip
        
        # PHP handling
        php_fastcgi unix//run/php/php8.2-fpm.sock
        file_server
        
        # Block access to sensitive files
        @blocked {
            path /xmlrpc.php
            path /.htaccess
            path /wp-config.php
        }
        respond @blocked 403
        
        # Enable pretty permalinks
        try_files {path} {path}/ /index.php?{query}
    }
    Laravel configuration
    laravel.example.com {
        root * /var/www/laravel/public
        encode gzip
        
        php_fastcgi unix//run/php/php8.2-fpm.sock
        file_server
        
        # Handle Laravel routing
        @notStatic {
            not path /build/* /vendor/* *.ico *.css *.js *.gif *.jpg *.jpeg *.png *.svg *.woff *.woff2
            file {
                try_files {path} {path}/
            }
            not
        }
        rewrite @notStatic /index.php
    }
    8

    Security Headers

    Add security headers to protect your site:

    Comprehensive security headers
    (security_headers) {
        header {
            # Enable HSTS
            Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
            
            # Prevent clickjacking
            X-Frame-Options "SAMEORIGIN"
            
            # Prevent MIME type sniffing
            X-Content-Type-Options "nosniff"
            
            # XSS protection
            X-XSS-Protection "1; mode=block"
            
            # Referrer policy
            Referrer-Policy "strict-origin-when-cross-origin"
            
            # Permissions policy
            Permissions-Policy "geolocation=(), microphone=(), camera=()"
            
            # Remove server header
            -Server
        }
    }
    
    example.com {
        import security_headers
        
        root * /var/www/html
        file_server
    }
    Rate limiting
    example.com {
        # Rate limit API endpoints
        @api path /api/*
        rate_limit @api {
            zone api_zone {
                key {remote_host}
                events 100
                window 1m
            }
        }
        
        reverse_proxy localhost:8080
    }
    9

    Logging

    Configure access logging for monitoring and debugging:

    JSON access logging
    example.com {
        log {
            output file /var/log/caddy/example.com.access.log {
                roll_size 100mb
                roll_keep 10
                roll_keep_for 720h
            }
            format json
        }
        
        root * /var/www/html
        file_server
    }
    Filtered logging (hide sensitive data)
    example.com {
        log {
            output file /var/log/caddy/access.log
            format filter {
                wrap json
                fields {
                    request>headers>Authorization delete
                    request>headers>Cookie delete
                }
            }
        }
        
        root * /var/www/html
        file_server
    }
    10

    JSON API Configuration

    Caddy supports JSON configuration via its admin API for programmatic management:

    Enable admin API
    # /etc/caddy/Caddyfile
    {
        admin localhost:2019
    }
    
    example.com {
        respond "Hello, World!"
    }
    Query and update configuration
    # Get current configuration
    curl localhost:2019/config/
    
    # Get specific app configuration
    curl localhost:2019/config/apps/http/
    
    # Update configuration
    curl -X POST localhost:2019/config/ \
        -H "Content-Type: application/json" \
        -d @config.json
    11

    Troubleshooting

    Common Issues

    Certificate Not Issuing
    • Verify DNS A/AAAA records point to your server
    • Ensure ports 80 and 443 are open and not blocked
    • Check if another service is using port 80 or 443
    502 Bad Gateway
    • Verify the upstream service is running
    • Check the upstream address and port
    • Ensure firewall allows internal connections
    Configuration Errors
    • Validate: caddy validate --config /etc/caddy/Caddyfile
    • Format: caddy fmt --overwrite /etc/caddy/Caddyfile
    Useful commands
    # View logs
    journalctl -u caddy -f
    
    # Test configuration
    caddy validate --config /etc/caddy/Caddyfile
    
    # Reload without downtime
    sudo systemctl reload caddy
    
    # Restart service
    sudo systemctl restart caddy
    
    # Check listening ports
    sudo ss -tlnp | grep caddy
    
    # Run in foreground for debugging
    caddy run --config /etc/caddy/Caddyfile
    Performance tuning
    {
        # Global options
        servers {
            protocol {
                experimental_http3
            }
        }
    }
    
    example.com {
        encode gzip zstd
        
        # Cache static assets
        @static {
            path *.css *.js *.ico *.gif *.jpg *.jpeg *.png *.svg *.woff *.woff2
        }
        header @static Cache-Control "public, max-age=31536000"
        
        reverse_proxy localhost:8080
    }

    Ready to Deploy Caddy?

    Get started with a RamNode Cloud VPS and have Caddy running with automatic HTTPS in minutes.