docker-library/httpd

WebDAV broken since Alpine 3.13

timschumi opened this issue ยท 18 comments

WebDAV requires a locking database, which gets created using the database driver previously known as apr-util-dbm_db. However, this package got removed by the Alpine developers and is neither included nor installable on any Alpine 3.13 based images or newer.

This results in a slightly confusing error message when trying to set up a WebDAV server using that image:

(20019)DSO load failed: AH00576: The DBM driver could not be loaded
The locks could not be queried for verification against a possible "If:" header.  [500, #0]
Could not open the lock database.  [500, #400]
(20019)DSO load failed: [client 172.21.0.7:37564] Could not open property database.  [500, #1]

As outlined in the Pull Request where the Alpine version was bumped to 3.13, Alpine switched to the ndbm database backend, which does not require this specific driver. Please consider making a similiar change to the Apache server that is built as a part of the alpine images to avoid relying on the missing driver.

Ah, I guess we probably need to add something like --with-ndbm to our ./configure arguments? Do you have a minimal example config / set of commands we can use to reproduce and/or are you willing to try adding that to a new build and testing whether it fixes the issue in your environment?

Adding --with-ndbm, --without-berkeley-db or --with-dbm=ndbm to the configure flags doesn't seem to make any difference, or at least I'm pretty sure that Apache just silently ignored these. The Pull Request also mentions that those were apr-util build options, so I'm not sure if those even apply here (since we appear to install apr-util from the Alpine repository).

I'll try to create a minimal configuration as soon as possible, so that you can test as well.

I now set up a slightly stripped down sample config that will reproduce the issue when queried using curl -X PUT http://localhost:8080/test (the error message mentioned above will show up in stdout/docker-compose logs):

docker-compose.yml
version: "3.6"

services:
  webdav:
    image: docker.io/httpd:alpine
    ports:
      - 8080:80
    volumes:
      - ./httpd.conf:/usr/local/apache2/conf/httpd.conf
httpd.conf
ServerRoot "/usr/local/apache2"

Listen 80

LoadModule mpm_event_module modules/mod_mpm_event.so
LoadModule authn_file_module modules/mod_authn_file.so
LoadModule authn_core_module modules/mod_authn_core.so
LoadModule authz_host_module modules/mod_authz_host.so
LoadModule authz_groupfile_module modules/mod_authz_groupfile.so
LoadModule authz_user_module modules/mod_authz_user.so
LoadModule authz_core_module modules/mod_authz_core.so
LoadModule access_compat_module modules/mod_access_compat.so
LoadModule auth_basic_module modules/mod_auth_basic.so
LoadModule reqtimeout_module modules/mod_reqtimeout.so
LoadModule filter_module modules/mod_filter.so
LoadModule mime_module modules/mod_mime.so
LoadModule log_config_module modules/mod_log_config.so
LoadModule env_module modules/mod_env.so
LoadModule headers_module modules/mod_headers.so
LoadModule setenvif_module modules/mod_setenvif.so
LoadModule version_module modules/mod_version.so
LoadModule unixd_module modules/mod_unixd.so
LoadModule dav_module modules/mod_dav.so
LoadModule status_module modules/mod_status.so
LoadModule dav_fs_module modules/mod_dav_fs.so
LoadModule dav_lock_module modules/mod_dav_lock.so
LoadModule dir_module modules/mod_dir.so
LoadModule alias_module modules/mod_alias.so

<IfModule unixd_module>
User daemon
Group daemon
</IfModule>

ServerAdmin you@example.com

<Directory />
    AllowOverride none
    Require all denied
</Directory>

DAVLockDB "/tmp/DavLockDB"
DocumentRoot "/usr/local/apache2/htdocs"
<Directory "/usr/local/apache2/htdocs">
    DAV on
    Options Indexes FollowSymLinks
    AllowOverride None
    Require all granted
</Directory>

ErrorLog /proc/self/fd/2
LogLevel warn

<IfModule log_config_module>
    LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
    LogFormat "%h %l %u %t \"%r\" %>s %b" common

    <IfModule logio_module>
      LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %I %O" combinedio
    </IfModule>

    CustomLog /proc/self/fd/1 common
</IfModule>

<IfModule mime_module>
    TypesConfig conf/mime.types

    AddType application/x-compress .Z
    AddType application/x-gzip .gz .tgz
</IfModule>

Switching docker.io/httpd:alpine for docker.io/httpd:latest successfully mitigates the database error, the new "permission denied" error is just happening because the server doesn't have permission to write into htdocs, but that is expected.

Nice, thank you! I was able to reproduce with this.

Interestingly, I was also able to reproduce using this against Alpine's own apache2 (+ apache2-webdav) package (which made me feel much better about how not-different our builds were), so we don't get to have any clues from them (however the maintainers there might have a better idea of what's wrong). ๐Ÿ˜…

(For testing against their packages, I had to adjust your configuration slightly to use ServerRoot "/var/www" and DocumentRoot "/var/www/localhost/htdocs" like their default does.)

https://gitlab.alpinelinux.org/alpine/aports/-/issues/12534 makes it sound like this might be expected ๐Ÿ˜ฉ

The fact that dbm_db has been removed is expected, but from what I grasped of the discussion in the Alpine 3.13 bump the idea was that a different DB backend got selected as default... (EDIT: For reference, the upstream change in question.)

Maybe it's time to build apr as well instead of relying on the Alpine prebuilt?

EDIT 2: Hmm, Wikipedia says that Debian also phased out usages of Berkeley DB, maybe we can learn something from them?

Debian is still pretty generous with their apr-util flags on ./configure: https://salsa.debian.org/apache-team/apr-util/-/blob/7ddc1edd77952cb5774f355a0e425e6de97f8dc0/debian/rules#L40-49

I'm not sure how we could do this any differently from Alpine by compiling apr-util ourselves though if Berkeley DB isn't available on Alpine?

I have to wonder if https://httpd.apache.org/docs/2.4/mod/mod_authn_dbm.html#authdbmtype is somehow related -- we don't have a way to choose which "type" / driver is used for DavLockDB (https://httpd.apache.org/docs/2.4/mod/mod_dav_fs.html#davlockdb).

Debian is still pretty generous with their apr-util flags on ./configure: https://salsa.debian.org/apache-team/apr-util/-/blob/7ddc1edd77952cb5774f355a0e425e6de97f8dc0/debian/rules#L40-49

More surprisingly, they do still use Berkeley DB. On closer inspection, it seems like they just stuck with version 5.3 forever, since only version 6.0 of the Berkeley DB and upwards are licensed under AGPL.

Regarding Alpine, now I'm not so sure why apr-utils-dbm_db was phased out, especially since all the dependencies that were removed in the "remove apr-util-db_dbm" commit (i.e. db-dev, db, etc.) are apparently still available in the package repository as of today (and at versions where the license change wouldn't have affected them in the fist place).

Maybe a full removal of Berkeley DB was drafted up, not carried through, but this patch somehow made it in without actually being needed?

In that case, compiling our own apr-utils with the Berkeley DB that Alpine still provides seems like a much more manageable task.

EDIT: Digging more into the archives, it wasn't directly removed because of the incompatible license, but rather deprecated because there is no maintained version of the Berkeley DB that is under a compatible license. So while just adding back bdb support would be a short-term solution, it probably won't be long until that doesn't work anymore either.

I'm not sure how we could do this any differently from Alpine by compiling apr-util ourselves though if Berkeley DB isn't available on Alpine?

I missed that Berkeley DB also depends on an entirely seperate (generic) package. I assumed it was self-contained inside the apr-utils build.

I tested a bit further, and it seems like apr-util simply doesn't care that we neither enabled --with-ndbm during configuration nor that we don't have the necessary ndbm headers installed, and just continues with a nonexistent database backend anyways.

Although, at this point this is a general Alpine issue, so I'm going to raise that issue with them.

EDIT: For reference: https://gitlab.alpinelinux.org/alpine/aports/-/issues/13112

So I guess we should probably close this, right?
(Since there's not really something we can/would do to fix it? ๐Ÿ™ˆ)

I guess so, unless we want to dive into building the package ourselves (but I don't think that we want to).

Yeah, unfortunately agreed; thanks โค๏ธ

This is unfortunately still a problem with httpd:2.4-alpine. Going to have to switch to the 2.4-bullseye image.

KEMBL commented

@neingeist
httpd:2.4.54-bullseye gives me the same:

BDB0004 fop_read_meta: /var/lib/dav/DavLock: unexpected file type or format
BDB0004 fop_read_meta: /var/lib/dav/DavLock: unexpected file type or format
[dav:error] The locks could not be queried for verification against a possible "If:" header.  [500, #0]
[dav:error] Could not open the lock database.  [500, #400]
[dav:error] (120013)APR does not understand this error code: Could not open property database.  [500, #1]

@neingeist httpd:2.4.54-bullseye gives me the same:

BDB0004 fop_read_meta: /var/lib/dav/DavLock: unexpected file type or format
BDB0004 fop_read_meta: /var/lib/dav/DavLock: unexpected file type or format
[dav:error] The locks could not be queried for verification against a possible "If:" header.  [500, #0]
[dav:error] Could not open the lock database.  [500, #400]
[dav:error] (120013)APR does not understand this error code: Could not open property database.  [500, #1]

Hmm. I'm now running an image based on httpd:2.4-bullseye without this issue. My config contains this, however:

DavLockDB "/usr/local/apache2/var/DavLock"

Still a problem here with the latest bookworm image (2.4.58-bookworm)

Is there a workaround to fix this?

Still a problem here with the latest bookworm image (2.4.58-bookworm)

If it's not an Alpine image, it's not this issue.