4

I'm trying to make a wildcard VirtualHost conf file for apache2, and I'm not sure how to handle the ErrorLog and CustomLog settings to put the logs where I want them to go. As you can see in the second VirtualHost, I have the logs in a logs folder in the domains DocumentRoot. This works fine for static VirtualHosts, but how would I go about it for a wildcard VirtualHost. eg, the first VirtualHost.

NameVirtualHost *:80

# Wild card all subdomains
<VirtualHost *:80>
        ServerAlias *.example.com
        VirtualDocumentRoot /var/www/%0/public
        ErrorLog ?????
        CustomLog ????? combined
</VirtualHost>


# Main domain
<VirtualHost *:80>
        ServerName example.com
        ServerAlias www.example.com
        DocumentRoot /var/www/example.com/public
        ErrorLog /var/www/example.com/logs/error.log
        CustomLog /var/www/example.com/logs/access.log combined
</VirtualHost>

I have tried going ErrorLog /var/www/*.example.com/logs/error.log and ErrorLog /var/www/%0/logs/error.log and the same for CustomLog, but when I try to restart apache it throws an error.

What syntax should I use to get a working version of my ErrorLog example above?

I have seen Wildcards in Virtual Hosts with dynamic logs? , but it is not really what I am after as it still ends up putting all the logs into one big file rather than having them split into their own subdomain specific folders.

2
  • Are your vhosts owned/run by different users/clients, or are you responsible for all of them? If you're responsible for all of them, what are you trying to achieve by separating them?
    – oucil
    May 25, 2020 at 13:35
  • @oucil Im responsible for all of them. I had originally had each subdomain separate with their own VirtualHost segment, but I thought I would try to automate the process of creating new subdomains whenever I needed a new site. This way I could just create the folder in the correct position and I have a live site without having to edit any config files. Having the logs separate is just much more tidy than having them all in one file, and follows the log format of what I had originally. May 25, 2020 at 13:40

2 Answers 2

3
+50

At the risk of giving you more work, you may also want to consider going the opposite direction and combining ALL of your logfiles into syslog. It seems more intimidating but it's a much more capable solution. I don't bother with separate logs anymore at all and just pipe all logs directly to the syslog (which keeps everything in /var/log/messages).

Though Apache doesn't do it natively, you can achieve it like so...

LogLevel info
ErrorLog  "| /usr/bin/logger -thttpd -plocal6.err"
CustomLog "| /usr/bin/logger -thttpd -plocal6.notice" "%v %h %l %u %t \"%r\" %>s %b"

Syslog will give you a lot of options as there are tons of services and utilities set up to parse and manage it. I love using lnav personally, you can filter, sort, search, etc. and the interface over ssh is colourized so it's easy to spot problems. You can also use utilities to deliver all of this into a SQL db where the sky's the limit, or for less work you can use commercial services like datadog that have pretty dashboards :).

You'll want to read up on things like facilities (local1-7) which allow you to assign groups basically to services that don't have syslog logging built in.

In the definition above, I'm piping both my access and error logs to logger which is a utility designed to accept logs and record them in a common format in the syslog along with the details of the service providing them. You can see that the %v is the first part of my access log which makes it easy to filter for vhosts in the syslog down the road.

You'll notice in the directives, that the error log uses local6.err while the access log uses local6.notice, this actually sets the level of the log line, the errors will end up coloured red in lnav, while the others will be standard/info.

Beware the rabit hole ;)

3
  • 1
    Tis a rabbit hole indeed. This way works really well. Thanks! May 26, 2020 at 0:56
  • @Mr.Simmons happy to pass it along, it made logging almost fun :D
    – oucil
    May 26, 2020 at 1:05
  • 1
    Hahaha. You have really sparked my interest in setting up logging into an SQL db. Im definitely going to have to mess around with that at some point. It sounds fun ;) Also to note, I changed %v to %V because the lowercase one was always returning 127.0.1.1 where as %V logs the full address May 26, 2020 at 1:29
0

One solution would be to split the combined log after the fact. Apache has a utility called split-logfile (https://httpd.apache.org/docs/2.4/programs/split-logfile.html)

From the docs...

Create a log file with virtual host information in it:

LogFormat "%v %h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-agent}i\"" combined_plus_vhost
CustomLog logs/access_log combined_plus_vhost

Log files will be created, in the directory where you run the script, for each virtual host name that appears in the combined log file. These logfiles will named after the hostname, with a .log file extension.

The combined log file is read from stdin. Records read will be appended to any existing log files.

split-logfile < access_log
7
  • Thanks for the suggestion, however it doesn't quite achieve what I would like it to. It kind of does the same thing as the link I put in my question. My understanding of this is that while it might create separate files after running the split-logfile utility, it puts them all into one file. Where as I would like the log files to be put in their own folders in the beginning based off the subdomain address. eg, a.example.com would create /var/www/a.example.com/logs/error.log etc. Also this only appears to work for access logs and not error logs. Thanks again though. May 25, 2020 at 9:11
  • @Mr.Simmons It should work for both logs as far as I understand, it just depends on what you supply it with, though you would need to ensure that the vhost is included in both, so they would both need custom formats. I know you're trying to get a variable into the path so that the path for each vhost log is unique but I'm not sure that it's possible in the wildcard setup you've got. The variable %v is what includes the vhost name in the logs, have you attempted to use it rather than %0 ?
    – oucil
    May 25, 2020 at 13:23
  • @Mr.Simmons The other thing you can consider doing is just running a cron job that first runs the split, then parses the name of the vhost out of the log file name, then moves them to their respective directories afterward. This would be pretty trivial to do, it would only mean there is a delay in getting the logs to the vhosts as long as the delay between cron runs.
    – oucil
    May 25, 2020 at 13:25
  • Sadly %v doesn't work. apache just crashes when I reload it. Ive never worked with cron jobs before. How would I go about setting one up? May 25, 2020 at 13:43
  • Cron is easy, it's literally just a basic repeating event schedule, the user you want to run a command as, and the command you want to run. For instance on Cent/Fedora/RHEL, if I want to run a script every night, I would create the file /etc/cron.d/split-logs and then within the file add the line 0 4 * * * root /home/myuser/split-logs.sh. The first 5 values in that line represent minutes, hours, day-of-month, month-of-year, day-of-week with * meaning 'all. Lastly you would create the sh script at the path which actually runs the split-logfile` and then redistributes them.
    – oucil
    May 25, 2020 at 13:56

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .