# i proofing folder structure

## ozzy468

hi all,

is there any way to preserve a linux folder structure. I set up a NAS/Streaming-Server-like box for a friend. The streaming server bind mounts a lot of folders, and crashes, if those are removed.

I did my best, to put some write-protected .keep files (root) into those folders, and I mentioned about 15 times, not to delete these folders. Sadly, some file managers (nautilus? or so) move folders to "trash" if you try to delete them.

So I have not found a way to prevent "moving". 

The box is configured on a "have you turned it off and back on again" level.

So is there any way, to preserve the given folder structure,

or recreate the structure on boot

Thanks

----------

## figueroa

Maybe chattr:

```
chattr +i filename
```

This makes the file immutable. If I make an ordinary file that I own immutable, I cannot move it, even as root. Try it for your use case and report back.

----------

## ozzy468

hi,

thanks for your reply. 

This won't prevent the user to move the folder. Let's say I have

chattr +i /home/user/folder/.keep, the user can still move folder to 

/home/user/.somefilemanager/Trash/

I'm thinking, if I can't prevent the user from shuffling folders, is there a way to create folders in an early stage. The bind mounts are done by docker, which starts at runlevel default.

----------

## pjp

Set it on the 'folder' directory: 

```
$ mkdir tmp

$ /usr/bin/sudo /usr/bin/chattr +i tmp

$ rmdir tmp/

rmdir: failed to remove 'tmp/': Operation not permitted

$ mv tmp/ ..

mv: cannot move 'tmp/' to '../tmp': Operation not permitted

$ /usr/bin/sudo /usr/bin/chattr -i tmp

$ rmdir tmp/
```

----------

## ozzy468

hi, 

thanks for the reply. 

from man chattr  i: ...and the file can not be opened in write mode.

Probably I was a little fuzzy in my post. The intention is:

I have some users (not in wheel). They all get the same folder structure in their home folder.

/home/user1/folder1

/home/user1/folder2

etc.

Then, there is a docker container, which bind mounts these folders (into some container folder structure).

