4

I got a virtualhost, which has some access restrictions configured like this:

<Location "/">
    AuthType Basic
    AuthName "Restricted Content"
    AuthUserFile /var/www/domain/htdocs/.htpasswd
    Require valid-user
</Location>

In addition to that, I have the following conf-file:

Alias /.well-known/acme-challenge/ "/var/www/letsencrypt/"

<Location /.well-known/acme-challenge/>
    # Security Options
    Options None
    AllowOverride None
    ForceType text/plain
    RedirectMatch 404 "^(?!/\.well-known/acme-challenge/[\w-]{43}$)"

    # Do not redirect to https or perform other rewrites
    RewriteEngine off

</Location>

I need /.well-known/acme-challenge/ to be accessible without auth.

I have already tried adding different variations of Require all granted to my conf-file, but to no avail.

How can I make /.well-known/acme-challenge/ accessible without authentication for all virtualhosts? (I do not want to modify any virtualhosts, this virtualhost is just an example).

Zulakis
  • 4,191
  • 14
  • 44
  • 75

2 Answers2

3

There is no possibility to override the <Location /> statement from your virtualhost-context in the server-context. From apache doc:

Sections inside <VirtualHost> sections are applied after the corresponding sections outside the virtual host definition. This allows virtual hosts to override the main server configuration.

The order of merging is (last merged group wins):

  1. <Directory> (except regular expressions) and .htaccess done simultaneously (with .htaccess, if allowed, overriding <Directory>)
  2. <DirectoryMatch> (and <Directory "~">)
  3. <Files> and <FilesMatch> done simultaneously
  4. <Location> and <LocationMatch> done simultaneously
  5. <If>

Apart from <Directory>, each group is processed in the order that they appear in the configuration files.

<VirtualHost> is not allowed inside <If> so <Location> is the last merged.

But

If you only serve the site in a https vhost (what would be reasonable, because of the authentication), you can do the following (without affecting your https vhost):

Apache v2.2

<VirtualHost *:80>
  ServerName example.com
  Include letsencrypt-well-known.conf
  RedirectMatch permanent ^(?!/\.well-known/acme-challenge/)(.*) "https://example.com$1"
</VirtualHost>

<VirtualHost *:443>
  ServerName example.com
  DocumentRoot /var/www/html
  <Location "/">
    AuthType Basic
    AuthName "Restricted Content"
    AuthUserFile /var/www/domain/htdocs/.htpasswd
    Require valid-user
  </Location>
  ...
</VirtualHost>

letsencrypt-well-known.conf:

<IfModule mod_proxy.c>
  ProxyPass /.well-known !
</IfModule>

Alias /.well-known/ /var/www/html/.well-known/

<Location /.well-known/acme-challenge>
  Options None
  Require all granted
</Location>

Apache v2.4

<Macro RedirectTo $protocol $domain>
  <If "'${well_known_enabled}' == 'On' && %{REQUEST_URI} =~ m#^/\.well-known(/|$)#">
    # Do nothing
  </If>
  <ElseIf "tolower(req('Host')) != '$domain' || tolower(%{REQUEST_SCHEME}) != '$protocol'">
    Redirect permanent / $protocol://$domain/
  </ElseIf>
</Macro>

<VirtualHost *:80>
  ServerName example.com
  Include letsencrypt-well-known.conf
  RedirectTo https example.com
</VirtualHost>

<VirtualHost *:443>
  ServerName example.com
  DocumentRoot /var/www/html
  <Location "/">
    AuthType Basic
    AuthName "Restricted Content"
    AuthUserFile /var/www/domain/htdocs/.htpasswd
    Require valid-user
  </Location>
  ...
</VirtualHost>

letsencrypt-well-known.conf:

<IfModule mod_proxy.c>
  ProxyPass /.well-known !
</IfModule>

Define well_known_enabled On
Define well_known_root "/var/www/html"

Alias /.well-known/ "${well_known_root}/.well-known/

<Directory "${well_known_root}/.well-known">
  Options None
  AllowOverride None
  Require all granted
</Directory>

<Location /.well-known/acme-challenge>
  Options None
  Require all granted
</Location>
rda
  • 1,887
  • 1
  • 12
  • 20
0

In Apache 2.4, you can add an Require expr statement to the first location block and evaluate the request URI, like so:

Require expr %{REQUEST_URI} =~ m#^/.well-known/acme-challenge/.*#

or something along that line (syntax not actually tested). The strange m# syntax is an alternative form for regexes to be able to use / in the string.

expr docs: https://httpd.apache.org/docs/2.4/expr.html

Sven
  • 97,248
  • 13
  • 177
  • 225
  • I am explicitly looking not to change the virtualhost (as noted in my question) :/ – Zulakis Dec 18 '16 at 21:02
  • 1
    @Zulakis: Then I believe you are out of luck. Citing the [docs](http://httpd.apache.org/docs/current/sections.html#merging): `Sections inside sections are applied after the corresponding sections outside the virtual host definition. This allows virtual hosts to override the main server configuration.` This means your `` block will override anything you put on a global level – Sven Dec 18 '16 at 21:17
  • Even if the non-virtualhost selector is more specific, I guess? Well, my question is looking for a solution that solves exactly this issue ;) – Zulakis Dec 18 '16 at 22:21
  • Yes, `Apart from , each group is processed in the order that they appear in the configuration files.` Is the VHost in question 443 or 80? – rda Dec 20 '16 at 17:21