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
-
Create a new GitHub repository or use an existing one for your web project.
-
Create a basic project structure:
my-apache-project/├── Dockerfile├── httpd.conf├── public/│ ├── index.html│ ├── css/│ │ └── style.css│ └── js/│ └── app.js└── .dockerignore -
Create a sample
index.htmlin thepublic/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>© 2024 Deployed with ❤️ on Klutch.sh</p></footer><script src="js/app.js"></script></body></html> -
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;} -
Create a
js/app.js:document.addEventListener('DOMContentLoaded', function() {console.log('Apache HTTP Server running on Klutch.sh!');// Add current timestamp to info sectionconst 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.
-
Create a
Dockerfilein your project root:# Use the official Apache HTTP Server imageFROM httpd:2.4-alpine# Install additional tools (optional)RUN apk add --no-cache curl# Remove default contentRUN rm -rf /usr/local/apache2/htdocs/*# Copy custom Apache configurationCOPY httpd.conf /usr/local/apache2/conf/httpd.conf# Copy website files to document rootCOPY public/ /usr/local/apache2/htdocs/# Set proper permissionsRUN chown -R www-data:www-data /usr/local/apache2/htdocs/ || trueRUN chmod -R 755 /usr/local/apache2/htdocs/# Expose port 80EXPOSE 80# Health checkHEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \CMD curl -f http://localhost/ || exit 1# Start Apache in foregroundCMD ["httpd-foreground"] -
Create a custom
httpd.conffor optimized configuration:# Apache HTTP Server Configuration for Klutch.shServerRoot "/usr/local/apache2"# Listen on port 80Listen 80# Load essential modulesLoadModule mpm_event_module modules/mod_mpm_event.soLoadModule authn_file_module modules/mod_authn_file.soLoadModule authn_core_module modules/mod_authn_core.soLoadModule authz_host_module modules/mod_authz_host.soLoadModule authz_groupfile_module modules/mod_authz_groupfile.soLoadModule authz_user_module modules/mod_authz_user.soLoadModule authz_core_module modules/mod_authz_core.soLoadModule access_compat_module modules/mod_access_compat.soLoadModule auth_basic_module modules/mod_auth_basic.soLoadModule reqtimeout_module modules/mod_reqtimeout.soLoadModule filter_module modules/mod_filter.soLoadModule mime_module modules/mod_mime.soLoadModule log_config_module modules/mod_log_config.soLoadModule env_module modules/mod_env.soLoadModule headers_module modules/mod_headers.soLoadModule setenvif_module modules/mod_setenvif.soLoadModule version_module modules/mod_version.soLoadModule unixd_module modules/mod_unixd.soLoadModule status_module modules/mod_status.soLoadModule autoindex_module modules/mod_autoindex.soLoadModule dir_module modules/mod_dir.soLoadModule alias_module modules/mod_alias.soLoadModule rewrite_module modules/mod_rewrite.soLoadModule deflate_module modules/mod_deflate.soLoadModule expires_module modules/mod_expires.so# Server identityServerAdmin webmaster@localhostServerName localhost# Document rootDocumentRoot "/usr/local/apache2/htdocs"# Directory configuration<Directory />AllowOverride noneRequire all denied</Directory><Directory "/usr/local/apache2/htdocs">Options Indexes FollowSymLinksAllowOverride AllRequire 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 logErrorLog /proc/self/fd/2LogLevel warn# Access log format<IfModule log_config_module>LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combinedLogFormat "%h %l %u %t \"%r\" %>s %b" commonCustomLog /proc/self/fd/1 combined</IfModule># MIME types<IfModule mime_module>TypesConfig conf/mime.typesAddType application/x-compress .ZAddType application/x-gzip .gz .tgzAddType text/html .shtmlAddType application/javascript .jsAddType text/css .cssAddType image/svg+xml .svg .svgzAddType application/json .jsonAddType font/woff .woffAddType font/woff2 .woff2</IfModule># Enable gzip compression<IfModule deflate_module>SetOutputFilter DEFLATEDeflateCompressionLevel 6# Compress text filesAddOutputFilterByType DEFLATE text/html text/plain text/xmlAddOutputFilterByType DEFLATE text/css text/javascriptAddOutputFilterByType DEFLATE application/javascript application/jsonAddOutputFilterByType DEFLATE application/xml application/xhtml+xmlAddOutputFilterByType DEFLATE image/svg+xml# Don't compress images and other binary filesSetEnvIfNoCase Request_URI \.(?:gif|jpe?g|png|ico|webp)$ no-gzipSetEnvIfNoCase Request_URI \.(?:exe|t?gz|zip|bz2|sit|rar)$ no-gzipSetEnvIfNoCase Request_URI \.(?:pdf|mov|avi|mp3|mp4|rm)$ no-gzip</IfModule># Cache control for static assets<IfModule expires_module>ExpiresActive On# Default expirationExpiresDefault "access plus 1 month"# HTML - no cacheExpiresByType text/html "access plus 0 seconds"# CSS and JavaScript - 1 weekExpiresByType text/css "access plus 1 week"ExpiresByType application/javascript "access plus 1 week"# Images - 1 monthExpiresByType 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 yearExpiresByType font/woff "access plus 1 year"ExpiresByType font/woff2 "access plus 1 year"</IfModule># Security headers<IfModule headers_module># Prevent MIME type sniffingHeader always set X-Content-Type-Options "nosniff"# XSS ProtectionHeader always set X-XSS-Protection "1; mode=block"# Clickjacking protectionHeader always set X-Frame-Options "SAMEORIGIN"# Referrer policyHeader always set Referrer-Policy "strict-origin-when-cross-origin"# Remove server versionHeader 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-statusRequire local</Location># Hide server versionServerTokens ProdServerSignature Off# Timeout settingsTimeout 60KeepAlive OnMaxKeepAliveRequests 100KeepAliveTimeout 5 -
Create a
.dockerignorefile:.git.gitignoreREADME.md.DS_Store*.lognode_modules/.env.env.local
Step 3: Deploy to Klutch.sh
-
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 -
Log in to Klutch.sh and navigate to the dashboard.
-
Create a new project (if you don’t have one already) by clicking “New Project”.
-
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
-
Configure the app settings:
- Traffic Type: Select HTTP
- Internal Port: Set to 80 (Apache’s default HTTP port)
-
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.
-
In your app settings, navigate to the “Volumes” section.
-
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)
- Mount Path:
-
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 modulesRUN 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.confCOPY 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.soLoadModule proxy_http_module modules/mod_proxy_http.soLoadModule 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 modulesRUN a2enmod rewrite headers expires deflate
# Install PHP extensionsRUN docker-php-ext-install pdo pdo_mysql mysqli
# Copy Apache configurationCOPY apache.conf /etc/apache2/sites-available/000-default.conf
# Copy application filesCOPY public/ /var/www/html/
# Set permissionsRUN 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:
# 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=150Using environment variables in httpd.conf:
# Reference environment variablesServerName ${SERVER_NAME}Set defaults in Dockerfile:
ENV SERVER_NAME=localhostENV DOCUMENT_ROOT=/usr/local/apache2/htdocsPerformance 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 DockerfileRUN sed -i \ -e 's/^#\(LoadModule http2_module modules\/mod_http2.so\)/\1/' \ /usr/local/apache2/conf/httpd.conf# Add to httpd.confLoadModule http2_module modules/mod_http2.so
Protocols h2 h2c http/1.1Security Best Practices
-
Hide server information:
ServerTokens ProdServerSignature Off -
Prevent directory listing:
<Directory "/usr/local/apache2/htdocs">Options -Indexes</Directory> -
Disable unnecessary methods:
<Directory "/usr/local/apache2/htdocs"><LimitExcept GET POST HEAD>Require all denied</LimitExcept></Directory> -
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';" -
Enable HSTS (Strict Transport Security):
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains" -
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 detailsExtendedStatus OnCustom 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 grantedin 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 temporarilyLogLevel debug
# Custom log format with timingLogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %D" combined_timingCustomLog /proc/self/fd/1 combined_timingSample 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
- Apache HTTP Server Documentation
- Official httpd Docker Image
- Apache Modules Reference
- Klutch.sh Quick Start Guide
- Klutch.sh Volumes Guide
- Klutch.sh Deployments Guide
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.