container starts (it's a guess, docker daemon starts at default, so I think the bind mounts are done at that time)

container:

mount bind /home/user1/folder1 /some/container/mountpoint

mount bind /home/user1/folder2 /some/container/mountpoint2

etc.

the folders need to be writable by their users, so they can put whatever media into those folders, and it gets recognized by the container.

of cause, user1 decides, there's no need for folder1 and deletes it (or moves it to trash, if a chattr +i file in the folder), and user2 does not like that the folder is called folder1 and renames it to Folder1.

reboot

container does not find the folders, and therefore does not start.

----------

## Leonardo.b

What do you want to do exactly?

Maybe there is a different solution.

----------

## Hu

This seems to me like seeking a solution to the wrong problem.  Either train your users not to delete these critical folders, or fix the startup script not to abort when the folders vanish.  If the users insist on deleting these folders, then finding a way to block the user will just cause other problems when they complain that they cannot delete the folder.

----------

## ozzy468

 *Quote:*   

> Maybe there is a different solution.

 

definitely.

 *Quote:*   

> What do you want to do exactly? 

 

Well, what will I do next time. The second "do not move or remove these folders" talk might have done the trick.

As far, as the container goes. It didn't complain or crash while the folder was removed. It's just a startup issue. 

I used docker-cli with restart = always option.

My first impulse was to (force) preserve the folder structure, but on 2nd thought it might be sufficient if the folders exist on startup.

I'll take any suggestion.

Thanks

----------

## pjp

 *ozzy468 wrote:*   

> hi, 
> 
> thanks for the reply. 
> 
> from man chattr  i: ...and the file can not be opened in write mode.

  You're correct. I noticed that you set it on a file and not the directory. I dislike extended attributes and never use them, so I wasn't familiar with that limitation. Now it seems even less useful than I already thought they were. I suppose it has a minor degree of protection from accidental deletion / modification.

 *ozzy468 wrote:*   

> Probably I was a little fuzzy in my post. The intention is:
> 
> I have some users (not in wheel). They all get the same folder structure in their home folder.
> 
> /home/user1/folder1
> ...

  You were clear earlier, I was just unaware of that limitation of the extended attributes.

The mount bind commands seem like folder# are only mountpoints. If the container is mounted onto folder#, does the user need write access? I may be misunderstanding what's going on there.

So, again with the chattr +i tmp directory: 

```
$ rmdir tmp/

rmdir: failed to remove 'tmp/': Operation not permitted

$ /usr/bin/sudo /bin/mount bind -t tmpfs tmp/

$ ls -ld tmp

drwxrwxrwt 2 root root 40 Mar 12 15:42 tmp/

$ vi tmp/foo

$ cat tmp/foo 

This is file foo.
```

 You could even mount the directory with the users uid & gid. 

What mounts the containers? Maybe that's the place to address mounting only if the directory exists. 

It isn't clear what the purpose of the containers are, so it is challenging to come up with an alternative suggestion other than don't try to force a directory structure in their home directories.

As others have commented, clarifying what you are trying to achieve might help. Why force the directory structure at all?

----------

## ozzy468

Thanks again for the replies

@Hu, users are untrainable  :Smile:  but I definitely get your thought. I was looking for a quick solution, so changing the script somehow passed my mind.

 *Quote:*   

> It isn't clear what the purpose of the containers are

 

ok, so the project real quick. I don't get, why people buy a "NAS". They seem quite expensive and I once had an older model, that terribly relied on it's s.m.a.r.t array (older drives, that were perfectly fine could not be used, etc.).

So, buy and old machine with some power and some power saving options. Install Linux.

What would a "NAS" have. samba, vnc (in case one needs to move or delete files  :Smile:  ).

on/off will mostly be controlled by the power button, so all services must run without any user interaction.

I think, today, if people say "NAS" the often mean "Streaming Server".

So I used jellyfin, which I must say is quite nice. I didn't want to go through the process of compiling it, so I used a docker container. 

On these prebuild by someone somewhere containers, there are 2 options to fire these up.

One can use docker-cli - which I did, or docker-compose which reads from some .yaml file, and I tend to hit tab.

here's the link

https://jellyfin.org/docs/general/administration/installing.html#docker

About the bind mounts, if you use docker, you may add users to the group docker, and then you probably won't need them. Knowing my users, the container runs under another user, so I think the bind mounts will stay.

Anyway, you don't have to go through the trouble of reading all that. 

@pjp this might already solve it, I will look into it tomorrow.

Thanks

----------

## szatox

No idea what you're doing there and what options you have, but the way I typically prevent users from messing up the directory tree is "not letting them access folders they are not supposed to delete".

Say, if we had paths like this:

/app_root/files/user1/some_garbage_file

/app_root/common_settings

I'd jail the user inside user1. If you decide you no longer need some_garbage_file hanging on your branch, you can delete it and nobody will complain, but you don't get to even see common_settings, since it belongs to the app admin.

This can be done using chroot or inside application, depending on the requirements of your particular scenario.

----------

## ozzy468

 *Quote:*   

> "not letting them access folders they are not supposed to delete".

 

I like that. 

It's tempting, but the whole thing has a real simple - private use - setup, and I think this is over the top; and most likely over my ability.

@pjp: thanks for your firm replies and patience. Tried to archive something similar with fstab: /test/ /home/user/test none bind(,rw), but this gave a non writable folder, too.

from, recently read, Gentoo's SELinux wiki:  *Quote:*   

> A discretionary model means that the owner of a resource can still decide how the resource is shared on the system. 

 

I'll stick with that, and the simple human intelligence solution, posted by Hu.

 *Quote:*   

> No idea what you're doing there and what options you have

 

I'm still not sure, if my posts were written in an overly complicated fashion.

Might be that docker and gentoo are very distinct approaches of doing things.

Thanks @all for investing your time, reading and thinking

----------

## Leonardo.b

https://jellyfin.org/docs/general/administration/installing.html#linux-generic-amd64

Looks simpler.

I believe Docker is adding problems and complexity to your setup.

----------

## ozzy468

hi, 

thanks!

 *Quote:*   

> I believe Docker is adding problems and complexity to your setup.

 

you might be right, but it has been done. And the only problem has really been the broken (docker) bind mount, whilst renaming/removing a directory. 

jellyfin uses (it's own) ffmpeg, and in the image/container, someone with more sense than me, installed it and compiled it in. 

There is some "fear" that, something like

 *Quote:*   

> Not being able to use jellyfin-ffmpeg will most likely break hardware acceleration and tonemapping.

 

will just take a lot of time fixing it. 

For example "hardware acceleration" is easily archived by using gentoo's VA-API, and some group add for the container to group render, and it works out of the box. 

Many thanks! don't worry about it. BR

----------

## pjp

 *ozzy468 wrote:*   

> @pjp: thanks for your firm replies and patience. Tried to archive something similar with fstab: /test/ /home/user/test none bind(,rw), but this gave a non writable folder, too.

  That looks different than the folder# example which was mounting a container. Is /test/ literally a directory under root which has contents 'user' should have write access to? For my own edification, I'd be curious to try repeating that setup. The mount option might need -o uid=<uid #>, guid=<gid #> (the underlying file system needs to support those options). Either the container or contents of /test/ would need the user to have write permissions.

Another option with an ext2 file system... 

```
dd if=/dev/zero of=example.img bs=1M count=100

/sbin/mke2fs example.img

/usr/bin/sudo /bin/mount example.img tmp/

/usr/bin/sudo /bin/chown tstuser.tstuser tmp/

touch tmp/inside-example.img
```

 I'm using example.img as a stunt double for your docker container. I couldn't get the mount option to work with -o uid=...,gid=... so I went the next best route which is to chown the mounted disk image directory. The user then has permission to write the contents. This is the part I think didn't happen with your test case and fstab, though I could be mistaken. The user has to be given permission to access the contents. Easy to miss, but I was also presuming the docker container already had correct permissions for the users.

 *ozzy468 wrote:*   

> from, recently read, Gentoo's SELinux wiki:  *Quote:*   A discretionary model means that the owner of a resource can still decide how the resource is shared on the system.  

  If you're using SELinux, then that changes a lot :).

 *ozzy468 wrote:*   

> I'll stick with that, and the simple human intelligence solution, posted by Hu.

  Simple is often better when it works. 

 *ozzy468 wrote:*   

> I'm still not sure, if my posts were written in an overly complicated fashion.
> 
> Might be that docker and gentoo are very distinct approaches of doing things.

  Unless docker uses special file systems, I think it is clear enough. Although if SELinux is enabled, that could cause some additional eccentricities.

 *ozzy468 wrote:*   

> Thanks @all for investing your time, reading and thinking

  It's also fun / a learning experience, so we both benefit :). You're welcome.

----------

## Hu

The straightforward way to use Docker would result in it providing bind mounts of the host filesystem, a chroot for the contained process, and some other details not relevant here.  The host filesystem's access controls would still be relevant.  The use of bind mounts may allow the container to cheat past the usual search permission rules, though.

----------

## ozzy468

 *Quote:*   

> That looks different than the folder# example which was mounting a container.

 

My bad. Of cause, in fstab, if you use folder to folder bind on existing file systems, it will respect the permissions previously set. 

I had a case of differing ones. Always wondered, what set this. - it was me. So it's case of trying to outsmart the system on a thought that came up on a former mistake.

About this:

 *Quote:*   

> a chroot for the contained process

 

This came up a few times, and I am going off topic here, so please don't mind.

I followed gentoo's docker wiki. You'll come across

 *Quote:*   

> root #usermod -aG docker <username>
> 
> Warning
> 
> Allowing a user to talk to the Docker daemon is equivalent to giving it full root access to the host. 

 

so what is wrong with

#usermod -aG docker larry

passwd -l larry

(and block larry on sshd)

Mind that larry only exists on the system to use a single image/container

If larry was a docker-developer, this might be a whole different case. 

or is chrooting a non optional security advise?

----------

## Hu

If you lock larry and block it on sshd, how can anything run as larry?  If nothing can run as larry, then the groups for larry are irrelevant.

The chroot is performed by the Docker daemon for the contained process(es).  It's an implementation detail related to giving them a private view of the filesystem.

----------

## ozzy468

 *Quote:*   

> The chroot is performed by the Docker daemon for the contained process(es). It's an implementation detail related to giving them a private view of the filesystem.

 

Thanks for clearing that up.

 *Quote:*   

> If you lock larry and block it on sshd, how can anything run as larry? If nothing can run as larry, then the groups for larry are irrelevant. 

 

Try it. 

I don't think the container is run as larry as such. So you might just pass larry's uid:gid for the bind mounts, and check if the one starting it (larry) is in group docker.

If you have /home/larry set it to 700

Fire up a container (as larry in group docker) which mounts some folders in /home/larry, by passing larry's uid:gid, and restart=always option.

lock larry 

restart docker daemon

check if your folders are still in your container.

----------

## Hu

Processes that are set to larry's uid by Docker or similar may or may not have larry's groups.  Moreover, it's not necessary to give the docker group to processes that will run inside a docker container.  Beyond that, I don't understand your post.  I'm not set up to try this, and have no need for it to work for me.  My users know better than to delete critical directories.

----------

## ozzy468

hi Hu,

you are right. I shall read up on the mechanisms of containers.

Thanks

----------

