What actual is
I have a server(EX42) and a storage box (BX21) both hosted at Hetzner. On the server runs a peertube instance and I want to save the data on the storage box.
I installed sshfs
on my Debian 10 root server and mounted the storage box:
/etc/fstab
:
<user>@<user>.your-storagebox.de:/data /peertube/data fuse.sshfs ssh_command=sshpass\040-f\040/peertube/sftp.pass\040ssh,uid=999,gid=999,allow_other,disable_hardlink,transform_symlinks,reconnect,_netdev 0 0
I mounted the filesystem with the following options regarding symlinks:
-o disable_hardlink
link(2) will return with errno set to ENOSYS. Hard links
don't currently work perfectly on sshfs, and this confuses
some programs. If that happens try disabling hard links
with this option.
-o transform_symlinks
transform absolute symlinks to relative
Then I start Peertube inside of docker and mount the folder into this container
peertube:
volumes:
- assets:/app/client/dist
- /peertube/data/peertube:/data
- /peertube/data/config:/config
networks:
- default
The problem
I run a peertube instance with docker and tried to install a plugin with this command:
$: NODE_ENV=production NODE_CONFIG_DIR=/config yarn plugin:install -n peertube-plugin-chapters
The output showed that there is an error with creating a symlink
yarn run v1.22.17
...
2022-03-29 09:35:16.286 error: Cannot install plugin peertube-plugin-chapters, removing it... {
"err": {
"err": {
"stack": "Error: Command failed: yarn add [email protected]\nwarning package.json: No license field\nwarning No license field\nerror An unexpected error occurred: \"EIO: i/o error, symlink '../../../marked/bin/marked' -> '/data/plugins/node_modules/peertube-plugin-chapters/node_modules/.bin/marked'\".\n\n at ChildProcess.exithandler (node:child_process:399:12)\n at ChildProcess.emit (node:events:526:28)\n at ChildProcess.emit (node:domain:475:12)\n at maybeClose (node:internal/child_process:1092:16)\n at Process.ChildProcess._handle.onexit (node:internal/child_process:302:5)",
"message": "Command failed: yarn add [email protected]\nwarning package.json: No license field\nwarning No license field\nerror An unexpected error occurred: \"EIO: i/o error, symlink '../../../marked/bin/marked' -> '/data/plugins/node_modules/peertube-plugin-chapters/node_modules/.bin/marked'\".\n",
"killed": false,
"code": 1,
"signal": null,
"cmd": "yarn add [email protected]"
},
"stdout": "[1/4] Resolving packages...\n[2/4] Fetching packages...\n[3/4] Linking dependencies...\ninfo If you think this is a bug, please open a bug report with the information provided in \"/data/plugins/yarn-error.log\".\ninfo Visit https://yarnpkg.com/en/docs/cli/add for documentation about this command.\n",
"stderr": "warning package.json: No license field\nwarning No license field\nerror An unexpected error occurred: \"EIO: i/o error, symlink '../../../marked/bin/marked' -> '/data/plugins/node_modules/peertube-plugin-chapters/node_modules/.bin/marked'\".\n"
}
}
...
{
err: Error: Command failed: yarn add [email protected]
warning package.json: No license field
warning No license field
error An unexpected error occurred: "EIO: i/o error, symlink '../../../marked/bin/marked' -> '/data/plugins/node_modules/peertube-plugin-chapters/node_modules/.bin/marked'".
at ChildProcess.exithandler (node:child_process:399:12)
at ChildProcess.emit (node:events:526:28)
at ChildProcess.emit (node:domain:475:12)
at maybeClose (node:internal/child_process:1092:16)
at Process.ChildProcess._handle.onexit (node:internal/child_process:302:5) {
killed: false,
code: 1,
signal: null,
cmd: 'yarn add [email protected]'
},
stdout: '[1/4] Resolving packages...\n' +
'[2/4] Fetching packages...\n' +
'[3/4] Linking dependencies...\n' +
'info If you think this is a bug, please open a bug report with the information provided in "/data/plugins/yarn-error.log".\n' +
'info Visit https://yarnpkg.com/en/docs/cli/add for documentation about this command.\n',
stderr: 'warning package.json: No license field\n' +
'warning No license field\n' +
`error An unexpected error occurred: "EIO: i/o error, symlink '../../../marked/bin/marked' -> '/data/plugins/node_modules/peertube-plugin-chapters/node_modules/.bin/marked'".\n`
}
error Command failed with exit code 255.
But when I look inside that folder, I can see the symlink was created and working
$: ls -la /data/plugins/node_modules/peertube-plugin-chapters/node_modules/.bin/
total 12
drwxr-xr-x 1 peertube peertube 3 Mar 29 09:35 .
drwxr-xr-x 1 peertube peertube 3 Mar 29 09:35 ..
lrwxr-xr-x 1 peertube peertube 26 Mar 29 09:35 marked -> ../../../marked/bin/marked
$: cat /data/plugins/node_modules/peertube-plugin-chapters/node_modules/.bin/marked
#!/usr/bin/env node
/**
* Marked CLI
* Copyright (c) 2011-2013, Christopher Jeffrey (MIT License)
*/
const fs = require('fs'),
path = require('path'),
marked = require('../');
/**
* Man Page
*/
function help() {
const spawn = require('child_process').spawn;
const options = {
cwd: process.cwd(),
env: process.env,
....
So I tried it myself inside the container with creating a file, symlink it, and modify it
$: echo "Hello" > /data/plugins/hello
$: cat /data/plugins/hello
Hello
----
$: ln -s /data/plugins/hello /data/plugins/hello_link
ln: failed to create symbolic link '/data/plugins/hello_link': Input/output error
----
$: cat /data/plugins/hello_link
Hello
----
$: echo "World" >> /data/plugins/hello_link
----
$: cat /data/plugins/hello
Hello
World
----
$: ls -la /data/plugins/
total 40
drwxr-xr-x 1 peertube peertube 10 Mar 29 09:38 .
drwxr-xr-x 1 peertube peertube 16 Mar 29 06:32 ..
drwxr-xr-x 1 peertube peertube 2 Mar 28 16:48 .DAV
drwxr-xr-x 1 peertube peertube 3 Mar 28 16:48 data
-rw-r--r-- 1 peertube peertube 12 Mar 29 09:38 hello
lrwxr-xr-x 1 peertube peertube 5 Mar 29 09:38 hello_link -> hello
drwxr-xr-x 1 peertube peertube 6 Mar 29 06:35 node_modules
-rw-r--r-- 1 peertube peertube 76 Mar 28 16:48 package.json
-rw-r--r-- 1 peertube peertube 1248 Mar 29 09:35 yarn-error.log
-rw-r--r-- 1 peertube peertube 413 Mar 28 16:48 yarn.lock
The ln -s
command throws an error, but otherwise everything looks fine and works as expected.
What I tried
I also tried to mount the storage with this option
-o follow_symlinks
follow symlinks on the server
but all that does was breaking files, and I couldn't delete them anymore, when the link target file was not existing anymore. So, I removed this option again.
I asked the customer support if symlink is supported, and the answer was "yes it is supported".
When I create symlinks on the server directly, it works without problems.
I tried to mount the folder inside of the container at the same folder as on the server
/etc/fstab
:
<user>@<user>.your-storagebox.de:/data /var/peertube/data fuse.sshfs ssh_command=sshpass\040-f\040/peertube/sftp.pass\040ssh,uid=999,gid=999,allow_other,disable_hardlink,transform_symlinks,reconnect,_netdev 0 0
peertube:
volumes:
- assets:/app/client/dist
- /var/peertube/data:/var/peertube/data
- /peertube/data/config:/config
networks:
- default
but this didn't help.
The question
It appears to me that, as soon as I mount the sshfs inside a docker container, it can't create any symlinks without this error message.
What do I need to do to get it to work inside of docker?