Skip to content

Deploying Apache HTTP Server

Introduction

Apache HTTP Server (commonly known as Apache or httpd) is the world’s most widely used open-source web server software, powering over 30% of all websites globally. Developed and maintained by the Apache Software Foundation, Apache HTTP Server has been the backbone of the internet since 1995, offering exceptional stability, security, and flexibility for serving web content.

Apache HTTP Server excels at serving static content, hosting dynamic applications through modules like mod_php and mod_wsgi, acting as a reverse proxy, load balancing traffic, and providing robust SSL/TLS encryption. Its modular architecture allows you to enable only the features you need, making it both lightweight and powerful.

This guide walks you through deploying Apache HTTP Server on Klutch.sh using a Dockerfile. You’ll learn how to configure virtual hosts, set up SSL/TLS, implement reverse proxy configurations, optimize performance, and follow production best practices.


What You’ll Learn

  • How to deploy Apache HTTP Server with a Dockerfile on Klutch.sh
  • Configuring virtual hosts and custom httpd.conf settings
  • Setting up reverse proxy for backend applications
  • Optimizing Apache for performance and security
  • Implementing persistent storage for logs and content
  • Best practices for production web hosting

Prerequisites

Before you begin, ensure you have:

  • A Klutch.sh account
  • A GitHub repository for your web project
  • Basic understanding of web servers and HTTP
  • (Optional) Static website files or backend application to proxy

Understanding Apache HTTP Server

Apache HTTP Server consists of several key components:

  • Core Server: The main httpd process that handles HTTP requests
  • Multi-Processing Modules (MPMs): Controls how Apache handles concurrent requests (prefork, worker, event)
  • Modules: Extend functionality (mod_ssl, mod_rewrite, mod_proxy, mod_php, etc.)
  • Configuration Files: httpd.conf and virtual host configurations
  • Document Root: Directory where website files are served from (default: /usr/local/apache2/htdocs)

The server listens on port 80 for HTTP traffic by default (and port 443 for HTTPS).


Step 1: Prepare Your GitHub Repository

    1. Create a new GitHub repository or use an existing one for your web project.

    2. Create a basic project structure:

      my-apache-project/
      ├── Dockerfile
      ├── httpd.conf
      ├── public/
      │ ├── index.html
      │ ├── css/
      │ │ └── style.css
      │ └── js/
      │ └── app.js
      └── .dockerignore
    3. Create a sample index.html in the public/ directory:

      <!DOCTYPE html>
      <html lang="en">
      <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>Welcome to Apache on Klutch.sh</title>
      <link rel="stylesheet" href="css/style.css">
      </head>
      <body>
      <header>
      <h1>🚀 Apache HTTP Server on Klutch.sh</h1>
      </header>
      <main>
      <section class="hero">
      <h2>Your Web Server is Running!</h2>
      <p>Apache HTTP Server has been successfully deployed on Klutch.sh.</p>
      </section>
      <section class="features">
      <h3>Features</h3>
      <ul>
      <li>High Performance Static File Serving</li>
      <li>Reverse Proxy Support</li>
      <li>SSL/TLS Encryption</li>
      <li>URL Rewriting</li>
      <li>Gzip Compression</li>
      </ul>
      </section>
      <section class="info">
      <h3>Server Information</h3>
      <p>Server: Apache/2.4</p>
      <p>Deployment: Klutch.sh</p>
      </section>
      </main>
      <footer>
      <p>&copy; 2024 Deployed with ❤️ on Klutch.sh</p>
      </footer>
      <script src="js/app.js"></script>
      </body>
      </html>
    4. Create a simple css/style.css:

      * {
      margin: 0;
      padding: 0;
      box-sizing: border-box;
      }
      body {
      font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, sans-serif;
      line-height: 1.6;
      color: #333;
      background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
      min-height: 100vh;
      }
      header {
      background: rgba(255, 255, 255, 0.1);
      padding: 2rem;
      text-align: center;
      color: white;
      }
      main {
      max-width: 800px;
      margin: 2rem auto;
      padding: 2rem;
      background: white;
      border-radius: 10px;
      box-shadow: 0 10px 40px rgba(0, 0, 0, 0.2);
      }
      section {
      margin-bottom: 2rem;
      }
      .hero {
      text-align: center;
      padding: 2rem 0;
      border-bottom: 1px solid #eee;
      }
      .hero h2 {
      color: #667eea;
      margin-bottom: 1rem;
      }
      h3 {
      color: #333;
      margin-bottom: 1rem;
      }
      ul {
      list-style: none;
      padding-left: 0;
      }
      ul li {
      padding: 0.5rem 0;
      padding-left: 1.5rem;
      position: relative;
      }
      ul li::before {
      content: "";
      color: #667eea;
      position: absolute;
      left: 0;
      }
      footer {
      text-align: center;
      padding: 2rem;
      color: white;
      }
    5. Create a js/app.js:

      document.addEventListener('DOMContentLoaded', function() {
      console.log('Apache HTTP Server running on Klutch.sh!');
      // Add current timestamp to info section
      const infoSection = document.querySelector('.info');
      if (infoSection) {
      const timestamp = document.createElement('p');
      timestamp.textContent = `Page loaded: ${new Date().toLocaleString()}`;
      infoSection.appendChild(timestamp);
      }
      });

