Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for docker secrets on first initialization broken #1148

Open
AlexCherrypi opened this issue Jun 10, 2020 · 22 comments · May be fixed by #2280
Open

Support for docker secrets on first initialization broken #1148

AlexCherrypi opened this issue Jun 10, 2020 · 22 comments · May be fixed by #2280
Labels
bug feature: auto config (Docker secrets) feature: installing First run / fresh installation needs review Needs confirmation this is still happening or relevant

Comments

@AlexCherrypi
Copy link
Contributor

AlexCherrypi commented Jun 10, 2020

Unfortunately the problem described in #385 reappeared again...
The exact thing happens, that I describe in my comment on #385

Unfortunately this seems to be broken again...

Unknown

When built with this docker-compose . yaml it still asks for database configuration. If built with an inline password on the other hand, it works like intended.

---
version: '3.3'

services:
nextcloud-db:
image: mariadb
container_name: nextcloud-db
command: --transaction-isolation=READ-COMMITTED --log-bin=ROW
networks:
- nextcloud-db
restart: always
environment:
MYSQL_ROOT_PASSWORD_FILE: /run/secrets/mysql_root_password
MYSQL_PASSWORD_FILE: /run/secrets/mysql_user_password
 // commented out // MYSQL_PASSWORD: 345Test
MYSQL_DATABASE: nextcloud
MYSQL_USER: nextcloud
MYSQL_INITDB_SKIP_TZINFO: 1
secrets:
- mysql_root_password
- mysql_user_password
--truncated--

nextcloud-app:
image: nextcloud
container_name: nextcloud-app
restart: always
depends_on:
- nextcloud-db
environment:
MYSQL_HOST: nextcloud-db
MYSQL_USER: nextcloud
MYSQL_DATABASE: nextcloud
MYSQL_PASSWORD_FILE: /run/secrets/mysql_user_password
// commented out // MYSQL_PASSWORD: 345Test
secrets:
- mysql_user_password
--truncated--

