Using .htaccess to restrict access

what you can do with .htaccess.
I really need to learn about that file for my site

You can block visitors in the .htaccess using the host name of the visitor.

thanks alot for your information

What I wanted is to restrict access to piwik using HttpAuth whilst allowing piwik.(php|js) and OptOut which is required in germany.

What worked for me:

   # Auth protect Everything
   <Files "*">
     AuthType Basic
     AuthName "Piwik"
     AuthUserFile /{PATH}/.htpasswd
     Require valid-user
   </Files>

   # Allow external access to piwik.php and piwik.js and robots.txt
   <FilesMatch "(^piwik\.(php|js)|robots\.txt)">
     Order Deny,Allow
     Allow from All
     Satisfy any
   </FilesMatch>

   # Allow Opt-Out
   <Files "index.php">
     <If "(%{QUERY_STRING} == 'module=CoreAdminHome&action=optOut')">
       Order Deny,Allow
       Allow from All
       Satisfy Any
      </If>
   </Files>

Hope this helps!

@ bpit
Its better to use require than “allow,deny” in .htaccess I think!

 # Auth protect Everything
   <Files "*">
     AuthType Basic
     AuthName "Piwik"
     AuthUserFile /{PATH}/.htpasswd
     Require valid-user
   </Files>

   # Allow external access to piwik.php and piwik.js and robots.txt
   <FilesMatch "(^piwik\.(php|js)|robots\.txt)">
     Require all granted
   </FilesMatch>

   # Allow Opt-Out
   <Files "index.php">
     <If "(%{QUERY_STRING} == 'module=CoreAdminHome&action=optOut')">
       Require all granted
      </If>
   </Files>

edited (Copy & Paste Mistake)

Hello @chriz
Thank you for your reply.

You’re absolutely right.

While “allow,deny” and “Allow from all” are allowed to be mixed with the new directives of apache 2.4, it is discouraged.

With the Require Directive the order is important (see Authentication and Authorization - Apache HTTP Server Version 2.4)
the Require directive not only specifies which authorization methods should be used, it also specifies the order in which they are called. Multiple authorization methods are called in the same order in which the Require directives appear in the configuration.

Hence, we also don’t need the Satisfy Directive anymore:

<Files "*">
 AuthType Basic
 AuthName "Piwik"
 # to be explicit, state the provider
 AuthBasicProvider file
 AuthUserFile /{PATH}/.htpasswd
 Require valid-user
</Files>
 
# Allow external access to piwik.php and piwik.js and robots.txt
<FilesMatch "(^piwik\.(php|js)|robots\.txt)">
 Require all granted
</FilesMatch>

# Allow Opt-Out
<Files "index.php">
 <If "(%{QUERY_STRING} == 'module=CoreAdminHome&action=optOut')">
   Require all granted
 </If>
</Files>

P.S. Somehow the “OptOut” part got twice in your answer. In one of that parts Files is closed with FilesMatch - which would throw an error! Therefore I put the whole entry here again.

(Edited: “P.S” to make it clearer what I meant)

1 Like

Hello @bpit

Oh, that was a copy & paste mistake. Thank you!
I have edited the post.

Updated simple .htaccess for Apache 2.4

  <Files "*">
      Require ip 172.16.0.0/12
      Require ip 192.168.39.0/24
  </Files>

  <Files ~ "^piwik.(js|php)$">
      Require all granted
  </Files>

Hello Everyone,

I got crucial tips from your answer, thanks for sharing your answers it will be helpful for me,

Regards,

Daniel

TechTIQ Solutions,

I hope this can help someone else in the same situation!

I was trying to use Matomo Tracker Proxy as well as Matomo’s Opt Out iframe. I followed the .htaccess instructions mentioned above, and got the following 401 error:

HTTP401: DENIED - The requested resource requires user authentication. GET - http://example.com/matomo-proxy.php?module=CoreAdminHome&amp;action=optOut&amp;language=en&amp;backgroundColor=&amp;fontColor=&amp;fontSize=&amp;fontFamily=

@fdellwing kindly modified the QUERY_STRING to fix the issue. This is the .htaccess that works for me now:

<Files "*">
 AuthType Basic
 AuthName "Piwik"
 # to be explicit, state the provider
 AuthBasicProvider file
 AuthUserFile "/PATH/TO/.htpasswd"
 Require valid-user
</Files>
 
# Allow external access to piwik.php and piwik.js and robots.txt
<FilesMatch "(^piwik\.(php|js)|robots\.txt)">
 Require all granted
</FilesMatch>

# Allow Opt-Out
<Files "index.php">
 <If "(%{QUERY_STRING} =~ /^module\=CoreAdminHome\&action\=optOut/)">
   Require all granted
 </If>
</Files>

I hope this can help someone who has as little knowledge as me! :pray: :grinning:

I just thought some more about this and will kindly suggest an additional change to the check.

# Allow Opt-Out
<Files "index.php">
 <If "(%{QUERY_STRING} =~ /^module\=CoreAdminHome\&action\=optOut(?!.*module\=)(?!.*action\=)/)">
   Require all granted
 </If>
</Files>

If someone wants to know why, take a look at this:

In short, someone could craft a link that matches the regex but does request completely different than the OptOut.

6 posts were split to a new topic: Restrict API access per IP address

Firstly, thanks a lot @bpit @HuffinPuffin for your well working solution :slight_smile:
Just to let you know :

  • it seems that in last Matomo version, the piwik.js was renamed matomo.js. Unfortunately it will popup an Apache Authentication window to any user who just display your website …
  • that optOut option uses a new file optOut.js which shouldn’t be blocked by Apache

