Howto setup permissions for plugins dir

I’m running KanBoard in a docker container. I have enabled the “Customizer” plugin. I can uploaded new logo, there is no error message. But it only displays a broken image.

The docker log log shows this:

2019/03/29 13:29:29 [error] 17#17: *29797 FastCGI sent in stderr: “PHP message: PHP Warning: file_put_contents(plugins/Customizer/Assets/css/theme.css): failed to open stream: Permission denied in /var/www/app/plugins/Customizer/Plugin.php on line 37” while reading response header from upstream, client:, server: localhost, request: “GET /?controller=UserAjaxController&action=status HTTP/1.1”, upstream: “fastcgi://unix:/var/run/php-fpm.sock:”, host: “”

I have three questions:

  1. Which directory should have write access to what user? I was trying to find this info on the kanban/kanban official docker image page but there is nothing useful about this ( )

  2. Shouldn’t the Customizer plugin detect that there was a file upload, and issue an error message about that? Actually it says that the file was successfully uploaded (but it was not)

  3. Would it be possible for users to select their own theme? E.g. on a per user bases, after they are logged in,

your plugins folder and data folder should be read/write. This issue may help:

If it says it did, then it did. You might not know where to look. It would no longer be named what you uploaded it as. It utilitizes the database and file upload controller components already in kanboard.

No. Only an admin can change the theme, and it is global.

Welcome to play with it:

u: admin
pw: admin

This is also running in a docker container.

Thank your for your answers! I’m a bit concerned, because the plugin writes files in a directory that also contains PHP files. Would it be more secure to allow uploads to a directory that is completely separated from PHP files? (This is not a very important question though.)

About the permissions: I have figured out that php fcgi runs as uid=100 and gid=100 in the docker container. After I did “chown -R 100:100 plugins” the upload errors disappeared from the logs, and I could change colors and upload files. (In the bacground it called file_put_contents on a css file.) The official page of the kanban/kanban docker image should really tell something about these uid and guid values. Most users will use mounted volumes for the plugins directory, and it would be better if they knew in advance that they must set uid=100 and guid=100.

I’m telling you, there was a file_put_contents/permission denied log message in the docker container log, and the Customizer plugin displayed a green (file successfully uploaded) notification at the same time. This is a fact. I can reproduce and create a new issue on github if you want to investigate. Just I’m not sure if I should post this to the KanBoard project or the Customizer project.

And finally: even though the errors in the logs disappeared, I still can’t change my logo. The upload suceeds, but a broken image symbol is displayed instead of the logo itself.

This is how it looks:


The relative URL for the logo is:


If I open this URL then I get HTTP 200 with image/jpeg content type, but my firefox says that it is a 0x0 jpeg image (probably it received nothing or garbage). There is nothing about this in the docker container logs.

Not that I am aware of. Images are uploaded to the Data Folder, DATA_DIR\files\customizer\..., the same place all kanboard files are uploaded to.
The theme.css is contained in an assets folder. That said, I’m not a security buff.

I don’t dispute that fact, but the log you referenced was not related to file upload.
PHP message: PHP Warning: file_put_contents(plugins/Customizer/Assets/css/theme.css)
It was related to you not having permission in the plugin folder, which is where the css is rewritten every time you change the theme.
If you have other logs, that might help.

My guess is you don’t have the correct permissions to the DATA_DIR or your DATA_DIR constant in the config.php of Kanboard is incorrect.

another clue is, file_id=11

Customizer cleans itself up, and there should never be more than 3 files. I can see file_id=4 maybe 5, but 11 is pretty high, it’s telling me that it either doesn’t have permissions to remove the files, or it can’t find them.

You could also check the customizer_files table in the DB.


96444767a622 kanboard/kanboard:v1.2.8 "/usr/local/bin/entr…" 6 days ago Up 4 days 80/tcp, 443/tcp kanboard

It was created with:

   docker run -d -t \
        --name kanboard \
        --network kanboard \
        --ip \
        -v /docker/kanboard/data:/var/www/app/data \
        -v /docker/kanboard/plugins:/var/www/app/plugins \
        --env-file $(pwd)/envfile \

Permissions for data and plugin dirs:

root@nkp:~# ls -lanh /docker/kanboard
total 24K
drwxr-xr-x  6   0   0 4.0K Mar 29 14:21 .
drwxr-xr-x  9   0   0 4.0K Mar 23 11:46 ..
drwxr-xr-x  3 100 101 4.0K Mar 25 09:14 data
drwx------ 19 999   0 4.0K Mar 23 13:09 db
drwxr-xr-x  8 100 101 4.0K Mar 29 14:24 plugins

It is the same for all files inside plugins and data (chown -R 100:101 /docker/kanboard/plugins). (The db directory is for a PostgreSQL that is provided for kanban and it is working fine.)

The kanboard/kanboard container runs php fgci with nginx, and indeed the nginx uid and guid is 101:100

# docker exec -ti kanboard grep nginx /etc/passwd

It seems that some files have been uploaded, because

I can see this under /docker/kanboard/data/files/customizer, before uploading a test file called 100.jpg:

# ls -R
1  2  3  themes





I have been watching the logs with this command:

# docker logs -f kanboard

When I upload the logo file, then there is no new message in the log. The UI display this:

After the upload, there are no new files under /docker/kanboard/data/files/customizer. If it was really uploaded, then it went somewhere else.