secrets:
mysql_root_password:
file: /opt/docker/secrets/mysql_root_password
mysql_user_password:
file: /opt/docker/secrets/mysql_user_password`

I would be very glad if someone might help me or point me in the right direction!

AlexCherrypi pushed a commit to AlexCherrypi/docker-homelab that referenced this issue Jun 10, 2020
@0x326
Copy link

0x326 commented Aug 1, 2020

Can confirm. Using POSTGRES_PASSWORD_FILE results defaults to the SQLite database whereas using POSTGRES_PASSWORD auto-configures the database properly

@isdnfan
Copy link

isdnfan commented Oct 9, 2020

@ptoulouse in reply to #1201 states NEXTCLOUD_ADMIN_USER and NEXTCLOUD_ADMIN_PASSWORD are absolutely necessary to make DB auto-config work..

@iFreilicht
Copy link

iFreilicht commented May 10, 2021

I can confirm this! It works perfectly when using regular environment variables, but not when using the _FILE suffix, despite what the documentation says.

@isdnfan I tried that as well, but couldn't reproduce the issue. For me it's working perfectly fine when specifying the values directly in environment variables, and doesn't work at all when a single one of them has the _FILE suffix. The ADMIN variables have no influence on this.

EDIT: Which is very weird, as the docker-entrypoint.sh suggests that the ADMIN variables are indeed a must. Maybe my setup wasn't entirely clean. I'll try again another day.

@tushev
Copy link
Contributor

tushev commented Jun 14, 2021

Any updates?

Currently, with 21.0.2, specifying _FILE secrets works only if NEXTCLOUD_ADMIN_USER and NEXTCLOUD_ADMIN_PASSWORD are provided.

Without _FILE secrets (specifying MYSQL_PASSWORD etc directly in docker-compose) DB autoconfigure works even if ADMIN variables are not set.

@tushev
Copy link
Contributor

tushev commented Jun 14, 2021

Actually, everything works as intended (if I got the things correctly):

if [ -n "${NEXTCLOUD_ADMIN_USER+x}" ] && [ -n "${NEXTCLOUD_ADMIN_PASSWORD+x}" ]; then

MYSQL_PASSWORD_FILE will be read and loaded only if NEXTCLOUD_ADMIN_USER and NEXTCLOUD_ADMIN_PASSWORD are provided.

This happens because in this case Nextcloud is being installed via occ maintenance:install command.

Otherwise Nextcloud is not installed, and autoconfig.php is used:

} elseif (getenv('MYSQL_DATABASE') && getenv('MYSQL_USER') && getenv('MYSQL_PASSWORD') && getenv('MYSQL_HOST')) {

Autoconfig reads only ordinary MYSQL_PASSWORD etc environment variables, which do not exist.

Solution:

Change autoconfig.php so it will use docker secrets

Can anyone please do it? @J0WI @tilosp

@iFreilicht
Copy link

I'm actually not sure it's worth it. You can use a single .env file or multiple *.env files to get the same effect with a built-in mechanism: https://docs.docker.com/compose/environment-variables/

It seems more useful to deprecate the _FILE suffixes and recommend using *.env files instead.

@tushev
Copy link
Contributor

tushev commented Jun 15, 2021

Well, that seems to be good alternative as well. Probably the documentation should be updated.

btw, would the environment variables remain in the container? From security point of view, isn't it better to remove sensitive ones from the .env files after configuration has been complete?

@snigge
Copy link

snigge commented Jun 15, 2021

I do not agree that _FILE should be deprecated. It’s a security feature which allows passwords in the environment variables to be kept from log files, process tools and env dumps.

.env gives you similar features but the environment variables aren’t obfuscated inside the container.

@isdnfan
Copy link

isdnfan commented Jun 15, 2021

it's definitely bad idea to skip secrets in favor of ENV variables. It is much more secure to use secrets rather then variables and this way should become preferred or at least remain open.

whole story: https://diogomonica.com/2017/03/27/why-you-shouldnt-use-env-variables-for-secret-data/
Short version:

Overall, secrets in ENV variables break the principle of least surprise, are a bad practice, and will lead to the eventual leak of secrets.

@Ninos
Copy link

Ninos commented Aug 17, 2021

For docker swarm or kubernetes-users we still need the _FILE functionality, otherwise we share secrets/passwords in clear type.. See also:
https://docs.docker.com/engine/swarm/secrets/

I think it's enough to search for all *_FILE environments and write the password in the environment variable with removed _FILE from name:
e.g. MYSQL_PASSWORD_FILE = /run/secrets/db_password replaces/adds environment variable MYSQL_PASSWORD with content of /run/secrets/db_password.

So you have an easy fix and compatibility with old docker-compose (not using docker secrets & _FILE).

Sry I currently have no time creating a MR :(

@francois-pasquier
Copy link

Hi, don't take it wrong but I just tried to install the project by following the README and the _FILE functionality should be removed from the README if it's broken for the moment.

I was surprised to see an issue this old being the culprit in basically preventing an installation.

@J0WI
Copy link
Contributor

J0WI commented Nov 25, 2021

Does #1516 work for you?

@Pkuutn
Copy link

Pkuutn commented Nov 30, 2021

Issue is still relevant.

@J0WI
Copy link
Contributor

J0WI commented Nov 30, 2021

@Pkuutn did you apply the changes in #1516 locally?

@Pkuutn
Copy link

Pkuutn commented Dec 1, 2021

Nope I'm using "latest" images from Dockerhub.
Shouldn't this patch be applied to image or I should apply it locally and rebuild?

@J0WI
Copy link
Contributor

J0WI commented Dec 2, 2021

It's only available from DockerHub after docker-library/official-images#11418 is merged.

@PhilipWhiteside
Copy link

PhilipWhiteside commented Dec 11, 2021

From my testing I believe this to be resolved.

I may have overlooked it in the docs, but for anyone else struggling. The use of _FILE must apply to all the DB settings, not just the password. I had MYSQL_USER and MYSQL_DATABASE as plain text env variables. Only MYSQL_PASSWORD_FILE as _FILE. However, the check for using _FILE needs them all to be _FILE, so converting the plain text to secrets resolved the issue.

You can see here it uses && operators, where they all must be true, rather than on a per value check. Personally, I'm fine with having them all as secrets, there is no harm in that approach.

} elseif (getenv('MYSQL_DATABASE_FILE') && getenv('MYSQL_USER_FILE') && getenv('MYSQL_PASSWORD_FILE') && getenv('MYSQL_HOST')) {

      MYSQL_HOST: db
      MYSQL_USER_FILE: /run/secrets/db_username
      MYSQL_DATABASE_FILE: /run/secrets/db_name
      MYSQL_PASSWORD_FILE: /run/secrets/db_password

Unfortunately for me, you can't set permissions without swarm (I use simple docker compose), so I'd have to make them public files so the permissions inside the container allow 33/www-data to read them. This defeats the point of using secrets over env vars.

@DerFireWal
Copy link

Despite all the helpful comments on this topic I'm sill struggling to get the initialisation running.

Snippet from docker-compose.yml:

    environment:
      - NEXTCLOUD_ADMIN_USER_FILE=/run/secrets/nextcloudadmin
      - NEXTCLOUD_ADMIN_PASSWORD_FILE=/run/secrets/nextcloudadminpwd
      - MYSQL_PASSWORD_FILE=/run/secrets/mysqluserpwd
      - MYSQL_DATABASE_FILE=/run/secrets/mysqldb
      - MYSQL_USER_FILE=/run/secrets/mysqluser
      - MYSQL_HOST=nextcloud-mariadb
      ...

Secrets should be readable by www-data inside the Nextcloud container:

root@db35ebf5bc32:/var/www/html#` ls -l /run/secrets/
total 28
-rw-r--r-- 1 root root 10 Jan 10 22:40 mysqldb
-rw-r--r-- 1 root root 18 Jan 11 08:06 mysqlhost
-rw-r--r-- 1 root root 10 Jan 10 22:41 mysqluser
-rw-r--r-- 1 root root 17 Jan 10 20:48 mysqluserpwd
-rw-r--r-- 1 root root 19 Jan 10 23:28 nextcloudadmin
-rw-r--r-- 1 root root 31 Jan 10 23:29 nextcloudadminpwd
-rw-r--r-- 1 root root 13 Jan 10 20:48 smtppwd

