linuxserver / docker-duplicati

GNU General Public License v3.0
303 stars 37 forks source link

[FEAT] Prepare for default encrypted setting with Docker #81

Open kenkendk opened 2 weeks ago

kenkendk commented 2 weeks ago

Is this a new feature request?

Wanted change

Support updates to Duplicati 2.0.9.105+ with encrypted settings.

Reason for change

With next canary release from Duplicati, the settings database is default encrypted, and if no key is supplied, it will derive the key from the machine serial number. For Docker setups, the underlying machine may change, causing the settings database to be lost. See issue #5420 and issue #5496.

Proposed code change

The easiest change is simply to add the default environment variable to the Docker file:

ENV DUPLICATI__DISABLE_DB_ENCRYPTION=true
ENV DUPLICATI__REQUIRE_DB_ENCRYPTION_KEY=true

The first one disables encryption, so the user needs to explicitly enable it, the second one prevents starting if no key is supplied (preventing use of the machine serial number as the key).

If there is some kind of persistent storage available, an alternative is to set the correct key, with something like:

ENV SETTINGS_ENCRYPTION_KEY=<persisted-key>
ENV DUPLICATI__REQUIRE_DB_ENCRYPTION_KEY=true
github-actions[bot] commented 2 weeks ago

Thanks for opening your first issue here! Be sure to follow the relevant issue templates, or risk having this issue marked as invalid.

thespad commented 2 weeks ago

So my thinking is we set DUPLICATI__REQUIRE_DB_ENCRYPTION_KEY=true in the Dockerfiles and then on init do something like

if [[ -f "/config/Duplicati-server.sqlite" ]]; then
    # Existing install
    if [[ -n ${SETTINGS_ENCRYPTION_KEY} ]]; then
        # Enable encryption
        true
    else
        # Disable encryption
        printf "true" > /run/s6/container_environment/DUPLICATI__DISABLE_DB_ENCRYPTION
        echo "***      Missing encryption key, unable to encrypt your settings database     ***"
        echo "*** Please set a value for SETTINGS_ENCRYPTION_KEY and recreate the container ***"
    fi
else
    # New install
    if [[ -n ${SETTINGS_ENCRYPTION_KEY} ]]; then
        # Enable encryption
        true
    else
        # Halt init
        echo "***      Missing encryption key, unable to encrypt your settings database     ***"
        echo "*** Please set a value for SETTINGS_ENCRYPTION_KEY and recreate the container ***"
        sleep infinity
    fi
fi

Does that seem sensible?

thespad commented 2 weeks ago

Also is there a max length for the key?

kenkendk commented 1 week ago

The changes here and in PR #84 looks good to me. As I commented on the PR, we rolled back the idea of using the deviceId as a key, so now there is either no key or a user supplied key.

With 2.0.9.106 you can skip the differentiation between new and existing install, unless you want to force users to make a choice. If neither DUPLICATI__DISABLE_DB_ENCRYPTION and SETTINGS_ENCRYPTION_KEY are set, a warning will appear in the logs.

If we (meaning the Duplicati team) at some point find a credible source for a system-derived encryption key, I will make a new issue.

For the key length: there is a minimum length of 8 characters, but no max. I think the code will handle up to 4GiB, but you will likely hit the environment key limits before that.

thespad commented 1 week ago

Cool, we'll stick with the code we've got in the PRs because it covers us if there are upstream changes later that we don't react to fast enough and it still encourages existing users to set an encryption key.