Munin can render both graphs and HTML pages periodically (cron driven) or on-demand with CGI. The method can be configured in /etc/munin/munin.conf by setting graph_strategy and html_strategy to either cgi or html. So for a CGI driven setup you will want these lines:

graph_strategy cgi
html_strategy cgi

For CGI to work (including the zoomable graph), you need a CGI module for Apache, e.g.:

apt-get install libapache2-mod-fcgid

Apache 2.4 configuration snippets

Cron HTML and graphs, no zoomable graph

With the default configuration in the Debian package, a Cron job will generate HTML and PNG files under /var/cache/munin/www. You can point your browser at this directory and load the files directly from there.

To serve when using Apache, you only need to serve the static files under a path (excerpt of the standard /etc/munin/apache24.conf):

Alias /munin /var/cache/munin/www
<Directory /var/cache/munin/www>
        Require local
        Options None
</Directory>

CGI graphs

The zoomable graph requires enabling the CGI script. This is the config that is shipped with the munin package as /etc/munin/apache24.conf. There is a symlink to this file from /etc/apache2/conf-available, so you can enable it with

a2enconf munin

For reference, the Apache config looks like this:

Alias /munin /var/cache/munin/www
<Directory /var/cache/munin/www>
        Require local
        Options None
</Directory>

ScriptAlias /munin-cgi/munin-cgi-graph /usr/lib/munin/cgi/munin-cgi-graph
<Location /munin-cgi/munin-cgi-graph>
        Require local
        <IfModule mod_fcgid.c>
            SetHandler fcgid-script
        </IfModule>
        <IfModule !mod_fcgid.c>
            SetHandler cgi-script
        </IfModule>
</Location>

The default graph_strategy is cron, so the CGI script is only used for the zoomable graph. With the above config, you can change graph_strategy to cron and avoid pre-generating the PNG images.

CGI HTML pages

To avoid pre-generating the HTML pages too, you need to set graph_strategy to cgi and change the Apache config slightly:

Alias /munin/static /var/cache/munin/www/static
<Directory /var/cache/munin/www/static>
        Require local
        Options None
</Directory>

ScriptAlias /munin /usr/lib/munin/cgi/munin-cgi-html
<LocationMatch "^/munin/(?!static/)">
        Require local
        <IfModule mod_fcgid.c>
            SetHandler fcgid-script
        </IfModule>
        <IfModule !mod_fcgid.c>
            SetHandler cgi-script
        </IfModule>
</LocationMatch>

ScriptAlias /munin-cgi/munin-cgi-graph /usr/lib/munin/cgi/munin-cgi-graph
<Location /munin-cgi/munin-cgi-graph>
        Require local
        <IfModule mod_fcgid.c>
            SetHandler fcgid-script
        </IfModule>
        <IfModule !mod_fcgid.c>
            SetHandler cgi-script
        </IfModule>
</Location>

You can then go and delete the HTML and PNG files under /var/cache/munin/www/ since they're no longer used. The static/ directory there is copied from /etc/munin/static every time the Cron job runs.

FastCGI reverse proxying to the CGI running as a service

The above setup using fcgid can easily lead to multiple munin-cgi-graph subprocesses to be spawned and your server might end up thrashing because of excessive memory usage.

To avoid this, you can use the systemd unit files profided in /usr/share/doc/munin/examples/systemd-fastcgi in order to run the cgi scripts as services and provide socket activation of the scripts.

With the systemd units in place, the Apache configuration for proxying looks like the following:

Alias /munin/static /var/cache/munin/www/static
<Directory /var/cache/munin/www/static>
        Require local
        Options None
</Directory>

<LocationMatch "^/((?!static\/dynazoom).*\.html)?$">
        Require all granted
        ProxyFCGISetEnvIf "true" PATH_INFO "%{REQUEST_URI}"
        ProxyPass "unix:/run/munin/fcgi-html.sock|fcgi://127.0.0.1/"
        ProxyPassReverse "unix:/run/munin/fcgi-html.sock|fcgi://127.0.0.1/"
</LocationMatch>

<LocationMatch "^/munin-cgi/.*\.png$">
        Require all granted
        # munin-cgi-graph expects the path to start with a slash and not to
        # contain the logical path the cgi from the URL (e.g. we just want to
        # send it something like /group/hostname/image.png)
        ProxyFCGISetEnvIf "%{REQUEST_URI} =~ m|^(/munin-cgi/munin-cgi-graph)?(/.*\.png)$|" PATH_INFO "$2"
        # Here we need to use a different localhost IP. Otherwise Apache
        # conflates the fcgi worker with the one defined above and requests for
        # images get us html instead.
        ProxyPass "unix:/run/munin/fcgi-graph.sock|fcgi://127.0.0.2/"
        ProxyPassReverse "unix:/run/munin/fcgi-graph.sock|fcgi://127.0.0.2/"
</LocationMatch>

Common Errors

Cannot serve directory /var/cache/munin/www/: No matching DirectoryIndex (index.php) found, and server-generated directory index forbidden by Options directive

If you get the following error:

[Tue Sep 20 21:20:13.517052 2016] [autoindex:error] [pid] [client ] xxx: Cannot serve directory /var/cache/munin/www/: No matching DirectoryIndex (index.php) found, and server-generated directory index forbidden by Options directive

Please add the ?DirectoryIndex index.html at the bottom of the <Direcoty> directive in /etc/munin/apache24.conf

<Directory /var/cache/munin/www>
        .....
        .....
        DirectoryIndex index.html
</Directory>