Result in config.php:

...
  'dbname' => 'nextcloud',
  'dbhost' => 'nextcloud-mariadb',
  'dbport' => '',
  'dbtableprefix' => 'oc_',
...

Apparently dbuser and dbpassword are not parsed correctly.

Log output:

Initializing nextcloud 23.0.0.10 ...
Initializing finished
New nextcloud instance
Installing with MySQL database
starting nextcloud installation
Error while trying to create admin user: Failed to connect to the database: An exception occurred in the driver: SQLSTATE[HY000] [1045] Access denied for user 'nextcloud'@'nextcloud.nextcloud_nextcloud' (using password: YES)
Trace: #0 /var/www/html/lib/private/DB/ConnectionAdapter.php(69): OC\DB\Exceptions\DbalException::wrap(Object(Doctrine\DBAL\Exception))

I don't understand how the connection string is constructed. dbhostseems to be parsed correctly but isn't used during the DB connection.

All other configuration options set via environment settings or secrets are applied to the corresponding config files without issues (STMP Password..).

I'm aware that there are apparently some open issue regarding docker secrets.

@PhilipWhiteside Do I understand you correctly, that you got this to work (apart from your remark about secrets being readable for everyone)? Any hint on what I might be missing?

@PhilipWhiteside
Copy link

@PhilipWhiteside Do I understand you correctly, that you got this to work (apart from your remark about secrets being readable for everyone)? Any hint on what I might be missing?

I did not get secrets to work, as I do not use Docker Swarm just standalone Docker Compose. What I did instead was put the credentials as plain text into a .env file. This keeps them out of the compose file.

philip@nas~/appdata/nextcloud $ cat docker-compose.yml 
version: "3.9"

services:
  nextcloud:
  ...truncated output...
    environment:
      NEXTCLOUD_DATA_DIR: /data
      MYSQL_HOST: db
      MYSQL_USER: ${MYSQL_USERNAME}
      MYSQL_DATABASE: ${MYSQL_DATABASE}
      MYSQL_PASSWORD: ${MYSQL_PASSWORD}
      REDIS_HOST: ${APP_NAME}-cache
      NEXTCLOUD_TRUSTED_DOMAIN: ${NEXTCLOUD_DOMAIN_NAME}
      TRUSTED_PROXIES: traefik
  ...truncated output...