It changes

<FilesMatch "(^piwik\.(php|js)|robots\.txt)">

by

<FilesMatch "(^piwik\.(php|js)|^matomo\.(php|js)|robots\.txt|optOut.js)">

So here is the conf which work for me :slight_smile:

<Files "*">
 AuthType Basic
 AuthName "Authentication Required"
 # to be explicit, state the provider
 AuthBasicProvider file
 AuthUserFile "/etc/httpd/.htpasswd"
 Require valid-user
</Files>

# Allow external access to piwik.php and piwik.js and matomo.js and robots.txt
<FilesMatch "(^piwik\.(php|js)|^matomo\.(php|js)|robots\.txt|optOut.js)">
 Require all granted
</FilesMatch>

# Allow Opt-Out
<Files "index.php">
 <If "(%{QUERY_STRING} =~ /^module\=CoreAdminHome\&action\=optOut/)">
   Require all granted
 </If>
</Files>

I kept the reference to ^piwik\.(php|js) just in case …

1 Like

For the Matomo Tag Manager as we’ll, you may need to allow the “container_xxx.js” as well.

<FilesMatch "(^piwik\.(php|js)|^matomo\.(php|js)|^container_.*\.js|robots\.txt|optOut.js)">
 Require all granted
</FilesMatch>

Even if this is an old post, in the How to configure Matomo for security User Guide - Analytics Platform - Matomo Docs, still this post is linked. So i have fixed the security issue with Nginx, blocking all the requests via basic_auth, exect for the one needed to Matomo, even for the iframe.

  1. first do a map of $request_uri and populare a variable, in my case called $auth_basic
map $request_uri $auth_basic {
    default                                               "Restricted Area";
    ~*^/index\.php\?module=CoreAdminHome&action=optOut$   off;
    ~*^/piwik\.(js|php)|matomo\.(js|php)|container_.*\.js|robots\.txt$     off;
}

  1. place the basic auth in the nginx config, eg. like this:
.....
    auth_basic           $auth_basic;
    auth_basic_user_file /path/to/my/basic_auth_file; 
.....

thats it!

-all the request to matomo will get 401, all the requests to matomo.php , matomo.js , piwik.php , piwik.js , and also to the URL index.php?module=CoreAdminHome&action=optOut will be allowed with http code 200

enjoy

I tried a solution inspired by the Apache 2.4 suggestion of @goodspeedal at Using .htaccess to restrict access , modified to restrict Matomo by IP and only allow specific public files.

(note: I’ve replaced the server IP and my IP with placeholder text below)

<Files "*">
        # Allow localhost IPv4 IPv6
        Require ip 127.0.0.1 ::1
        # Allow server IPv4 IPv6
        Require ip <server_IPv4> <server_IPv6>
        # Allow my IP
        Require ip <my_IP>
</Files>

# Allow public access to basic Matomo files
<FilesMatch "(^piwik\.(php|js)|^matomo\.(php|js)|^container_.*\.js|robots\.txt|optOut.js)">
        Require all granted
</FilesMatch>

This example works fine for access from the browser, however, the auto-archiving cron job for Matomo fails… Even though the server IP and localhost are both allowed.

Any ideas to allow access for the archiving cron job, as well?

Not really sure your meaning, as the the crontab is using php to execute internal command without to go/request via the web, (neither related to Apache). So just follow the intructions to create crontab will be work.
https://matomo.org/docs/setup-auto-archiving/

The cron job parameter --url wants a URL, correct?

Manually performing the cron job outputs errors, a fragment mentioning the exact HTML content of a 403 Forbidden page (see below). When I comment out the Require ip ... from the .htaccess file, the cron job works fine.

Error: Got invalid response from API request: ?module=API&method=API.get&idSite=2&period=day&date=last2&format=php&trigger=archivephp. Response was '<!DOCTYPE html> <html lang="en"> <head>   <meta charset="utf-8">   <meta http-equiv="x-ua-compatible" content="ie=edge">   <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">   <title>403 Forbidden</title>   <link rel="stylesheet" href="/error_docs/styles.css"> </head> <body> <div class="page">   <div class="main">     <h1>Server Error</h1>     <div class="error-code">403</div>     <h2>Forbidden</h2>     <p class="lead">You do not have permission to access this document.</p>     <hr/>     <p>That's what you can do</p>     <div class="help-actions">       <a href="javascript:location.reload();">Reload Page</a>       <a href="javascript:history.back();">Back to Previous Page</a>       <a href="/">Home Page</a>     </div>   </div> </div> </body> </html>'

Hi,

The cron job does access the HTTP API, so I’d recommend you to look into the webserver log to see how exactly the rule is blocking the request (I know nothing about Apache, so I can’t be more specific)

Thanks Lukas, I’ve checked the Apache error_log for the domain and found that the HTTP API uses IP address 0.0.0.0, so I’ve changed my .htaccess to something like:

<Files "*">
        # Allow localhost IPv4 IPv6
        Require ip 127.0.0.1 ::1
        # Allow HTTP API
        Require ip 0.0.0.0
        # Allow admin IP
        Require ip <my_IP>
</Files>

# Allow public access to basic Matomo files
<FilesMatch "(^piwik\.(php|js)|^matomo\.(php|js)|^container_.*\.js|robots\.txt|optOut.js)">
        Require all granted
</FilesMatch>

Now it works without issues.

PS I probably won’t have to allow localhost, but it doesn’t hurt.