Apache (httpd / apache2) Complete Cheatsheet
Covers both the Debian/Ubuntu standard (
apache2) and RHEL/Oracle Linux/CentOS (httpd), pointing out the differences where they exist.
Summary
Installation and Service
Debian/Ubuntu
apt update
apt install apache2 -y
RHEL/Oracle Linux/CentOS
dnf install httpd -y
# versões antigas:
yum install httpd -y
Service management (systemd)
# Debian/Ubuntu — serviço chama-se apache2
systemctl start apache2
systemctl stop apache2
systemctl restart apache2
systemctl reload apache2 # reload gracioso (sem dropar conexões)
systemctl status apache2
systemctl enable --now apache2
# RHEL/Oracle Linux — serviço chama-se httpd
systemctl start httpd
systemctl stop httpd
systemctl restart httpd
systemctl reload httpd
systemctl status httpd
systemctl enable --now httpd
Test and validate configuration
# Debian/Ubuntu
apache2ctl configtest
apache2ctl -t
apache2ctl -S # lista VirtualHosts e como foram resolvidos
apache2ctl -M # lista módulos carregados
apache2 -v # versão
# RHEL/Oracle Linux
httpd -t
apachectl configtest
apachectl -S
apachectl -M
httpd -v
File Structure
Debian/Ubuntu
/etc/apache2/
├── apache2.conf # config principal
├── ports.conf # portas que o Apache escuta (Listen)
├── conf-available/ # snippets de config disponíveis
├── conf-enabled/ # symlinks ativos de conf-available
├── mods-available/ # módulos disponíveis
├── mods-enabled/ # symlinks de módulos ativos
├── sites-available/ # vhosts disponíveis
└── sites-enabled/ # symlinks de vhosts ativos
/var/log/apache2/
├── access.log
└── error.log
/var/www/html/ # webroot padrão
RHEL/Oracle Linux
/etc/httpd/
├── conf/
│ └── httpd.conf # config principal
├── conf.d/ # *.conf incluídos automaticamente (vhosts geralmente aqui)
└── conf.modules.d/ # carregamento de módulos (*.conf com LoadModule)
/var/log/httpd/
├── access_log
└── error_log
/var/www/html/ # webroot padrão
Enable/disable site (Debian — uses helper scripts)
a2ensite meusite.conf
a2dissite meusite.conf
a2enmod rewrite
a2dismod rewrite
a2enconf nome-do-conf
a2disconf nome-do-conf
systemctl reload apache2
On RHEL/Oracle Linux there is no
a2ensite/a2enmod— just place/remove the.confinconf.d/and modules are already loaded by default inconf.modules.d/.
Modules
Most used essential modules
Enable modules
# Debian/Ubuntu
a2enmod rewrite ssl proxy proxy_http proxy_wstunnel headers deflate expires
systemctl restart apache2
# RHEL/Oracle Linux — editar/criar arquivo em conf.modules.d/ ou
# garantir que a linha LoadModule não está comentada
grep -r "LoadModule rewrite_module" /etc/httpd/conf.modules.d/
systemctl restart httpd
List loaded modules
apache2ctl -M # Debian
httpd -M # RHEL
Basic Configuration Syntax
# Debian: /etc/apache2/apache2.conf
# RHEL: /etc/httpd/conf/httpd.conf
ServerRoot "/etc/apache2" # ou /etc/httpd no RHEL
Listen 80
User www-data # Debian (RHEL: User apache)
Group www-data # Debian (RHEL: Group apache)
ServerAdmin [email protected]
ServerName exemplo.com.br
DocumentRoot /var/www/html
<Directory /var/www/html>
Options Indexes FollowSymLinks
AllowOverride None
Require all granted
</Directory>
ErrorLog ${APACHE_LOG_DIR}/error.log
LogLevel warn
CustomLog ${APACHE_LOG_DIR}/access.log combined
IncludeOptional conf-enabled/*.conf # Debian
IncludeOptional sites-enabled/*.conf # Debian
# RHEL usa: IncludeOptional conf.d/*.conf
Configuration contexts: Server config (global) → VirtualHost → Directory/Location/Files → .htaccess (if allowed). More specific directives override general ones, respecting AllowOverride.
VirtualHosts
Basic HTTP
<VirtualHost *:80>
ServerName exemplo.com.br
ServerAlias www.exemplo.com.br
DocumentRoot /var/www/exemplo.com.br
<Directory /var/www/exemplo.com.br>
Options -Indexes +FollowSymLinks
AllowOverride All
Require all granted
</Directory>
ErrorLog ${APACHE_LOG_DIR}/exemplo_error.log
CustomLog ${APACHE_LOG_DIR}/exemplo_access.log combined
</VirtualHost>
Multiple domains (name-based virtual hosting)
<VirtualHost *:80>
ServerName app1.exemplo.com.br
DocumentRoot /var/www/app1
</VirtualHost>
<VirtualHost *:80>
ServerName app2.exemplo.com.br
DocumentRoot /var/www/app2
</VirtualHost>
Default VirtualHost (catch-all)
<VirtualHost _default_:80>
DocumentRoot /var/www/html
# responde para qualquer Host não mapeado explicitamente
</VirtualHost>
IP-based VirtualHost
<VirtualHost 10.0.0.10:80>
ServerName site-a.exemplo.com.br
DocumentRoot /var/www/site-a
</VirtualHost>
Directory and Access Control
Directory vs Location vs Files
# Directory: aplica a um caminho no filesystem
<Directory /var/www/html/admin>
Require all denied
</Directory>
# Location: aplica a um caminho na URL (não no filesystem)
<Location /admin>
Require ip 192.168.0.0/24
</Location>
# Files / FilesMatch: aplica a arquivos específicos
<FilesMatch "\.(env|git|htaccess)$">
Require all denied
</FilesMatch>
Access control by IP
<Directory /var/www/html/admin>
Require ip 192.168.0.0/24
Require ip 10.0.0.5
</Directory>
Combining conditions (Apache 2.4+)
<RequireAny>
Require ip 192.168.0.0/24
Require user admin
</RequireAny>
<RequireAll>
Require ip 10.0.0.0/8
Require not ip 10.0.0.50
</RequireAll>
AllowOverride (controls what .htaccess can override)
<Directory /var/www/html>
AllowOverride All # permite tudo via .htaccess (custo de performance)
AllowOverride None # ignora .htaccess (recomendado por performance/segurança)
AllowOverride AuthConfig # só permite diretivas de autenticação
</Directory>
.htaccess
Only works if
AllowOverrideallows it in the parentDirectory. It has a performance cost (Apache reads the file on every request) — prefer direct configuration in the VirtualHost when possible.
# Exemplo de .htaccess típico (WordPress-style)
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^ index.php [L]
# Bloquear acesso a arquivos sensíveis
<FilesMatch "\.(env|git|sql)$">
Require all denied
</FilesMatch>
# Forçar HTTPS
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
Reverse Proxy
Basic configuration (requires mod_proxy + mod_proxy_http)
<VirtualHost *:80>
ServerName api.exemplo.com.br
ProxyPreserveHost On
ProxyPass / http://127.0.0.1:8080/
ProxyPassReverse / http://127.0.0.1:8080/
RequestHeader set X-Forwarded-Proto "http"
RequestHeader set X-Forwarded-For %{REMOTE_ADDR}e
</VirtualHost>
Exclude paths from proxy
ProxyPass /static/ !
ProxyPass / http://127.0.0.1:8080/
Timeouts
ProxyTimeout 60
Timeout 60
Buffers / large upload
LimitRequestBody 52428800 # ~50MB em bytes (0 = ilimitado)
Attention to trailing slash in ProxyPass (same logic as nginx)
# COM barra: remove o prefixo /api/ antes de enviar ao backend
ProxyPass /api/ http://backend:3000/
# /api/users -> http://backend:3000/users
# SEM barra: mantém o prefixo completo
ProxyPass /api http://backend:3000
# /api/users -> http://backend:3000/api/users
Load Balancing
Basic balancer (requires mod_proxy_balancer + mod_lbmethod_byrequests)
<Proxy "balancer://backend_app">
BalancerMember http://10.0.0.10:8080
BalancerMember http://10.0.0.11:8080
BalancerMember http://10.0.0.12:8080 status=+H # +H = hot standby (backup)
ProxySet lbmethod=byrequests
</Proxy>
<VirtualHost *:80>
ServerName app.exemplo.com.br
ProxyPass / balancer://backend_app/
ProxyPassReverse / balancer://backend_app/
</VirtualHost>
Balancing strategies (lbmethod)
ProxySet lbmethod=byrequests # round-robin por número de requisições (padrão)
ProxySet lbmethod=bytraffic # balanceia por tráfego (bytes)
ProxySet lbmethod=bybusyness # menos requisições pendentes
Weights and health check
<Proxy "balancer://backend_app">
BalancerMember http://10.0.0.10:8080 loadfactor=3
BalancerMember http://10.0.0.11:8080 loadfactor=1
BalancerMember http://10.0.0.12:8080 retry=30 timeout=5
</Proxy>
Sticky session
<Proxy "balancer://backend_app">
BalancerMember http://10.0.0.10:8080 route=node1
BalancerMember http://10.0.0.11:8080 route=node2
ProxySet stickysession=ROUTEID
</Proxy>
Balancer management panel
<Location /balancer-manager>
SetHandler balancer-manager
Require ip 127.0.0.1
</Location>
SSL/TLS and Certbot
Basic SSL block (requires mod_ssl)
<VirtualHost *:443>
ServerName exemplo.com.br
SSLEngine on
SSLCertificateFile /etc/letsencrypt/live/exemplo.com.br/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/exemplo.com.br/privkey.pem
SSLProtocol -all +TLSv1.2 +TLSv1.3
SSLCipherSuite HIGH:!aNULL:!MD5
SSLHonorCipherOrder on
SSLSessionCache shmcb:/var/cache/mod_ssl/scache(512000)
SSLSessionCacheTimeout 300
# OCSP stapling
SSLUseStapling on
SSLStaplingCache shmcb:/var/run/ocsp(128000)
</VirtualHost>
# Redirect HTTP -> HTTPS
<VirtualHost *:80>
ServerName exemplo.com.br
Redirect permanent / https://exemplo.com.br/
</VirtualHost>
Enable SSL module
# Debian/Ubuntu
a2enmod ssl
a2ensite default-ssl
systemctl restart apache2
# RHEL/Oracle Linux
dnf install mod_ssl -y
systemctl restart httpd
Certbot — issuance and renewal
# Instalação
apt install certbot python3-certbot-apache -y # Debian/Ubuntu
dnf install certbot python3-certbot-apache -y # RHEL/Oracle Linux
# Emitir certificado (modo apache, edita config automaticamente)
certbot --apache -d exemplo.com.br -d www.exemplo.com.br
# Emitir só o certificado (sem tocar na config)
certbot certonly --apache -d exemplo.com.br
# Wildcard (requer plugin DNS, ex: Cloudflare)
certbot certonly --dns-cloudflare \
--dns-cloudflare-credentials /etc/letsencrypt/cloudflare.ini \
-d "*.exemplo.com.br" -d "exemplo.com.br"
# Renovação manual / teste
certbot renew --dry-run
certbot renew --deploy-hook "systemctl reload apache2"
# Listar certificados
certbot certificates
# Deletar certificado
certbot delete --cert-name exemplo.com.br
Generate dhparam
openssl dhparam -out /etc/apache2/dhparam.pem 2048
SSLOpenSSLConfCmd DHParameters "/etc/apache2/dhparam.pem"
HTTP Headers
# Requer mod_headers (a2enmod headers)
Header always set X-Frame-Options "SAMEORIGIN"
Header always set X-Content-Type-Options "nosniff"
Header always set X-XSS-Protection "1; mode=block"
Header always set Referrer-Policy "strict-origin-when-cross-origin"
Header always set Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"
Header always set Content-Security-Policy "default-src 'self'"
# Remover/ofuscar header que expõe versão
ServerTokens Prod
ServerSignature Off
# CORS básico
Header always set Access-Control-Allow-Origin "*"
Header always set Access-Control-Allow-Methods "GET, POST, OPTIONS"
Header always set Access-Control-Allow-Headers "Authorization, Content-Type"
ServerTokens ProdandServerSignature Offgo in the global context (apache2.conf/httpd.conf), not insideVirtualHost.
Compression (Gzip/Brotli)
Gzip (requires mod_deflate)
<IfModule mod_deflate.c>
AddOutputFilterByType DEFLATE text/plain
AddOutputFilterByType DEFLATE text/css
AddOutputFilterByType DEFLATE text/xml
AddOutputFilterByType DEFLATE application/json
AddOutputFilterByType DEFLATE application/javascript
AddOutputFilterByType DEFLATE application/xml
AddOutputFilterByType DEFLATE image/svg+xml
DeflateCompressionLevel 6
<IfModule mod_filter.c>
FilterDeclare COMPRESS
FilterProvider COMPRESS DEFLATE resp=Content-Type $text/html
</IfModule>
</IfModule>
Brotli (requires mod_brotli, Apache 2.4.26+)
<IfModule mod_brotli.c>
AddOutputFilterByType BROTLI_COMPRESS text/html text/css application/json application/javascript
BrotliCompressionQuality 6
</IfModule>
Cache
Static assets cache (requires mod_expires)
<IfModule mod_expires.c>
ExpiresActive On
ExpiresByType image/jpeg "access plus 30 days"
ExpiresByType image/png "access plus 30 days"
ExpiresByType text/css "access plus 7 days"
ExpiresByType application/javascript "access plus 7 days"
</IfModule>
<IfModule mod_headers.c>
<FilesMatch "\.(jpg|jpeg|png|gif|css|js|woff2?)$">
Header set Cache-Control "public, immutable"
</FilesMatch>
</IfModule>
Reverse proxy cache (requires mod_cache + mod_cache_disk)
<IfModule mod_cache.c>
CacheRoot /var/cache/apache2/mod_cache_disk
CacheEnable disk /
CacheDirLevels 2
CacheDirLength 1
CacheMaxFileSize 10000000
CacheIgnoreCacheControl On
CacheDefaultExpire 600
</IfModule>
Rewrite and Redirects
Enable module
a2enmod rewrite # Debian
# RHEL: já vem habilitado por padrão em conf.modules.d/
systemctl restart apache2
Simple redirects
Redirect 301 /antigo /novo
Redirect 302 /temp /pagina-temporaria
RedirectMatch 301 ^/blog/(.*)$ /artigos/$1
RewriteRule (more flexible, with regex and conditions)
RewriteEngine On
# Forçar HTTPS
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
# Forçar non-www
RewriteCond %{HTTP_HOST} ^www\.(.*)$ [NC]
RewriteRule ^(.*)$ https://%1%{REQUEST_URI} [L,R=301]
# SPA (React/Vue/Angular) — tudo cai no index.html
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^ /index.html [L]
# Remover .php da URL
RewriteCond %{REQUEST_FILENAME}.php -f
RewriteRule ^(.*)$ $1.php [L]
Most used flags
PHP (mod_php vs PHP-FPM)
mod_php (legacy model, Apache process executes PHP directly)
# Debian/Ubuntu
apt install libapache2-mod-php8.3 php8.3 -y
a2enmod php8.3
systemctl restart apache2
# RHEL/Oracle Linux
dnf install php php-cli -y
systemctl restart httpd
PHP-FPM (recommended — separate process, better performance/isolation)
<FilesMatch \.php$>
SetHandler "proxy:unix:/run/php/php8.3-fpm.sock|fcgi://localhost"
</FilesMatch>
# Habilitar módulos necessários
a2enmod proxy_fcgi setenvif
a2enconf php8.3-fpm
systemctl restart apache2
Important:
mod_phpandPHP-FPMshould not coexist in the same VirtualHost — choose one model. PHP-FPM is preferable in production because it allows independent pool tuning from Apache (same as done with Nginx).
WebSockets
Requires mod_proxy_wstunnel
a2enmod proxy proxy_wstunnel
systemctl restart apache2
<VirtualHost *:443>
ServerName ws.exemplo.com.br
RewriteEngine On
RewriteCond %{HTTP:Upgrade} websocket [NC]
RewriteCond %{HTTP:Connection} upgrade [NC]
RewriteRule ^/?(.*) "ws://127.0.0.1:8080/$1" [P,L]
ProxyPass / http://127.0.0.1:8080/
ProxyPassReverse / http://127.0.0.1:8080/
</VirtualHost>
Basic Authentication
# Gerar arquivo de senha (requer apache2-utils / httpd-tools)
htpasswd -c /etc/apache2/.htpasswd usuario1
htpasswd /etc/apache2/.htpasswd usuario2 # adicionar outro sem -c
<Directory /var/www/html/admin>
AuthType Basic
AuthName "Área restrita"
AuthUserFile /etc/apache2/.htpasswd
Require valid-user
</Directory>
Combining IP + authentication (either one allows)
<Directory /var/www/html/admin>
AuthType Basic
AuthName "Área restrita"
AuthUserFile /etc/apache2/.htpasswd
<RequireAny>
Require valid-user
Require ip 192.168.0.0/24
</RequireAny>
</Directory>
Rate Limiting / Throttling
Apache does not have native rate limiting as direct as Nginx's
limit_req. The main options:
mod_ratelimit (limits bandwidth, not request rate)
<IfModule mod_ratelimit.c>
<Location /downloads>
SetOutputFilter RATE_LIMIT
SetEnv rate-limit 400 # KB/s
</Location>
</IfModule>
mod_evasive (protection against brute-force/DoS)
apt install libapache2-mod-evasive -y # Debian
dnf install mod_evasive -y # RHEL
<IfModule mod_evasive20.c>
DOSHashTableSize 3097
DOSPageCount 5 # max requisições à mesma página
DOSPageInterval 1 # intervalo em segundos
DOSSiteCount 50 # max requisições ao site todo
DOSSiteInterval 1
DOSBlockingPeriod 600 # tempo de bloqueio em segundos
DOSEmailNotify [email protected]
</IfModule>
mod_security2 (complete WAF, with OWASP CRS)
apt install libapache2-mod-security2 -y
cp /etc/modsecurity/modsecurity.conf-recommended /etc/modsecurity/modsecurity.conf
sed -i 's/SecRuleEngine DetectionOnly/SecRuleEngine On/' /etc/modsecurity/modsecurity.conf
systemctl restart apache2
Logs
Custom formats
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %D" detailed
CustomLog ${APACHE_LOG_DIR}/access.log detailed
Conditional logs (do not log health checks)
SetEnvIf Request_URI "^/health$" dontlog
CustomLog ${APACHE_LOG_DIR}/access.log combined env=!dontlog
Log rotation (logrotate)
cat /etc/logrotate.d/apache2 # Debian
cat /etc/logrotate.d/httpd # RHEL
logrotate -f /etc/logrotate.d/apache2
Useful analysis commands
tail -f /var/log/apache2/access.log
tail -f /var/log/apache2/error.log
# Top IPs
awk '{print $1}' access.log | sort | uniq -c | sort -rn | head -20
# Status codes mais frequentes
awk '{print $9}' access.log | sort | uniq -c | sort -rn
# Requisições mais lentas (com %D no log format)
awk '{print $NF, $7}' access.log | sort -rn | head -20
MPM (Multi-Processing Modules)
The MPM defines how Apache handles simultaneous connections — the choice directly impacts performance and compatibility with PHP.
# Ver MPM ativo
apache2ctl -V | grep -i mpm # Debian
httpd -V | grep -i mpm # RHEL
# Trocar MPM (Debian)
a2dismod mpm_prefork
a2enmod mpm_event
systemctl restart apache2
# Trocar MPM (RHEL — editar conf.modules.d/00-mpm.conf, descomentar a linha desejada)
nano /etc/httpd/conf.modules.d/00-mpm.conf
systemctl restart httpd
Example configuration (mpm_event)
<IfModule mpm_event_module>
StartServers 3
MinSpareThreads 75
MaxSpareThreads 250
ThreadsPerChild 25
MaxRequestWorkers 400
MaxConnectionsPerChild 0
</IfModule>
Attention: if you use
mod_php(instead of PHP-FPM), you are required to usempm_prefork, because mod_php is not thread-safe.
Performance Tuning
# Conexões
Timeout 60
KeepAlive On
MaxKeepAliveRequests 100
KeepAliveTimeout 5
# Limites de requisição (proteção)
LimitRequestBody 52428800
LimitRequestFields 100
LimitRequestFieldSize 8190
# Desabilitar listagem de diretórios e symlinks desnecessários
<Directory /var/www/html>
Options -Indexes -FollowSymLinks
</Directory>
# Desabilitar .htaccess globalmente quando não usado (ganho de performance real)
<Directory /var/www/html>
AllowOverride None
</Directory>
Calculate ideal MaxRequestWorkers
MaxRequestWorkers ≈ (RAM disponível para Apache) / (memória média por processo/thread)
Check actual memory per worker with:
ps -ylC apache2 --sort:rss # Debian
ps -ylC httpd --sort:rss # RHEL
Security
# Esconder versão e informações do servidor (contexto global)
ServerTokens Prod
ServerSignature Off
# Desabilitar listagem de diretórios
Options -Indexes
# Bloquear acesso a arquivos sensíveis
<FilesMatch "\.(env|git|htaccess|htpasswd|sql|bak)$">
Require all denied
</FilesMatch>
# Bloquear acesso a diretórios ocultos
<DirectoryMatch "/\.">
Require all denied
</DirectoryMatch>
# Limitar métodos HTTP
<Location />
<LimitExcept GET POST HEAD>
Require all denied
</LimitExcept>
</Location>
# Timeout agressivo contra slow loris
<IfModule mod_reqtimeout.c>
RequestReadTimeout header=20-40,MinRate=500 body=20,MinRate=500
</IfModule>
fail2ban (complementary, brute-force on auth/admin)
apt install fail2ban -y
# Filtro padrão: /etc/fail2ban/filter.d/apache-auth.conf
SELinux (RHEL/Oracle Linux)
On Debian/Ubuntu there is usually no SELinux (there may be AppArmor). On RHEL/Oracle Linux, SELinux is often the #1 cause of unexpected "403" or "502" when integrating with proxy/backend.
# Verificar status
getenforce
sestatus
# Ver se SELinux está bloqueando o Apache (logs recentes)
ausearch -m avc -ts recent
journalctl -t setroubleshoot
# Permitir que httpd faça conexões de rede (necessário para proxy reverso!)
setsebool -P httpd_can_network_connect 1
# Permitir conexão com banco de dados (ex: PostgreSQL/MySQL remoto)
setsebool -P httpd_can_network_connect_db 1
# Corrigir contexto de arquivos servidos (após mover/criar arquivos manualmente)
restorecon -Rv /var/www/html
# Definir contexto correto para um diretório fora do padrão
semanage fcontext -a -t httpd_sys_content_t "/dados/site(/.*)?"
restorecon -Rv /dados/site
# Permitir escrita (uploads, cache, sessions)
semanage fcontext -a -t httpd_sys_rw_content_t "/var/www/html/uploads(/.*)?"
restorecon -Rv /var/www/html/uploads
Troubleshooting
Common errors
Diagnostic commands
# Testar configuração
apache2ctl configtest # Debian
httpd -t # RHEL
# Ver VirtualHosts resolvidos
apache2ctl -S
httpd -S
# Processos
ps aux | grep apache2 # Debian
ps aux | grep httpd # RHEL
# Conexões ativas
ss -tn state established '( dport = :80 or dport = :443 )' | wc -l
# Porta escutando
ss -tlnp | grep -E 'apache2|httpd'
# Testar vhost sem alterar DNS
curl -H "Host: exemplo.com.br" http://127.0.0.1/
# Checar certificado SSL
openssl s_client -connect exemplo.com.br:443 -servername exemplo.com.br
# Status em tempo real (requer mod_status)
curl http://localhost/server-status
mod_status (metrics for monitoring/Zabbix)
<Location /server-status>
SetHandler server-status
Require ip 127.0.0.1
</Location>
ExtendedStatus On
curl http://127.0.0.1/server-status?auto # formato parseável para scripts/Zabbix
Apache vs Nginx — Quick Equivalences
Complete Examples
1. Static site with SSL and asset cache
<VirtualHost *:80>
ServerName site.com.br
ServerAlias www.site.com.br
Redirect permanent / https://site.com.br/
</VirtualHost>
<VirtualHost *:443>
ServerName site.com.br
DocumentRoot /var/www/site.com.br
SSLEngine on
SSLCertificateFile /etc/letsencrypt/live/site.com.br/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/site.com.br/privkey.pem
<Directory /var/www/site.com.br>
Options -Indexes +FollowSymLinks
AllowOverride None
Require all granted
</Directory>
<FilesMatch "\.(jpg|jpeg|png|gif|css|js|woff2?)$">
Header set Cache-Control "public, immutable"
</FilesMatch>
ExpiresActive On
ExpiresByType image/jpeg "access plus 30 days"
ExpiresByType text/css "access plus 7 days"
ErrorLog ${APACHE_LOG_DIR}/site_error.log
CustomLog ${APACHE_LOG_DIR}/site_access.log combined
</VirtualHost>
2. Reverse proxy for Java/Spring Boot application
<VirtualHost *:443>
ServerName api.empresa.com.br
SSLEngine on
SSLCertificateFile /etc/letsencrypt/live/api.empresa.com.br/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/api.empresa.com.br/privkey.pem
LimitRequestBody 20971520
ProxyPreserveHost On
ProxyPass / http://127.0.0.1:8080/
ProxyPassReverse / http://127.0.0.1:8080/
RequestHeader set X-Forwarded-Proto "https"
RequestHeader set X-Real-IP %{REMOTE_ADDR}e
ProxyTimeout 60
<Location /actuator/health>
Require ip 127.0.0.1
</Location>
</VirtualHost>
3. Load balancer with failover and sticky session
<Proxy "balancer://cluster_app">
BalancerMember http://10.0.1.10:8080 route=node1 loadfactor=2
BalancerMember http://10.0.1.11:8080 route=node2 loadfactor=2
BalancerMember http://10.0.1.12:8080 route=node3 status=+H
ProxySet lbmethod=byrequests
ProxySet stickysession=ROUTEID
</Proxy>
<VirtualHost *:443>
ServerName app.empresa.com.br
SSLEngine on
SSLCertificateFile /etc/letsencrypt/live/app.empresa.com.br/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/app.empresa.com.br/privkey.pem
ProxyPass / balancer://cluster_app/
ProxyPassReverse / balancer://cluster_app/
<Location /balancer-manager>
SetHandler balancer-manager
Require ip 127.0.0.1
</Location>
</VirtualHost>
4. PHP-FPM with complete vhost (WinThor-style web frontend, e.g.)
<VirtualHost *:443>
ServerName erp.empresa.com.br
DocumentRoot /var/www/erp
SSLEngine on
SSLCertificateFile /etc/letsencrypt/live/erp.empresa.com.br/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/erp.empresa.com.br/privkey.pem
<Directory /var/www/erp>
AllowOverride All
Require all granted
</Directory>
<FilesMatch \.php$>
SetHandler "proxy:unix:/run/php/php8.3-fpm.sock|fcgi://localhost"
</FilesMatch>
ErrorLog ${APACHE_LOG_DIR}/erp_error.log
CustomLog ${APACHE_LOG_DIR}/erp_access.log combined
</VirtualHost>
Quick Command Reference
# Debian/Ubuntu
apache2ctl configtest
apache2ctl -S
apache2ctl -M
systemctl reload apache2
a2ensite meusite.conf && a2dissite outrosite.conf
a2enmod rewrite ssl proxy proxy_http headers
# RHEL/Oracle Linux
httpd -t
httpd -S
httpd -M
systemctl reload httpd
# Comuns aos dois
journalctl -u apache2 -f # ou -u httpd
curl -I https://exemplo.com.br
openssl s_client -connect host:443 -servername host
htpasswd -c /etc/apache2/.htpasswd usuario
Cheatsheet generated for quick reference of Apache administration (apache2/httpd) in Linux production environments, highlighting the differences between Debian/Ubuntu and RHEL/Oracle Linux.
Keep reading
Read also

StorCLI - Complete Cheat Sheet
StorCLI is the official and modern tool for managing Broadcom/LSI RAID controllers. This guide covers essential commands, syntax and use cases.
12 min de leitura
TutoriaisBusiness Services in Nyverra Portal: Translating IT into Business
The business doesn't feel a server go down — it feels email stop. The Business Services (Service Mapping) module of Nyverra ITSM Portal connects services like Email, ERP or PACS to CMDB assets, revealing the real impact of each failure.
5 min de leitura
SegurançaRPO vs RTO: How to Define Before Buying Backup (and Why Most Companies Get It Wrong)
Most companies buy backup asking the wrong question: "how much does it cost?". The right question is: how much data can I lose (RPO) and how long can I be down (RTO). Discover how to define these numbers per system and avoid purchasing protection based on price, not on real need.
9 min de leitura
Comments
No comments yet
Be the first to share your thoughts on this article.

Leave a comment