philip@nas~/appdata/nextcloud $ ll -a
total 24K
drwxrwx---  4 philip philip 4.0K Dec 12 16:28 .
drwxrwxr-x 15 philip philip 4.0K Jan 11 09:17 ..
drwxr-xr-x  4 philip philip 4.0K Dec 11 20:16 config
-rwxrwx---  1 philip philip 4.0K Dec 12 08:48 docker-compose.yml
-rwx------  1 philip philip  532 Dec 11 16:58 .env
drwxrwx---  2 philip philip 4.0K Dec 12 16:31 systemd
lrwxrwxrwx  1 philip philip    4 Dec 11 10:35 variables.env -> .env
philip@nas~/appdata/nextcloud $ cat variables.env 
APP_NAME=nextcloud
NEXTCLOUD_DOMAIN_NAME=nextcloud.lan
# Docker secrets does not support permissions without swarm. So have to be world readable. Using vars instead.
MYSQL_DATABASE=nextcloud
MYSQL_USERNAME=xxx
MYSQL_PASSWORD=yyy
MYSQL_ROOT_PASSWORD=zzz
philip@nas~/appdata/nextcloud $ 

@CamilleHbp
Copy link

CamilleHbp commented Nov 21, 2022

This is still broken. I've followed all the help given. This was very useful, thanks @PhilipWhiteside !

Everything is parsed correctly except for the db user. It prepends the dbtableprefix to the file path instead of prepending it to the username!

image

Any ideas, have I missed something?

EDIT:

Indeed, I had missed something. You also need to pass the NEXTCLOUD_ADMIN_PASSWORD and NEXTCLOUD_ADMIN_USER by file NOT in clear. ^^ I had forgotten to add the _FILE suffix.
These are the mandatory fields (for Postgres):
- NEXTCLOUD_ADMIN_PASSWORD_FILE
- NEXTCLOUD_ADMIN_USER_FILE
- POSTGRES_DB_FILE
- POSTGRES_HOST
- POSTGRES_PASSWORD_FILE
- POSTGRES_USER_FILE

Now I just have a Previous: PDOException: SQLSTATE[42501]: Insufficient privilege: 7 ERROR: permission denied for schema public LINE 1: CREATE TABLE oc_migrations error to fix

EDIT 2:

I could not find the info in the Docker container's documentation but you can only use Postgres 14, not the latest. This has fixed everything now, yay!

@joshtrichards joshtrichards added the needs review Needs confirmation this is still happening or relevant label Jun 18, 2024
@mabeett
Copy link
Contributor

mabeett commented Aug 18, 2024

Hello all,

The problem about accessing the secrets is directly related with secrets permissions, here the scenario:

The code these commits will only work while the www-data user in the container has access to the /run/secret/file_id, ( I mean user/group file permissions).

From what is see the compose-spec admits remaping the gid and uid for the secret, but

Note that the uid, gid, and mode attributes are implementation specific.
So, not supported in the compose plugin while supported by docker swarm.

At the end a demo.

The entrypoint in the image handles secrets files generating a VAR for VAR_FILE , and normally has no problem because it is running as root by default, but the logic in PHP code takes precedence searching for the file defined in the variables considered in the mentioned commits.

I'll be working during my spare time in order to honor the precedence of secrets files over variable definition, as indicated in the README, but from the entrypoint which is executed as root.
Other strategies could be applied ( cc @J0WI ).

