• HWIKI

    Build. Break. Explain.

    Understand Web Servers

    Alright kids, I'm going to explain how to deploy a real web server. I see way too much garbage on the internet, especially from people deploying things half-assed, copy-pasting busted tutorials without understanding a single thing running under the hood.

    We are going back to basics, laying down the concepts, and doing a clean installation on a Debian machine. Read carefully, I'm not going to repeat myself.

    1. The Concepts: Stop mixing everything up

    Before typing commands like monkeys, you need to understand the architecture.

    A Server vs A Desktop PC Fundamentally, it's the exact same hardware architecture (CPU, RAM, storage). The difference is the use case and the design. A PC is meant to be turned off, run a heavy graphical interface, and play your games. A server (physical or virtual machine) is designed for high availability: it runs 24/7, usually has no GUI (we manage everything via command line to save resources), and its components are often redundant.

    A Server (Hardware) vs A Service (Software) When people say "web server", they often mean the software (Apache, Nginx).

    • The machine (the piece of metal or the VM) hosts the OS (Debian).
    • The service (the daemon) is a background process running on this OS that "listens" on a specific network port (port 80 for HTTP, 443 for HTTPS) waiting for a client to talk to it.

    Where does this fit in the OSI model? The OSI model is the network bible. A software web server operates at the very top of the stack, on Layer 7 (Application). It speaks the HTTP protocol. But for your web page to reach the browser, it relies on Layer 4 (Transport) via TCP to ensure no part of the page gets lost in transit, and Layer 3 (Network) via IP to route packets across the internet.


    2. Installation (Debian Base)

    We are going with packaged software. No obscure compilation from source code, we use the official Debian repositories. That's what they are for, they are maintained, and they are stable. We will use Apache2 for the example, but the directory logic is identical for Nginx.

    bash
    # Update local package index
    apt update
    
    # Install the Apache web server
    apt install apache2 -y
    

    Once that's done crunching, your service is already running. But you need to understand how it is organized.


    3. Anatomy of the beast: Vital directories

    Everything happens in /etc/apache2/ (or /etc/nginx/). Debian uses a smart system of symbolic links to enable or disable things cleanly.

    • sites-available/: This is where you create your website configuration files (VirtualHosts). Everything in here "exists" but is not necessarily active.

    • sites-enabled/: This is where the actually running sites live. How does it work? We don't copy the file. We create a symbolic link from sites-available to sites-enabled (via the a2ensite command). If we want to take the site down, we delete the link (via a2dissite), and the original configuration file stays safe and sound.

    • conf-available/ and conf-enabled/: Same concept, but for global server configurations (security, charset, etc.), not for a specific site.

    • DocumentRoot: This is the directive in your configuration that tells the server: "The HTML/PHP files for this site are located in this physical folder.". By default, this is often /var/www/html/.

    • /var/log/apache2/: The folder of truth. If something crashes, you don't cry on forums, you read error.log. If you want to see who is visiting the site, you read access.log.


    4. Creating an example configuration (VirtualHost)

    Forget the default configuration. We are going to create a real configuration block for your domain. We will place it in /etc/apache2/sites-available/my-site.conf.

    The idea of a VirtualHost is to tell the server how to react when it is called with a specific domain name. And in 2026, we do HTTPS (port 443), so we need SSL.

    apache
    # Configuration for the secure site
    <VirtualHost *:443>
        # Define the primary domain name and any alias
        ServerName www.example.com
        ServerAlias example.com
    
        # Define the physical directory of the website
        DocumentRoot /var/www/my-site/
    
        # SSL Configuration
        SSLEngine on
        SSLCertificateFile /etc/ssl/certs/my-site-cert.pem
        SSLCertificateKeyFile /etc/ssl/private/my-site-key.pem
    
        # Isolated log files for this specific site
        ErrorLog ${APACHE_LOG_DIR}/my-site_error.log
        CustomLog ${APACHE_LOG_DIR}/my-site_access.log combined
    </VirtualHost>
    

    Note on SSL: For the SSLEngine directives to work, the Apache SSL module must be enabled. The server won't guess it on its own. By the way, if you want to know how to generate clean certificates instead of throwing in self-signed junk that screams errors in the browser, read our guide on Automated SSL Certificate Management.

    Now, let's apply all this cleanly with a few commands:

    bash
    # Enable the SSL module for Apache
    a2enmod ssl
    
    # Enable our newly created site configuration
    a2ensite my-site.conf
    
    # Disable the ugly default configuration
    a2dissite 000-default.conf
    
    # ALWAYS test the syntax before restarting the service
    apache2ctl configtest
    
    # If the output says "Syntax OK", reload the service
    systemctl reload apache2
    
    
    

    5. Permissions (The thing you screw up all the time)

    If your browser shows a "403 Forbidden" error on your new domain, 99% of the time it is a Linux permissions issue on your DocumentRoot. The web service runs under the www-data user. If it doesn't have permission to read your files, it cannot send them to the client.

    Quick Reminder: Linux Permissions On Linux, permissions are defined by numbers that you have to add up.

    • r (Read - 4): Read permission.
    • w (Write - 2): Write/modify permission.
    • x (Execute - 1): Execute permission (or permission to traverse a directory).

    To get the final permission digit, you just add these values together. You do this calculation for three distinct entities in this exact order: User (owner), Group, and Others (the rest of the world).

    Let's take the chmod command as an example. If you want the User to have read and write access, you add 4 (Read) + 2 (Write) = 6. If you only want the Group and Others to read, that is just a 4.

    bash
    # Give read/write to owner (6), read-only to group (4) and others (4)
    chmod 644 /var/www/my-site/index.html
    

    Generally, for a web directory, we make sure folders are set to 755 (User gets 4+2+1=7, Group and Others get 4+1=5) and files are set to 644, with www-data assigned as the owner and group.


    6. A minimum of security

    We don't expose a naked server to the internet. There are two immediate things to do.

    Stop leaking info

    By default, the server shouts its exact version and the OS used to anyone listening. That is a blessing for automated scripts looking for vulnerabilities. We are going to shut that down.

    apache
    # Edit /etc/apache2/conf-available/security.conf
    
    # Hide server version and OS details in HTTP headers
    ServerTokens Prod
    
    # Disable the server signature on error pages
    ServerSignature Off
    

    Reload the service with a systemctl reload apache2.

    The Firewall (UFW)

    Opening a server without a firewall is criminal. We are going to use UFW (Uncomplicated Firewall).

    bash
    # Install UFW
    apt install ufw -y
    
    # Deny all incoming traffic by default
    ufw default deny incoming
    
    # Allow all outgoing traffic
    ufw default allow outgoing
    
    # NEVER FORGET THIS: Allow SSH before enabling the firewall
    ufw allow ssh
    
    # Allow HTTP and HTTPS traffic for the web server
    ufw allow http
    ufw allow https
    
    # Enable the firewall rules
    ufw enable
    

    There you go. You have a clean machine that knows what it's doing, with a properly configured VirtualHost, planned certificates, and that doesn't let the whole internet in on just any port. If you master this, you've done the heavy lifting.


    Made by h0ag