Step 2: Create the Dockerfile

Klutch.sh automatically detects a Dockerfile in your repository’s root directory and uses it to build your application.

    1. Create a Dockerfile in your project root:

      # Use the official Apache HTTP Server image
      FROM httpd:2.4-alpine
      # Install additional tools (optional)
      RUN apk add --no-cache curl
      # Remove default content
      RUN rm -rf /usr/local/apache2/htdocs/*
      # Copy custom Apache configuration
      COPY httpd.conf /usr/local/apache2/conf/httpd.conf
      # Copy website files to document root
      COPY public/ /usr/local/apache2/htdocs/
      # Set proper permissions
      RUN chown -R www-data:www-data /usr/local/apache2/htdocs/ || true
      RUN chmod -R 755 /usr/local/apache2/htdocs/
      # Expose port 80
      EXPOSE 80
      # Health check
      HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
      CMD curl -f http://localhost/ || exit 1
      # Start Apache in foreground
      CMD ["httpd-foreground"]
    2. Create a custom httpd.conf for optimized configuration:

      # Apache HTTP Server Configuration for Klutch.sh
      ServerRoot "/usr/local/apache2"
      # Listen on port 80
      Listen 80
      # Load essential modules
      LoadModule mpm_event_module modules/mod_mpm_event.so
      LoadModule authn_file_module modules/mod_authn_file.so
      LoadModule authn_core_module modules/mod_authn_core.so
      LoadModule authz_host_module modules/mod_authz_host.so
      LoadModule authz_groupfile_module modules/mod_authz_groupfile.so
      LoadModule authz_user_module modules/mod_authz_user.so
      LoadModule authz_core_module modules/mod_authz_core.so
      LoadModule access_compat_module modules/mod_access_compat.so
      LoadModule auth_basic_module modules/mod_auth_basic.so
      LoadModule reqtimeout_module modules/mod_reqtimeout.so
      LoadModule filter_module modules/mod_filter.so
      LoadModule mime_module modules/mod_mime.so
      LoadModule log_config_module modules/mod_log_config.so
      LoadModule env_module modules/mod_env.so
      LoadModule headers_module modules/mod_headers.so
      LoadModule setenvif_module modules/mod_setenvif.so
      LoadModule version_module modules/mod_version.so
      LoadModule unixd_module modules/mod_unixd.so
      LoadModule status_module modules/mod_status.so
      LoadModule autoindex_module modules/mod_autoindex.so
      LoadModule dir_module modules/mod_dir.so
      LoadModule alias_module modules/mod_alias.so
      LoadModule rewrite_module modules/mod_rewrite.so
      LoadModule deflate_module modules/mod_deflate.so
      LoadModule expires_module modules/mod_expires.so
      # Server identity
      ServerAdmin webmaster@localhost
      ServerName localhost
      # Document root
      DocumentRoot "/usr/local/apache2/htdocs"
      # Directory configuration
      <Directory />
      AllowOverride none
      Require all denied
      </Directory>
      <Directory "/usr/local/apache2/htdocs">
      Options Indexes FollowSymLinks
      AllowOverride All
      Require all granted
      </Directory>
      # Default file
      <IfModule dir_module>
      DirectoryIndex index.html index.htm
      </IfModule>
      # Deny access to .htaccess files
      <Files ".ht*">
      Require all denied
      </Files>
      # Error log
      ErrorLog /proc/self/fd/2
      LogLevel warn
      # Access log format
      <IfModule log_config_module>
      LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
      LogFormat "%h %l %u %t \"%r\" %>s %b" common
      CustomLog /proc/self/fd/1 combined
      </IfModule>
      # MIME types
      <IfModule mime_module>
      TypesConfig conf/mime.types
      AddType application/x-compress .Z
      AddType application/x-gzip .gz .tgz
      AddType text/html .shtml
      AddType application/javascript .js
      AddType text/css .css
      AddType image/svg+xml .svg .svgz
      AddType application/json .json
      AddType font/woff .woff
      AddType font/woff2 .woff2
      </IfModule>
      # Enable gzip compression
      <IfModule deflate_module>
      SetOutputFilter DEFLATE
      DeflateCompressionLevel 6
      # Compress text files
      AddOutputFilterByType DEFLATE text/html text/plain text/xml
      AddOutputFilterByType DEFLATE text/css text/javascript
      AddOutputFilterByType DEFLATE application/javascript application/json
      AddOutputFilterByType DEFLATE application/xml application/xhtml+xml
      AddOutputFilterByType DEFLATE image/svg+xml
      # Don't compress images and other binary files
      SetEnvIfNoCase Request_URI \.(?:gif|jpe?g|png|ico|webp)$ no-gzip
      SetEnvIfNoCase Request_URI \.(?:exe|t?gz|zip|bz2|sit|rar)$ no-gzip
      SetEnvIfNoCase Request_URI \.(?:pdf|mov|avi|mp3|mp4|rm)$ no-gzip
      </IfModule>
      # Cache control for static assets
      <IfModule expires_module>
      ExpiresActive On
      # Default expiration
      ExpiresDefault "access plus 1 month"
      # HTML - no cache
      ExpiresByType text/html "access plus 0 seconds"
      # CSS and JavaScript - 1 week
      ExpiresByType text/css "access plus 1 week"
      ExpiresByType application/javascript "access plus 1 week"
      # Images - 1 month
      ExpiresByType image/jpeg "access plus 1 month"
      ExpiresByType image/png "access plus 1 month"
      ExpiresByType image/gif "access plus 1 month"
      ExpiresByType image/svg+xml "access plus 1 month"
      ExpiresByType image/webp "access plus 1 month"
      ExpiresByType image/x-icon "access plus 1 year"
      # Fonts - 1 year
      ExpiresByType font/woff "access plus 1 year"
      ExpiresByType font/woff2 "access plus 1 year"
      </IfModule>
      # Security headers
      <IfModule headers_module>
      # Prevent MIME type sniffing
      Header always set X-Content-Type-Options "nosniff"
      # XSS Protection
      Header always set X-XSS-Protection "1; mode=block"
      # Clickjacking protection
      Header always set X-Frame-Options "SAMEORIGIN"
      # Referrer policy
      Header always set Referrer-Policy "strict-origin-when-cross-origin"
      # Remove server version
      Header always unset X-Powered-By
      # Cache control for static files
      <FilesMatch "\.(ico|pdf|flv|jpg|jpeg|png|gif|webp|js|css|swf|woff|woff2)$">
      Header set Cache-Control "max-age=2592000, public"
      </FilesMatch>
      </IfModule>
      # Enable URL rewriting
      <IfModule rewrite_module>
      RewriteEngine On
      </IfModule>
      # Server status (for health checks)
      <Location "/server-status">
      SetHandler server-status
      Require local
      </Location>
      # Hide server version
      ServerTokens Prod
      ServerSignature Off
      # Timeout settings
      Timeout 60
      KeepAlive On
      MaxKeepAliveRequests 100
      KeepAliveTimeout 5
    3. Create a .dockerignore file:

      .git
      .gitignore
      README.md
      .DS_Store
      *.log
      node_modules/
      .env
      .env.local

Step 3: Deploy to Klutch.sh

    1. Commit and push your changes to GitHub:

      Terminal window
      git add .
      git commit -m "Add Apache HTTP Server configuration for Klutch.sh"
      git push origin main
    2. Log in to Klutch.sh and navigate to the dashboard.

    3. Create a new project (if you don’t have one already) by clicking “New Project”.

    4. Create a new app within your project:

      • Click “New App”
      • Select your GitHub repository
      • Choose the branch to deploy (e.g., main)
      • Klutch.sh will automatically detect your Dockerfile
    5. Configure the app settings:

      • Traffic Type: Select HTTP
      • Internal Port: Set to 80 (Apache’s default HTTP port)
    6. Click “Create” to deploy your Apache HTTP Server.

    Once deployed, your web server will be accessible at a URL like https://example-app.klutch.sh.


Step 4: Configure Persistent Storage (Optional)

If you need to persist logs or allow content updates without redeployment, configure persistent volumes.

    1. In your app settings, navigate to the “Volumes” section.

    2. Add persistent volumes for your needs:

      For access logs:

      • Mount Path: /usr/local/apache2/logs
      • Size: 5 GB

      For custom content (if serving dynamic/uploaded content):

      • Mount Path: /usr/local/apache2/htdocs/uploads
      • Size: 10 GB (adjust based on your needs)
    3. Save the configuration and redeploy.

For more details on managing storage, see the Volumes Guide.


Advanced Configuration

Reverse Proxy Setup

Apache can act as a reverse proxy to forward requests to backend applications. Update your Dockerfile and configuration:

Enhanced Dockerfile with proxy modules:

FROM httpd:2.4-alpine
RUN apk add --no-cache curl
# Enable proxy modules
RUN sed -i \
-e 's/^#\(LoadModule proxy_module modules\/mod_proxy.so\)/\1/' \
-e 's/^#\(LoadModule proxy_http_module modules\/mod_proxy_http.so\)/\1/' \
-e 's/^#\(LoadModule proxy_wstunnel_module modules\/mod_proxy_wstunnel.so\)/\1/' \
/usr/local/apache2/conf/httpd.conf
COPY httpd.conf /usr/local/apache2/conf/httpd.conf
COPY public/ /usr/local/apache2/htdocs/
EXPOSE 80
CMD ["httpd-foreground"]

Add to httpd.conf for reverse proxy:

# Load proxy modules (add near other LoadModule directives)
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_http_module modules/mod_proxy_http.so
LoadModule proxy_wstunnel_module modules/mod_proxy_wstunnel.so
# Reverse proxy configuration
<VirtualHost *:80>
ServerName example-app.klutch.sh
# Proxy settings
ProxyPreserveHost On
ProxyRequests Off
# Proxy API requests to backend
ProxyPass /api http://your-backend-app.klutch.sh:8000/api
ProxyPassReverse /api http://your-backend-app.klutch.sh:8000/api
# WebSocket support
RewriteEngine On
RewriteCond %{HTTP:Upgrade} websocket [NC]
RewriteCond %{HTTP:Connection} upgrade [NC]
RewriteRule ^/ws/(.*) ws://your-backend-app.klutch.sh:8000/ws/$1 [P,L]
# Serve static files directly
DocumentRoot "/usr/local/apache2/htdocs"
<Directory "/usr/local/apache2/htdocs">
Options Indexes FollowSymLinks
AllowOverride All
Require all granted
</Directory>
</VirtualHost>

Single Page Application (SPA) Configuration

For React, Vue, or Angular apps that use client-side routing:

Add to httpd.conf:

<Directory "/usr/local/apache2/htdocs">
Options Indexes FollowSymLinks
AllowOverride All
Require all granted
# Enable URL rewriting for SPA
RewriteEngine On
RewriteBase /
# Don't rewrite files or directories
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
# Rewrite everything else to index.html
RewriteRule ^(.*)$ /index.html [L,QSA]
</Directory>

PHP Support

To serve PHP applications, use a PHP-enabled Apache image:

FROM php:8.2-apache
# Enable Apache modules
RUN a2enmod rewrite headers expires deflate
# Install PHP extensions
RUN docker-php-ext-install pdo pdo_mysql mysqli
# Copy Apache configuration
COPY apache.conf /etc/apache2/sites-available/000-default.conf
# Copy application files
COPY public/ /var/www/html/
# Set permissions
RUN chown -R www-data:www-data /var/www/html
EXPOSE 80
CMD ["apache2-foreground"]

apache.conf for PHP:

<VirtualHost *:80>
ServerAdmin webmaster@localhost
DocumentRoot /var/www/html
<Directory /var/www/html>
Options Indexes FollowSymLinks
AllowOverride All
Require all granted
</Directory>
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>

Environment Variables

While Apache HTTP Server doesn’t require many environment variables, you can use them for dynamic configuration:

In the Klutch.sh dashboard:

Terminal window
# Server name (optional - for logging)
SERVER_NAME=example-app.klutch.sh
# Document root (if customizing)
DOCUMENT_ROOT=/usr/local/apache2/htdocs
# Max clients (for tuning)
MAX_REQUEST_WORKERS=150

Using environment variables in httpd.conf:

# Reference environment variables
ServerName ${SERVER_NAME}

Set defaults in Dockerfile:

ENV SERVER_NAME=localhost
ENV DOCUMENT_ROOT=/usr/local/apache2/htdocs

Performance Tuning

MPM Event Configuration

For high-traffic sites, tune the MPM event module. Add to httpd.conf:

<IfModule mpm_event_module>
StartServers 3
MinSpareThreads 75
MaxSpareThreads 250
ThreadsPerChild 25
MaxRequestWorkers 400
MaxConnectionsPerChild 0
</IfModule>

Enable HTTP/2

For better performance with modern browsers:

# Add to Dockerfile
RUN sed -i \
-e 's/^#\(LoadModule http2_module modules\/mod_http2.so\)/\1/' \
/usr/local/apache2/conf/httpd.conf
# Add to httpd.conf
LoadModule http2_module modules/mod_http2.so
Protocols h2 h2c http/1.1

Security Best Practices

    1. Hide server information:

      ServerTokens Prod
      ServerSignature Off
    2. Prevent directory listing:

      <Directory "/usr/local/apache2/htdocs">
      Options -Indexes
      </Directory>
    3. Disable unnecessary methods:

      <Directory "/usr/local/apache2/htdocs">
      <LimitExcept GET POST HEAD>
      Require all denied
      </LimitExcept>
      </Directory>
    4. Set Content Security Policy:

      Header always set Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self';"
    5. Enable HSTS (Strict Transport Security):

      Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"
    6. Protect sensitive files:

      # Block access to hidden files
      <FilesMatch "^\.">
      Require all denied
      </FilesMatch>
      # Block access to backup files
      <FilesMatch "\.(bak|config|sql|fla|psd|ini|log|sh|inc|swp|dist)$">
      Require all denied
      </FilesMatch>

Monitoring and Health Checks

Server Status Module

Enable server status for monitoring:

<Location "/server-status">
SetHandler server-status
Require ip 127.0.0.1
</Location>
# Extended status for more details
ExtendedStatus On

Custom Health Check Endpoint

Create a simple health check page at public/health:

<!DOCTYPE html>
<html>
<head><title>Health Check</title></head>
<body>OK</body>
</html>

Configure in httpd.conf:

<Location "/health">
SetHandler none
Require all granted
</Location>

Troubleshooting

Common Issues

Container won’t start:

  • Check Klutch.sh logs for error messages
  • Verify httpd.conf syntax: httpd -t
  • Ensure all LoadModule directives reference existing modules

403 Forbidden errors:

  • Check file permissions in document root
  • Verify Require all granted in directory configuration
  • Check for .htaccess rules blocking access

404 Not Found for SPA routes:

  • Enable mod_rewrite
  • Add RewriteRule to redirect to index.html
  • Verify RewriteEngine is On

Slow response times:

  • Enable gzip compression
  • Configure browser caching with expires module
  • Tune MPM settings for your traffic

Proxy errors:

  • Verify backend service is accessible
  • Check ProxyPass URLs are correct
  • Enable proxy modules (mod_proxy, mod_proxy_http)

Viewing Logs

Apache logs are sent to stdout/stderr by default, viewable in the Klutch.sh dashboard. For more detailed logging:

# Increase log level temporarily
LogLevel debug
# Custom log format with timing
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %D" combined_timing
CustomLog /proc/self/fd/1 combined_timing

Sample Configurations

Static Website with CDN Headers

<VirtualHost *:80>
DocumentRoot "/usr/local/apache2/htdocs"
# Enable CORS for CDN
<Directory "/usr/local/apache2/htdocs">
Header set Access-Control-Allow-Origin "*"
Options -Indexes +FollowSymLinks
AllowOverride None
Require all granted
</Directory>
# Long cache for static assets
<FilesMatch "\.(css|js|jpg|jpeg|png|gif|ico|woff|woff2|svg)$">
Header set Cache-Control "max-age=31536000, public, immutable"
</FilesMatch>
# No cache for HTML
<FilesMatch "\.(html|htm)$">
Header set Cache-Control "no-cache, no-store, must-revalidate"
</FilesMatch>
</VirtualHost>

API Gateway Configuration

<VirtualHost *:80>
ServerName api-gateway.klutch.sh
# Proxy settings
ProxyPreserveHost On
ProxyRequests Off
# Rate limiting headers
Header set X-RateLimit-Limit "1000"
# Route to different services
ProxyPass /users http://users-service:8000
ProxyPassReverse /users http://users-service:8000
ProxyPass /products http://products-service:8000
ProxyPassReverse /products http://products-service:8000
ProxyPass /orders http://orders-service:8000
ProxyPassReverse /orders http://orders-service:8000
# Health check endpoint
<Location "/health">
ProxyPass !
SetHandler none
Require all granted
</Location>
</VirtualHost>

Resources


Conclusion

You now have Apache HTTP Server deployed on Klutch.sh, configured with:

  • Optimized static file serving with compression and caching
  • Security headers and hardened configuration
  • Support for modern web applications (SPA, API proxy)
  • Performance tuning for production workloads
  • Persistent storage for logs and dynamic content

Apache HTTP Server’s flexibility and mature ecosystem make it an excellent choice for serving websites, acting as a reverse proxy, or hosting legacy PHP applications on Klutch.sh.