Apache#
Integration Details |
|
Ingester |
Apache Configuration#
Apache defines its log locations via the ErrorLog and CustomLog directives, which can be configured globally (typically /etc/apache2/apache2.conf) or per virtual host (typically /etc/apache2/sites-available/{VHOST_NAME}.conf). By default, these write to error.log and access.log in /var/log/apache2/. Follow the steps below to configure Apache to output clean data for Gravwell ingestion, then install File Follower on your Apache host by following the instructions in File Follower. Then add the configuration from the File Follower section below.
Define LogFormat#
Apache uses the Common Log Format by default, so we will define a custom structure called: json_combined. This will write the logs cleanly as JSON before ingestion into Gravwell.
You can define this globally in /etc/apache2/apache2.conf or inside a specific Virtual Host in /etc/apache2/sites-available/{VHOST_NAME}.conf.
LogFormat \
"{\"time\":\"%{%Y-%m-%dT%H:%M:%S}t\",\
\"remote_addr\":\"%a\",\
\"method\":\"%m\",\
\"uri\":\"%U\",\
\"query\":\"%q\",\
\"status\":%>s,\
\"bytes\":%B,\
\"duration\":%D,\
\"user_agent\":\"%{User-Agent}i\",\
\"referer\":\"%{Referer}i\"}" json_combined
Key Field Mechanics:#
%auses the client IP address ( or the proxy-decode address ifmod_remoteipis enabled).%Dreports the request duration in microseconds.%qincludes the query string, complete with leading?. If no query string exists, outputs an empty string.
Note
If you’re using this in a template or config management tool, the %{%Y-%m-%dT%H:%M:%S}t strftime pattern contains {% which many templating engines will try to interpret — escape it appropriately for your tooling.
Apply custom logging#
Once the format is defined, update the configuration file to apply it:
CustomLog /var/log/apache2/access.log json_combined
ErrorLog /var/log/apache2/error.log
Common Gotchas & Advanced Tweaks#
RewriteRule placement (Extensionless URLS)#
If you’re using mod_rewrite to handle extensionless URLs (e.g. routing /status to /status.php), your rules must must be placed inside a <Directory> block rather than directly at the global VirtualHost level.
At the global VirtualHost level, %{REQUEST_FILENAME} treats the target as a plain URI string instead of a filesystem path. This causes -f (file) and -d (directory) checks to always evaluate false:
<Directory /var/www/html>
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.+)$ $1.php [L]
</Directory>
Proxy Configuration#
If Apache sits behind a proxy, the standard remote host field will log the proxy’s internal IP address instead of the real clients. We can fix this using mod_remoteip.
Enable the required modules: Run the following commands to enable both the proxy headers and rewrite engines:
a2enmod remoteip
a2enmod rewrite # if you need extensionless URL rewrites
Configure mod_remoteip: Create a dedicated configuration file at
/etc/apache2/conf-available/remoteip.conf:
RemoteIPHeader X-Real-IP
RemoteIPTrustedProxy 172.18.100.60 # nginx's IP
Activate the Configuration
a2enconf remoteip
systemctl restart apache2
Gravwell Configuration#
Gravwell Storage Well Configuration#
Setup the well configuration in your Gravwell indexers.
Sample well config:
Create or edit: /opt/gravwell/etc/gravwell.conf.d/apache-well.conf
[Storage-Well "apache"]
Location=/opt/gravwell/storage/apache
Tags=apache*
Gravwell Ingester Configuration: File Follower#
Sample Apache config:
Create or edit: /opt/gravwell/etc/file_follow.conf.d/apache.conf
[Follower "apache-access"]
Base-Directory = /var/log/apache2
File-Filter = access.log
Tag-Name = apache
[Follower "apache-error"]
Base-Directory = /var/log/apache2
File-Filter = error.log
Tag-Name = apache-err
Note
Remember to restart the service to apply the new config:
sudo systemctl restart gravwell_file_follow.service