What else should I test?

Thank you,


These are your files. The ff7bf4430e505423a9867b11fa45db6ef590360c is your header , e295b88ed734a89b4185868e7f129850671c0fac is your login logo 2bdba66919db3dc94f9f4231e11c13c7cd4f2df7 is your favicon.

When you upload them, this is what the become. You will not find 100.jpg anywhere.


root@site:/docker/kanboard/data/files/customizer# docker exec -ti kanboard-db psql -U postgres -d kanboard -c "select * from customizer_files "
 id | custom_id |       name       |                         path                          | is_image | size | user_id |    date
 12 |         3 | site_logo_100.jpg | customizer/3/2bdba66919db3dc94f9f4231e11c13c7cd4f2df7 | t        | 6523 |       2 | 1553866573
 13 |         2 | favicon.png      | customizer/2/e295b88ed734a89b4185868e7f129850671c0fac | t        | 4299 |       2 | 1553866604
 14 |         1 | 100.jpg          | customizer/1/abf4e46b66d46c14bc6a942311231d3a1755b4a9 | t        | 4365 |       2 | 1553889608
(3 rows)

yes, see they are there, and they have sizes.

Okay, so they are uploaded and stored. But it is still not displayed. The SRC attribute for the logo is:


If I replace file_id=11 with file_id=1 or 2 or 3 then I get HTTP 500 internal error and this log:

2019/03/29 20:12:47 [error] 17#17: *31116 FastCGI sent in stderr: "PHP message: PHP Fatal error:  Uncaught TypeError: Argument 1 passed to Kanboard\Plugin\Customizer\Controller\CustomizerFileController::renderFileWithoutCache() must be of the type array, null given, called in /var/www/app/plugins/Customizer/Controller/CustomizerFileController.php on line 207 and defined in /var/www/app/plugins/Customizer/Controller/CustomizerFileController.php:70
Stack trace:
#0 /var/www/app/plugins/Customizer/Controller/CustomizerFileController.php(207): Kanboard\Plugin\Customizer\Controller\CustomizerFileController->renderFileWithoutCache(NULL, 'image/jpeg')
#1 /var/www/app/app/Core/Controller/Runner.php(77): Kanboard\Plugin\Customizer\Controller\CustomizerFileController->image()
#2 /var/www/app/app/Core/Controller/Runner.php(31): Kanboard\Core\Controller\Runner->executeController()
#3 /var/www/app/index.php(9): Kanboard\Core\Controller\Runner->execute()
#4 {main}
  thrown in /var/www/app/plugins/Customizer/Controller/CustomizerFileController.php on line 70" while reading response header from upstream, client:, server: localhost, request: "GET /?controller=CustomizerFileController&action=image&plugin=customizer&file_id=1 HTTP/1.1", upstream: "fastcgi://unix:/var/run/php-fpm.sock:", host: ""

Something is still wrong.

The SRC attribute for the logo WAS, not is.

Looking at your DB, id 11 is no longer in your DB. That number keeps going up, everytime you upload a file. It should not being do that.

Yes, you are right. After the upload, the logo src has changed to file_id=14. I’m going to paste the full link to the url below for the logo.

You can check the request and the response yourself. The response is HTTP 200, but it I’m not able to display it as an image.

I think that the reply has HTTP 200 and Content-Type: image/jpeg, but the contents of that is a HTML page. Very strange.

Give me sometime, I’ll try and duplicate your container and see if I can replicate your issue. I’m not going to solve it by shooting in the dark.

Well, I can only thank you. You are very responsive. I don’t know how to thank you. :slight_smile:

FYI here is the list of installed plugins:

Bigboard Calendar Customizer Gantt OAuth2 Timetrackingeditor

It may matter.

Your mounted volumes match mine in permissions:
drwxr-xr-x 4 0 0 4.0K Nov 8 2017 .
drwxr-xr-x 3 0 0 4.0K Nov 8 2017 …
drwxr-xr-x 3 100 101 4.0K Mar 29 08:00 data
drwxr-xr-x 16 100 101 4.0K Jan 14 18:15 plugins

Could you try switching to sqlite for a moment, lets rule out DB. Just change it in the config, it will reset all the stored info, but it will all return when you switch back to postgres.

After swtiched to sqlite, I could upload a new logo and it is displayed. I have also tried to upload another one and it also worked.

I cannot just replace my PostgreSQL database with a new one, because it already has live data.

This table has default id value of nextval('customizer_files_id_seq'::regclass) I would expect it to increase when a new row is inserted.

# docker exec -ti kanboard-db psql -U postgres -d kanboard
psql (10.2 (Debian 10.2-1.pgdg90+1))
Type "help" for help.

kanboard=# \d customizer_files
                                     Table "public.customizer_files"
  Column   |          Type          | Collation | Nullable |                   Default
 id        | integer                |           | not null | nextval('customizer_files_id_seq'::regclass)
 custom_id | integer                |           | not null |
 name      | character varying(255) |           | not null |
 path      | character varying(255) |           | not null |
 is_image  | boolean                |           |          | false
 size      | integer                |           | not null | 0
 user_id   | integer                |           | not null | 0
 date      | integer                |           | not null | 0
    "customizer_files_pkey" PRIMARY KEY, btree (id)


it deletes before it adds, not adds before it deletes.

if you don’t mind, adding it to the issue tracker, and I will look for the issue.