About the dependency on NEXTCLOUD_ADMIN_USER ( or NEXTCLOUD_ADMIN_USER_FILE ), NEXTCLOUD_ADMIN_PASSWORD ( or NEXTCLOUD_ADMIN_PASSWORD_FILE ). the variables are a must in order to enter in the details of the installation (#2223, #1905,..)

https://github.com/nextcloud/docker/blob/75e1b80ba4d448e9bc82876d0be826e9c7fa2c9a/docker-entrypoint.sh#L190-L250

demo

Files:

```sh $ ls -ln total 12 -rw-r--r-- 1 1000 1000 1119 Aug 18 17:30 docker-compose.yml -rw------- 1 1000 1000 20 Aug 18 17:08 mysql_root_password -rw------- 1 1000 1000 20 Aug 18 17:08 mysql_user_password ```

docker-compose.yml

---
version: '3.3'

services:
  nextcloud-db:
    image: mariadb
    container_name: nextcloud-db
    command: --transaction-isolation=READ-COMMITTED --log-bin=ROW
      # networks:
      #   - nextcloud-db
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD_FILE: /run/secrets/mysql_root_password
      MYSQL_PASSWORD_FILE: /run/secrets/mysql_user_password
      # // commented out // MYSQL_PASSWORD: 345Test
      MYSQL_DATABASE: nextcloud
      MYSQL_USER: nextcloud
      MYSQL_INITDB_SKIP_TZINFO: 1
    secrets:
      - mysql_root_password
      - mysql_user_password
  nextcloud-app:
    image: nextcloud
    container_name: nextcloud-app
    restart: always
    depends_on:
      - nextcloud-db
    ports:
      - 80:80
    environment:
      MYSQL_HOST: nextcloud-db
      MYSQL_USER: nextcloud
      MYSQL_DATABASE: nextcloud
      MYSQL_PASSWORD_FILE: /run/secrets/mysql_user_password
      # // commented out // MYSQL_PASSWORD: 345Test
    secrets:
      - mysql_user_password

secrets:
  mysql_root_password:
    file: ./mysql_root_password
  mysql_user_password:
    file: ./mysql_user_password

Execution

$ docker compose up -d 
WARN[0000] /home/debian/nextcloud/nc2/docker-compose.yml: the attribute `version` is obsolete, it will be ignored, please remove it to avoid potential confusion 
[+] Running 3/3
 ✔ Network nc2_default      Created                                                                                                                                                                                                                                0.1s 
 ✔ Container nextcloud-db   Started                                                                                                                                                                                                                                2.3s 
 ✔ Container nextcloud-app  Started
 $ docker compose exec -it nextcloud-app /bin/bash -c  'curl -q http://localhost/'  > /dev/null
WARN[0000] /home/debian/nextcloud/nc2/docker-compose.yml: the attribute `version` is obsolete, it will be ignored, please remove it to avoid potential confusion 
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  6655  100  6655    0     0   5903      0  0:00:01  0:00:01 --:--:--  5905
$ docker compose exec -it nextcloud-app /bin/bash -c  'cat /var/www/html/data/nextcloud.log' 
WARN[0000] /home/debian/nextcloud/nc2/docker-compose.yml: the attribute `version` is obsolete, it will be ignored, please remove it to avoid potential confusion 
{"reqId":"UjaIPqzPiap1ZMsi7TG8","level":3,"time":"2024-08-18T17:50:30+00:00","remoteAddr":"127.0.0.1","user":"--","app":"PHP","method":"GET","url":"/","message":"fopen(/var/www/html/config/config.php): Failed to open stream: No such file or directory at /var/www/html/lib/private/Config.php#221","userAgent":"curl/7.88.1","version":"","data":{"app":"PHP"}}
$ docker compose exec -it nextcloud-app /bin/bash -c  'ps faxu' 
WARN[0000] /home/debian/nextcloud/nc2/docker-compose.yml: the attribute `version` is obsolete, it will be ignored, please remove it to avoid potential confusion 
USER         PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root         117  5.5  0.3   8100  3940 pts/0    Rs+  17:52   0:00 ps faxu
root           1  0.0  4.3 406012 43416 ?        Ss   17:49   0:00 apache2 -DFOREGROUND
www-data      92  0.0  1.0 406052 10348 ?        S    17:50   0:00 apache2 -DFOREGROUND
www-data      93  0.1  5.1 408640 51936 ?        S    17:50   0:00 apache2 -DFOREGROUND
www-data      94  0.0  1.0 406052 10348 ?        S    17:50   0:00 apache2 -DFOREGROUND
www-data      95  0.0  1.0 406052 10348 ?        S    17:50   0:00 apache2 -DFOREGROUND
www-data      96  0.0  1.0 406052 10348 ?        S    17:50   0:00 apache2 -DFOREGROUND
www-data     103  0.0  1.0 406052 10348 ?        S    17:50   0:00 apache2 -DFOREGROUND
$ docker compose exec -it nextcloud-app /bin/bash -c  'ls -l /run/secrets/' 
WARN[0000] /home/debian/nextcloud/nc2/docker-compose.yml: the attribute `version` is obsolete, it will be ignored, please remove it to avoid potential confusion 
total 4
-rw------- 1 1000 1000 20 Aug 18 17:08 mysql_user_password
$ docker compose exec -u www-data -it nextcloud-app /bin/bash -c  'cat /run/secrets/mysql_user_password' 
WARN[0000] /home/debian/nextcloud/nc2/docker-compose.yml: the attribute `version` is obsolete, it will be ignored, please remove it to avoid potential confusion 
cat: /run/secrets/mysql_user_password: Permission denied
{
  "reqId": "UjaIPqzPiap1ZMsi7TG8",
  "level": 3,
  "time": "2024-08-18T17:50:30+00:00",
  "remoteAddr": "127.0.0.1",
  "user": "--",
  "app": "PHP",
  "method": "GET",
  "url": "/",
  "message": "fopen(/var/www/html/config/config.php): Failed to open stream: No such file or directory at /var/www/html/lib/private/Config.php#221",
  "userAgent": "curl/7.88.1",
  "version": "",
  "data": {
    "app": "PHP"
  }
}

mabeett pushed a commit to mabeett/docker that referenced this issue Aug 18, 2024
Secrets files handled only in the entrypoint, converted during
initial execuition.

Solves nextcloud#1148
@mabeett mabeett linked a pull request Aug 18, 2024 that will close this issue
mabeett pushed a commit to mabeett/docker that referenced this issue Aug 18, 2024
Secrets files handled only in the entrypoint, converted during
initial execuition.

Solves nextcloud#1148

Signed-off-by: Matías Pecchia <[email protected]>
mabeett pushed a commit to mabeett/docker that referenced this issue Aug 18, 2024
Secrets files handled only in the entrypoint, converted during
initial execuition.

Solves nextcloud#1148

Signed-off-by: Matías Pecchia <[email protected]>
mabeett pushed a commit to mabeett/docker that referenced this issue Aug 18, 2024
Secrets files handled only in the entrypoint, converted during
initial execuition.

Solves nextcloud#1148

Signed-off-by: Matías Pecchia <[email protected]>
mabeett pushed a commit to mabeett/docker that referenced this issue Aug 18, 2024
Secrets files handled only in the entrypoint, converted during
initial execuition.

Solves nextcloud#1148

Signed-off-by: Matías Pecchia <[email protected]>
mabeett pushed a commit to mabeett/docker that referenced this issue Aug 18, 2024
Secrets files handled only in the entrypoint, converted during
initial execuition.

Solves nextcloud#1148

Signed-off-by: Matías Pecchia <[email protected]>
mabeett added a commit to mabeett/docker that referenced this issue Aug 18, 2024
Secrets files handled only in the entrypoint, converted during
initial execuition.

Solves nextcloud#1148

Signed-off-by: Matías Pecchia <[email protected]>
mabeett added a commit to mabeett/docker that referenced this issue Aug 18, 2024
Secrets files handled only in the entrypoint, converted during
initial execuition.

Solves nextcloud#1148

Signed-off-by: Matías Pecchia <[email protected]>
mabeett added a commit to mabeett/docker that referenced this issue Sep 4, 2024
Secrets files handled only in the entrypoint, converted during
initial execuition.

Solves nextcloud#1148

Signed-off-by: Matías Pecchia <[email protected]>
@mabeett
Copy link
Contributor

mabeett commented Sep 4, 2024

I created #2280 2 weeks ago, your feedback will be appreciated.

mabeett added a commit to mabeett/docker that referenced this issue Sep 22, 2024
Secrets files handled only in the entrypoint, converted during
initial execuition.

Solves nextcloud#1148

Signed-off-by: Matías Pecchia <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug feature: auto config (Docker secrets) feature: installing First run / fresh installation needs review Needs confirmation this is still happening or relevant
Projects
None yet
Development

Successfully merging a pull request may close this issue.