[GH-ISSUE #83] Shared Game Libraries #58

Open
opened 2026-10-15 12:55:35 +00:00 by bsakaguchi · 34 comments
Owner

Originally created by @salty2011 on GitHub (Jul 2, 2024).
Original GitHub issue: https://github.com/games-on-whales/wolf/issues/83

With the way wolf currently works when having multiple uses, each user end up installing their own copy of a game. For illustrative purposes we have User1 and User2 (i realise wolf currently splits this out based on client unless you make changes in the config).

The user data would be stored in
/wolf/user1/.....
/wolf/user2.....

And for each user would have their copy of the game installed.

The issue with this is that results in excessive storage, additional downloads unless cached etc.

After doing some research into docker I did find a potential solution that may work. Within docker when binding folders it possible to create an overlay and that layer write changes else where. So in theory we could do this (using a simple dir structure to explain the concept)

[CONTAINER HOST]
/games/steam/{installed games}}
/wolf/user1/steam
/wolf/user2/steam

[CONTAINER]
lowerdir = /mnt/shared-steam/ (read-only)
workdir = /mnt/user-steam/ (RW)

When launching the docker container this would look like

#USER1
docker run --name steamapp_user1 --privileged \
  -v /games/steam:/mnt/shared-steam:ro \
  -v /wolf/user1/steam:/mnt/user-steam \
  -it steamapp /bin/bash

docker exec -d steamapp_user1 /sbin/mount -t overlay overlay \
  -o lowerdir=/mnt/shared-steam,upperdir=/mnt/user-steam,workdir=/mnt/user-steam \
  /games/steam

#USER2
docker run --name steamapp_user2 --privileged \
  -v /games/steam:/mnt/shared-steam:ro \
  -v /wolf/user2/steam:/mnt/user-steam \
  -it steamapp /bin/bash

docker exec -d steamapp_user2 /sbin/mount -t overlay overlay \
  -o lowerdir=/mnt/shared-steam,upperdir=/mnt/user-steam,workdir=/mnt/user-steam \
  /games/steam

Now within the container you'll see all installed games from the hosts /games/steam but changes would be written into /wolf/user1|2/steam, this is possible by leveraging the overlay features outlined in the last part of the command

In addition could have a 3rd container that is responsible for pre-populating /games/steam and also maybe schedule merging game installations that a user does by moving installed games from their profile into the /games/steam dir (although that may be somewhat of a challenge)

Originally created by @salty2011 on GitHub (Jul 2, 2024). Original GitHub issue: https://github.com/games-on-whales/wolf/issues/83 With the way wolf currently works when having multiple uses, each user end up installing their own copy of a game. For illustrative purposes we have User1 and User2 (i realise wolf currently splits this out based on client unless you make changes in the config). The user data would be stored in /wolf/user1/..... /wolf/user2..... And for each user would have their copy of the game installed. The issue with this is that results in excessive storage, additional downloads unless cached etc. After doing some research into docker I did find a potential solution that may work. Within docker when binding folders it possible to create an overlay and that layer write changes else where. So in theory we could do this (using a simple dir structure to explain the concept) [CONTAINER HOST] /games/steam/{installed games}} /wolf/user1/steam /wolf/user2/steam [CONTAINER] lowerdir = /mnt/shared-steam/ (read-only) workdir = /mnt/user-steam/ (RW) When launching the docker container this would look like ``` #USER1 docker run --name steamapp_user1 --privileged \ -v /games/steam:/mnt/shared-steam:ro \ -v /wolf/user1/steam:/mnt/user-steam \ -it steamapp /bin/bash docker exec -d steamapp_user1 /sbin/mount -t overlay overlay \ -o lowerdir=/mnt/shared-steam,upperdir=/mnt/user-steam,workdir=/mnt/user-steam \ /games/steam #USER2 docker run --name steamapp_user2 --privileged \ -v /games/steam:/mnt/shared-steam:ro \ -v /wolf/user2/steam:/mnt/user-steam \ -it steamapp /bin/bash docker exec -d steamapp_user2 /sbin/mount -t overlay overlay \ -o lowerdir=/mnt/shared-steam,upperdir=/mnt/user-steam,workdir=/mnt/user-steam \ /games/steam ``` Now within the container you'll see all installed games from the hosts /games/steam but changes would be written into /wolf/user1|2/steam, this is possible by leveraging the overlay features outlined in the last part of the command In addition could have a 3rd container that is responsible for pre-populating /games/steam and also maybe schedule merging game installations that a user does by moving installed games from their profile into the /games/steam dir (although that may be somewhat of a challenge)
Author
Owner

@ABeltramo commented on GitHub (Jul 18, 2024):

This is all very interesting and I should definitely look further into it, the arch wiki entry is a nice starting point.

Am I right in thinking that this isn't really a docker specific feature? Because I saw this but it doesn't apply here since you are just manually mounting from inside the container.

I have to wrap my head around it and I'm not sure how the directory tree should be managed (probably needs some proper setting in the config.toml). Currently we do something like:

/etc/wolf/<user_id>/Steam:/home/retro/

Steam will generally store most of his stuff under ~/.steam. We'll then mount an overlay fs somewhere else but where would that live in the host? Something like

/etc/wolf/overlay/Steam

so that each app will have a common overlay in a known location?

<!-- gh-comment-id:2237484827 --> @ABeltramo commented on GitHub (Jul 18, 2024): This is all very interesting and I should definitely look further into it, the [arch wiki entry](https://wiki.archlinux.org/title/Overlay_filesystem) is a nice starting point. Am I right in thinking that this isn't really a docker specific feature? Because I saw [this](https://docs.docker.com/storage/storagedriver/overlayfs-driver/) but it doesn't apply here since you are just manually mounting from inside the container. I have to wrap my head around it and I'm not sure how the directory tree should be managed (probably needs some proper setting in the `config.toml`). Currently we do something like: ``` /etc/wolf/<user_id>/Steam:/home/retro/ ``` Steam will generally store most of his stuff under `~/.steam`. We'll then mount an overlay fs somewhere else but where would that live in the host? Something like ``` /etc/wolf/overlay/Steam ``` so that each app will have a common overlay in a known location?
Author
Owner

@salty2011 commented on GitHub (Jul 19, 2024):

Yeah there are a few ways to approach this, but to me I would have some configuration within the config.toml where you would define global settings that apply to all users. Within this section I would have a library definition that would

  • define library locations on the host
  • the container this library applies to, as may need similar config for things like Emulation Station etc

The default for this could be '/etc/wolf/overlay/Steam' , and agree this would mean each app would have a common overlay so that duplication of game libraries does not occur and avoid potential locking issues when multiple users are accessing the same games.

Going of my previous Wolf setup on unraid the ~/.steam was being persisted outside of the container under "../wolf//Steam/" although not sure if thats something by default or if I set it up that way.

<!-- gh-comment-id:2238548483 --> @salty2011 commented on GitHub (Jul 19, 2024): Yeah there are a few ways to approach this, but to me I would have some configuration within the config.toml where you would define global settings that apply to all users. Within this section I would have a library definition that would - define library locations on the host - the container this library applies to, as may need similar config for things like Emulation Station etc The default for this could be '/etc/wolf/overlay/Steam' , and agree this would mean each app would have a common overlay so that duplication of game libraries does not occur and avoid potential locking issues when multiple users are accessing the same games. Going of my previous Wolf setup on unraid the ~/.steam was being persisted outside of the container under "../wolf/<id>/Steam/" although not sure if thats something by default or if I set it up that way.
Author
Owner

@lukaszzyla commented on GitHub (Aug 21, 2024):

Hi!
I have issues trying to use the way described in quickstart for wolf.
First of all in config.toml I only have one entry for paired clients, even though I have paired 2 already.
I did the recommended solution to change the folder name there from number (10897384724) to "common"
When i tried accesing steam via moonlight for the first time from my pc and also android phone as a second user - I had steam installed and I did connect to the same common apps - I was downloading a game and on both devices I could see this game being downloaded.
But then I came to another location with another network and suddenly it stopped working - wolf created another app_state_folder for my already paired pc and I had to start everything from scratch (updating steam, logging into it and downloading game again).
When I moved contents of previously configured "common" folder to a new numeric folder that appeared after connecting from new location - everything was working, but this is very labour intensive method to move files and deal with config.toml every time I want to just access my profile and its games/progress.
I think this is one of the most important functionalities to work on at the moment and would be very happy if someone agrees.

<!-- gh-comment-id:2302616185 --> @lukaszzyla commented on GitHub (Aug 21, 2024): Hi! I have issues trying to use the way described in quickstart for wolf. First of all in config.toml I only have one entry for paired clients, even though I have paired 2 already. I did the recommended solution to change the folder name there from number (10897384724) to "common" When i tried accesing steam via moonlight for the first time from my pc and also android phone as a second user - I had steam installed and I did connect to the same common apps - I was downloading a game and on both devices I could see this game being downloaded. But then I came to another location with another network and suddenly it stopped working - wolf created another app_state_folder for my already paired pc and I had to start everything from scratch (updating steam, logging into it and downloading game again). When I moved contents of previously configured "common" folder to a new numeric folder that appeared after connecting from new location - everything was working, but this is very labour intensive method to move files and deal with config.toml every time I want to just access my profile and its games/progress. I think this is one of the most important functionalities to work on at the moment and would be very happy if someone agrees.
Author
Owner

@salty2011 commented on GitHub (Aug 21, 2024):

I moved contents of previously configured "common" folder to a new numeric folder that appeared after connecting from new location - everything was working,

hey @lukaszzyla , thats interesting. definitely going need more info. however the problem you are describing is not related this feature exactly. When setting to common it results all clients referencing same folder. This useful if there is only one user of wolf, but if you have multiple users at the same time.... this is where this proposed solution comes in.

The idea is to have the steamapps folders be accessible to multiple users at the same time.

Could I suggest you reach out on the discord channel or log an issue for this... When you do can you attach your wolf logs so we can get sense of whats occuring.

<!-- gh-comment-id:2302741000 --> @salty2011 commented on GitHub (Aug 21, 2024): > I moved contents of previously configured "common" folder to a new numeric folder that appeared after connecting from new location - everything was working, hey @lukaszzyla , thats interesting. definitely going need more info. however the problem you are describing is not related this feature exactly. When setting to common it results all clients referencing same folder. This useful if there is only one user of wolf, but if you have multiple users at the same time.... this is where this proposed solution comes in. The idea is to have the steamapps folders be accessible to multiple users at the same time. Could I suggest you reach out on the discord channel or log an issue for this... When you do can you attach your wolf logs so we can get sense of whats occuring.
Author
Owner

@mikewalshchicago commented on GitHub (Nov 25, 2024):

I am sharing a SteamLibrary in a less sophisticated way than what is being described in this change request. In my config.toml, I added the following to the steam app.runner:

mounts = [ '/mnt/games:/mnt/games:rw', '/mnt/shared:/mnt/shared:rw' ]

one of these mounts is a local drive, and the other is a nfs share. When I launch a steam container for the first time, I go into settings> storage, and navigate to the 'SteamLibrary' directory in both of these mounts and add them.

As far as I can tell, this method is working. I can launch the same game on 4 different containers logged in with 4 different steam accounts, however I will admit that the game doesn't always launch on the first try, or the second. If the game hangs while trying to launch, i can kill the container from the moonlight client and try again. eventually it will work.

I am not sure if the reason for the failed launches is because of the shared files (e.g. file locks), or something completely unrelated, like issue #151. Presumably the suggestion to have a read-only mount as well as a write mount that merges with the ro would suggest that there is something flawed with simply mounting the SteamLibrary as rw, so I wanted to share my findings.

<!-- gh-comment-id:2498615546 --> @mikewalshchicago commented on GitHub (Nov 25, 2024): I am sharing a SteamLibrary in a less sophisticated way than what is being described in this change request. In my config.toml, I added the following to the steam app.runner: mounts = [ '/mnt/games:/mnt/games:rw', '/mnt/shared:/mnt/shared:rw' ] one of these mounts is a local drive, and the other is a nfs share. When I launch a steam container for the first time, I go into settings> storage, and navigate to the 'SteamLibrary' directory in both of these mounts and add them. As far as I can tell, this method is working. I can launch the same game on 4 different containers logged in with 4 different steam accounts, however I will admit that the game doesn't always launch on the first try, or the second. If the game hangs while trying to launch, i can kill the container from the moonlight client and try again. eventually it will work. I am not sure if the reason for the failed launches is because of the shared files (e.g. file locks), or something completely unrelated, like issue #151. Presumably the suggestion to have a read-only mount as well as a write mount that merges with the ro would suggest that there is something flawed with simply mounting the SteamLibrary as rw, so I wanted to share my findings.
Author
Owner

@Diudid commented on GitHub (Jan 2, 2025):

To add my stone to the edifice, I manage to save storage space and share game by manually hardlinking the common folder of a profile into another with Rsync :
i go into the steamapps folder of the second user i want to sync game into
/etc/wolf/9288016748385337878/Steam/.steam/debian-installation/steamapps
then i rsync with :
rsync -a --link-dest=../../../../../../4399479825034202445/Steam/.steam/debian-installation/steamapps/common/ /etc/wolf/4399479825034202445/Steam/.steam/debian-installation/steamapps/common/ ./common/

After this i can start a steam container and tryt o launch the game, if it fail i launch a integrity verification of the games files.

Depending of the games, the file are reusable (Wayfinder) or it redownload nearly all the game (warframe)
Some time the game need to be launched once to be able to have a 100% harlinked content (Wayfinder)
and the updates mess up the hardlinks so I have to resync every week/months so that still an hacky solution.

<!-- gh-comment-id:2567970551 --> @Diudid commented on GitHub (Jan 2, 2025): To add my stone to the edifice, I manage to save storage space and share game by manually hardlinking the common folder of a profile into another with Rsync : i go into the steamapps folder of the second user i want to sync game into /etc/wolf/9288016748385337878/Steam/.steam/debian-installation/steamapps then i rsync with : rsync -a --link-dest=../../../../../../4399479825034202445/Steam/.steam/debian-installation/steamapps/common/ /etc/wolf/4399479825034202445/Steam/.steam/debian-installation/steamapps/common/ ./common/ After this i can start a steam container and tryt o launch the game, if it fail i launch a integrity verification of the games files. Depending of the games, the file are reusable (Wayfinder) or it redownload nearly all the game (warframe) Some time the game need to be launched once to be able to have a 100% harlinked content (Wayfinder) and the updates mess up the hardlinks so I have to resync every week/months so that still an hacky solution.
Author
Owner

@glm11-aoc commented on GitHub (Apr 21, 2025):

Couldn't the steam games be potentially stored in a ro section and then something like unionfs could be used to make it writeable over the top for the steam application to do stuff like join betas and store saves improperly. The only issue is that it might be hard to keep track of which files are identical and should be stored in the shared segment (especially with proton vs non-proton versions and such).

IIRC unionfs should also fix the issue of some games not liking symlinks (i.e. warframe redownloading it's binary files as mentioned by @Diudid)

<!-- gh-comment-id:2817962522 --> @glm11-aoc commented on GitHub (Apr 21, 2025): Couldn't the steam games be potentially stored in a `ro` section and then something like [unionfs](https://en.wikipedia.org/wiki/UnionFS) could be used to make it writeable over the top for the steam application to do stuff like join betas and store saves improperly. The only issue is that it might be hard to keep track of which files are identical and should be stored in the shared segment (especially with proton vs non-proton versions and such). IIRC unionfs should also fix the issue of some games not liking symlinks (i.e. warframe redownloading it's binary files as mentioned by @Diudid)
Author
Owner

@Diudid commented on GitHub (Apr 21, 2025):

You resumed the situation, many ways to get games in ready only, the central issue is keeping the games updated.
I am working on a script to sync games, will only work on steam i think, still coding.

<!-- gh-comment-id:2817967511 --> @Diudid commented on GitHub (Apr 21, 2025): You resumed the situation, many ways to get games in ready only, the central issue is keeping the games updated. I am working on a script to sync games, will only work on steam i think, still coding.
Author
Owner

@Pierrick584 commented on GitHub (May 6, 2025):

i havent tested this yet, but maybe mounting the wolf directory on a different drive with a deduplication filesystem would fix the issue without modifying the code?

<!-- gh-comment-id:2854080626 --> @Pierrick584 commented on GitHub (May 6, 2025): i havent tested this yet, but maybe mounting the wolf directory on a different drive with a deduplication filesystem would fix the issue without modifying the code?
Author
Owner

@salty2011 commented on GitHub (May 6, 2025):

i havent tested this yet, but maybe mounting the wolf directory on a different drive with a deduplication filesystem would fix the issue without modifying the code?

This is an approach the challenge is unique data related to the user (eg game saves) can also end up being stored in this location which in a multi user scenario will result in that data being accessible across all users and worse potentially altered.

The additional challenges is not all games store temp, save data outside of the games install directory. Additionally some games have lock files or similar that prevent multiple copies launching. So dedupe can save space but doesn't solve the other challenges.

@glm11-aoc has correctly identified optimum approach, this was conceptually tested a year ago. The caveat to this approach is for example if you are presenting the steam interface and they install a game, those install files now end up in the RW layer which in the @glm11-aoc approach would result in those files being stored in the users persistent layer (ie their home directory). In testing i did try doing some sort of sync script but this has issues.

To solve the issue the suggested approach was to present the user with a launch UI so that they don't actually really see the steam UI, or have the ability to install games directly through steam ( this approach somewhat valid if you also check out nvidia's GeForce Now service). At the moment there is two pieces of work underway

  1. WolfUI, is designed to be the launcher that is published as an app that appears in moonlight. there are a few features offered outside of this like couch coop etc, but I don't have the latest on this

  2. WolfManager, this if an administrative UI I have been working on, initial release will be able to create multiple users, pair clients with those users, view logs.

Planned features post release is to add a plugin system that enables library management like steam to install / remove games etc. The approach for this would be similar to what @glm11-aoc mentioned before. The plugin approach means others in the community in theory could build additional plugins for library etc.

As for how far away WolfManager is from lease, hoping not to much longer. All initial features are ready and the final UI is present it's now at a point to cleanup, package to into docker.

In the meantime here is the preview of the WolfManager UI
image

<!-- gh-comment-id:2854777581 --> @salty2011 commented on GitHub (May 6, 2025): > i havent tested this yet, but maybe mounting the wolf directory on a different drive with a deduplication filesystem would fix the issue without modifying the code? This is an approach the challenge is unique data related to the user (eg game saves) can also end up being stored in this location which in a multi user scenario will result in that data being accessible across all users and worse potentially altered. The additional challenges is not all games store temp, save data outside of the games install directory. Additionally some games have lock files or similar that prevent multiple copies launching. So dedupe can save space but doesn't solve the other challenges. @glm11-aoc has correctly identified optimum approach, this was conceptually tested a year ago. The caveat to this approach is for example if you are presenting the steam interface and they install a game, those install files now end up in the RW layer which in the @glm11-aoc approach would result in those files being stored in the users persistent layer (ie their home directory). In testing i did try doing some sort of sync script but this has issues. To solve the issue the suggested approach was to present the user with a launch UI so that they don't actually really see the steam UI, or have the ability to install games directly through steam ( this approach somewhat valid if you also check out nvidia's GeForce Now service). At the moment there is two pieces of work underway 1. WolfUI, is designed to be the launcher that is published as an app that appears in moonlight. there are a few features offered outside of this like couch coop etc, but I don't have the latest on this 2. WolfManager, this if an administrative UI I have been working on, initial release will be able to create multiple users, pair clients with those users, view logs. Planned features post release is to add a plugin system that enables library management like steam to install / remove games etc. The approach for this would be similar to what @glm11-aoc mentioned before. The plugin approach means others in the community in theory could build additional plugins for library etc. As for how far away WolfManager is from lease, hoping not to much longer. All initial features are ready and the final UI is present it's now at a point to cleanup, package to into docker. In the meantime here is the preview of the WolfManager UI ![image](https://github.com/user-attachments/assets/61ec1e92-9563-438a-8ca2-2ff12f90fe8c)
Author
Owner

@glm11-aoc commented on GitHub (May 8, 2025):

I have done more digging and BTRFS supports offline dedups (rather than ZFS' slow online dedups) which means you should be able to get the full benefit of game de-duplication handled at the FS level, pretty neat if you are specifically making a machine for game streaming. Also bypasses any issues around improper file usage/modification (as long as it's properly configured) or userspace overhead (unionfs will have some of it intrinsically). For most people though WolfUI/Manager will 100% be the easier & better solution than learning how to set up performant dedup.

<!-- gh-comment-id:2862899348 --> @glm11-aoc commented on GitHub (May 8, 2025): I have done more digging and BTRFS supports offline dedups (rather than ZFS' slow online dedups) which means you should be able to get the full benefit of game de-duplication handled at the FS level, pretty neat if you are specifically making a machine for game streaming. Also bypasses any issues around improper file usage/modification (as long as it's properly configured) or userspace overhead (unionfs will have some of it intrinsically). For most people though WolfUI/Manager will 100% be the easier & better solution than learning how to set up performant dedup.
Author
Owner

@salty2011 commented on GitHub (May 8, 2025):

@glm11-aoc interesting so your thinking have btrfs dedupe configured, you store a common library but then each user installs a copy of a game in their own space (as long as it's the same file system).

In theory only the differences are written to the users location and the rest of the game files are deduped due to being stores else where?

You able to share your research. BTRFS is more commonly used around the place where Wolf is likely to be installed so definitely open to looking at this approach as well if it reduces complexity. Wonder if one could leverage docker volumes and this fs in the instance the host doesn't use btrfs

One of the features I want to get happening in WolfManager is the ability to launch a Wolf stack as part of initial setup

<!-- gh-comment-id:2862928263 --> @salty2011 commented on GitHub (May 8, 2025): @glm11-aoc interesting so your thinking have btrfs dedupe configured, you store a common library but then each user installs a copy of a game in their own space (as long as it's the same file system). In theory only the differences are written to the users location and the rest of the game files are deduped due to being stores else where? You able to share your research. BTRFS is more commonly used around the place where Wolf is likely to be installed so definitely open to looking at this approach as well if it reduces complexity. Wonder if one could leverage docker volumes and this fs in the instance the host doesn't use btrfs One of the features I want to get happening in WolfManager is the ability to launch a Wolf stack as part of initial setup
Author
Owner

@glm11-aoc commented on GitHub (May 8, 2025):

@salty2011 I was just having a look through the BTRFS docs and found BEES. It seems like it could work quite well as long as the underlying system is equipped with an SSD (random rw performance would be important here). I'm sure there are other options that could be picked but out of the ones listed there, this seemed like the better option (unless you can schedule a cron job against your wolf folder, then duperemove should work alright).

<!-- gh-comment-id:2862955741 --> @glm11-aoc commented on GitHub (May 8, 2025): @salty2011 I was just having a look through the [BTRFS docs](https://btrfs.readthedocs.io/en/latest/Deduplication.html) and found [BEES](https://github.com/Zygo/bees). It seems like it could work quite well as long as the underlying system is equipped with an SSD (random rw performance would be important here). I'm sure there are other options that could be picked but out of the ones listed there, this seemed like the better option (unless you can schedule a cron job against your wolf folder, then [duperemove](https://github.com/markfasheh/duperemove) should work alright).
Author
Owner

@Diudid commented on GitHub (May 8, 2025):

I looked a little into it. This look like a simple way to have a dedup process.
They warned about performances loss at reading time.
And you have to use an external utility to tag files as DUP.

<!-- gh-comment-id:2862960577 --> @Diudid commented on GitHub (May 8, 2025): I looked a little into it. This look like a simple way to have a dedup process. They warned about performances loss at reading time. And you have to use an external utility to tag files as DUP.
Author
Owner

@salty2011 commented on GitHub (May 8, 2025):

Given Wolf's primary focus is on game streaming I would imagine most people at this point aren't running this on HDD's. SSD at worst but most are likely using nvme.

Suppose we won't know until we give it a shot. Good news is testing this doesn't require code changes in Wolf or WolfManager to see if it would at least work.

The one thing that sorta a flag for me is the dependancy on host having BTRFS... how common is that, for me it's the norm sll my Linux distro's use it by default.

<!-- gh-comment-id:2862982874 --> @salty2011 commented on GitHub (May 8, 2025): Given Wolf's primary focus is on game streaming I would imagine most people at this point aren't running this on HDD's. SSD at worst but most are likely using nvme. Suppose we won't know until we give it a shot. Good news is testing this doesn't require code changes in Wolf or WolfManager to see if it would at least work. The one thing that sorta a flag for me is the dependancy on host having BTRFS... how common is that, for me it's the norm sll my Linux distro's use it by default.
Author
Owner

@glm11-aoc commented on GitHub (May 8, 2025):

@salty2011 probably worth checking if the host is BTRFS (and disabling game library dedup), Ubuntu & derivatives don't ship it as an option in their installers even though it is supported for some reason.

<!-- gh-comment-id:2863011523 --> @glm11-aoc commented on GitHub (May 8, 2025): @salty2011 probably worth checking if the host is BTRFS (and disabling game library dedup), Ubuntu & derivatives don't ship it as an option in their installers even though it is supported for some reason.
Author
Owner

@Diudid commented on GitHub (May 8, 2025):

Some use raid HDD though still slower than ssd but faster than single HDD.
Still is a good idea to dedup with this. I will give it a try.
Found this https://github.com/Lakshmipathi/dduper, will give it a spin

<!-- gh-comment-id:2863024085 --> @Diudid commented on GitHub (May 8, 2025): Some use raid HDD though still slower than ssd but faster than single HDD. Still is a good idea to dedup with this. I will give it a try. Found this https://github.com/Lakshmipathi/dduper, will give it a spin
Author
Owner

@salty2011 commented on GitHub (May 8, 2025):

Nice,

Was just having a thought on this further. If this approach works, I'm wondering if I can have a background Task in WolfManager to check for newly installed games in user profiles and then downloads a copy to store in common, and then when a container launches we present the common library into the cached installer directory for steam. That way if a user attempts to install a game that's been downloaded previously it'll grab it from its cached installs.

I had intended on implementing some sort of Library management into WolfManager to add app/games straight into Wolf's app published app for direct launching... sorta want something where if USER_A owns a game that's been launched by USER_B so it's cacheD, then USER_A launches it just goes straight in and launches or installs into their profile from cache and launches. Should install quick cause it's just grabbing from cache and given dedupe won't be writing any actual data for the most part

<!-- gh-comment-id:2863079529 --> @salty2011 commented on GitHub (May 8, 2025): Nice, Was just having a thought on this further. If this approach works, I'm wondering if I can have a background Task in WolfManager to check for newly installed games in user profiles and then downloads a copy to store in common, and then when a container launches we present the common library into the cached installer directory for steam. That way if a user attempts to install a game that's been downloaded previously it'll grab it from its cached installs. I had intended on implementing some sort of Library management into WolfManager to add app/games straight into Wolf's app published app for direct launching... sorta want something where if USER_A owns a game that's been launched by USER_B so it's cacheD, then USER_A launches it just goes straight in and launches or installs into their profile from cache and launches. Should install quick cause it's just grabbing from cache and given dedupe won't be writing any actual data for the most part
Author
Owner

@Diudid commented on GitHub (May 8, 2025):

Yeah so no DL for USER_B, and this make most of depup useless. I am still curious about how it will handle mods 😄

<!-- gh-comment-id:2863092299 --> @Diudid commented on GitHub (May 8, 2025): Yeah so no DL for USER_B, and this make most of depup useless. I am still curious about how it will handle mods 😄
Author
Owner

@glm11-aoc commented on GitHub (May 8, 2025):

@salty2011 sounds pretty good, just have to make steam validate the game first time instead (since idk how well it will handle some of the non-game files being shared).

@Diudid Dedup is mostly useful for multi-user/device scenarios tbh, but that's reason enough in my eyes as to why it should be done.

<!-- gh-comment-id:2863102026 --> @glm11-aoc commented on GitHub (May 8, 2025): @salty2011 sounds pretty good, just have to make steam validate the game first time instead (since idk how well it will handle some of the non-game files being shared). @Diudid Dedup is mostly useful for multi-user/device scenarios tbh, but that's reason enough in my eyes as to why it should be done.
Author
Owner

@Diudid commented on GitHub (May 8, 2025):

@glm11-aoc yeah i usually run bash scripts to dedup and will try btrfs dedup while waiting for Salty solution.
If i undetsood well Salty is working on a solution to have a reference library with each game used by any user and each user get a copy with some docker fs tricks.

<!-- gh-comment-id:2863128221 --> @Diudid commented on GitHub (May 8, 2025): @glm11-aoc yeah i usually run bash scripts to dedup and will try btrfs dedup while waiting for Salty solution. If i undetsood well Salty is working on a solution to have a reference library with each game used by any user and each user get a copy with some docker fs tricks.
Author
Owner

@salty2011 commented on GitHub (May 8, 2025):

@Diudid not sure I am following your testing.

So did you download a game using USER_A and then in USER_B download the same game?

If you don't map USER_A's steam cached installer directory then it would definitely redownload the game from scratch. However dedupe would prevent the same game from being taken up twice.

If you do map the cache installer it'll still appear to download but you'll notice the download / write speeds will be about the same as your disks read/write speeds minus overhead

@glm11-aoc not knowing how BTRFS dedupe works, if it's block level dedupe then mods shouldn't be an issue cause the base file should still exist and just the changed blocks would be present... hmm actually now I'm thinking about it between two users in docker how would it know what blocks to reference... could BTRFS sub volumes per user be the way to avoid that? So each user has their own sub volume, and dupe between that's. That way only changes blocks are written to the sub volume.. while the rest of the blocks related to the game are referenced from wherever they are... suppose could then use the tool @Diudid mention before to do offline dedupe to reconcile to a single spot so all user sub volumes don't actually store the data just the changes

lol I still can't help but feel this sort of thing was way easier in the good old days of VMware... you could just to linked disk clones. Haven't really found anything like that these days

<!-- gh-comment-id:2863150824 --> @salty2011 commented on GitHub (May 8, 2025): @Diudid not sure I am following your testing. So did you download a game using USER_A and then in USER_B download the same game? If you don't map USER_A's steam cached installer directory then it would definitely redownload the game from scratch. However dedupe would prevent the same game from being taken up twice. If you do map the cache installer it'll still appear to download but you'll notice the download / write speeds will be about the same as your disks read/write speeds minus overhead @glm11-aoc not knowing how BTRFS dedupe works, if it's block level dedupe then mods shouldn't be an issue cause the base file should still exist and just the changed blocks would be present... hmm actually now I'm thinking about it between two users in docker how would it know what blocks to reference... could BTRFS sub volumes per user be the way to avoid that? So each user has their own sub volume, and dupe between that's. That way only changes blocks are written to the sub volume.. while the rest of the blocks related to the game are referenced from wherever they are... suppose could then use the tool @Diudid mention before to do offline dedupe to reconcile to a single spot so all user sub volumes don't actually store the data just the changes lol I still can't help but feel this sort of thing was way easier in the good old days of VMware... you could just to linked disk clones. Haven't really found anything like that these days
Author
Owner

@Diudid commented on GitHub (May 8, 2025):

@salty2011 i didn't started to test it. Will try this week end.

<!-- gh-comment-id:2863162113 --> @Diudid commented on GitHub (May 8, 2025): @salty2011 i didn't started to test it. Will try this week end.
Author
Owner

@salty2011 commented on GitHub (May 8, 2025):

@glm11-aoc yeah i usually run bash scripts to dedup and will try btrfs dedup while waiting for Salty solution.
If i undetsood well Salty is working on a solution to have a reference library with each game used by any user and each user get a copy with some docker fs tricks.

Well the idea is WolfManager does the heavy lifting. I'm still trying to work out the best approach to this, not simple. To date I was going the route of overlayfs and wolf manager just downloading the games and mapping that on container launch. I was going to try and have it for initial launch but quickly finding this is....not simple

But the dedupe option on paper would be simpler... as wouldn't have to mess with complicated overlayfs and symlinks. Plus don't have to limit users access to the steam ui to prevent downloading games outside of WolfManager ui.

Ok so if someone can sorta do the ground work on the dedupe testing, sub volumes per user... testing of game mods not persisting across users. And lastly mapping steam installer cache. That at least confirms if it's viable. Assuming viable what setup is needed. That part I might able to have WolfManager deal with.

<!-- gh-comment-id:2863181318 --> @salty2011 commented on GitHub (May 8, 2025): > @glm11-aoc yeah i usually run bash scripts to dedup and will try btrfs dedup while waiting for Salty solution. > If i undetsood well Salty is working on a solution to have a reference library with each game used by any user and each user get a copy with some docker fs tricks. Well the idea is WolfManager does the heavy lifting. I'm still trying to work out the best approach to this, not simple. To date I was going the route of overlayfs and wolf manager just downloading the games and mapping that on container launch. I was going to try and have it for initial launch but quickly finding this is....not simple But the dedupe option on paper would be simpler... as wouldn't have to mess with complicated overlayfs and symlinks. Plus don't have to limit users access to the steam ui to prevent downloading games outside of WolfManager ui. Ok so if someone can sorta do the ground work on the dedupe testing, sub volumes per user... testing of game mods not persisting across users. And lastly mapping steam installer cache. That at least confirms if it's viable. Assuming viable what setup is needed. That part I might able to have WolfManager deal with.
Author
Owner

@glm11-aoc commented on GitHub (May 8, 2025):

@salty2011 BTRFS supports both file and block level dedup, depends on which tool you use to dedup the data. (BEES does block whilst duperemover does file level). I'm planning on installing Gentoo on my game server soon, I'll give the btrfs + BEES a go and see if it works. :-)

<!-- gh-comment-id:2863195520 --> @glm11-aoc commented on GitHub (May 8, 2025): @salty2011 BTRFS supports both file and block level dedup, depends on which tool you use to dedup the data. (BEES does block whilst duperemover does file level). I'm planning on installing Gentoo on my game server soon, I'll give the btrfs + BEES a go and see if it works. :-)
Author
Owner

@salty2011 commented on GitHub (Jun 13, 2025):

thanks @glm11-aoc

Also for reference all, I have raised a feature request on the WolfManager repo... I have a full description ill update shortly

https://github.com/games-on-whales/wolfmanager/issues/10

<!-- gh-comment-id:2968906058 --> @salty2011 commented on GitHub (Jun 13, 2025): thanks @glm11-aoc Also for reference all, I have raised a feature request on the WolfManager repo... I have a full description ill update shortly https://github.com/games-on-whales/wolfmanager/issues/10
Author
Owner

@kearoth commented on GitHub (Aug 6, 2025):

I had a go at setting up overlayfs for sharing steamgames between clients

To automate this task i used ionotifywait (on ubuntu sudo apt install inotify-tools -y)
I also put together a systemd service which launches a monitor script on boot.

#Systemd service (nano /etc/systemd/system/monitor-steamapps.service)

Service start

[Unit]
Description=Watch for steamapps creation and mount overlay
After=local-fs.target

[Service]
ExecStart=/usr/local/bin/mount_steam_overlay.sh
Restart=always
User=root

[Install]
WantedBy=multi-user.target

This uses a script (/usr/local/bin/mount_steam_overlay.sh)
Said script (nano /usr/local/bin/mount_steam_overlay.sh && chmod +x /usr/local/bin/mount_steam_overlay.sh)

Script start

#!/bin/bash

# Mount at boot
overlays=$(cat /etc/fstab | grep overlay | cut -f4 -d' ')

for overlay in $overlays; do
        mount $overlay
done

WATCH_BASE="/etc/wolf"
STEAM_APPS="/games/steamapps"
owner="ownername"
group="groupname"

# Watches the directory for new folders (numerical names)
inotifywait -m -e create --format '%f' "$WATCH_BASE" 2>/dev/null |
while read -r newdir; do
    if [[ "$newdir" =~ ^[0-9]+$ ]]; then
        echo "[INFO] New user found: $newdir"
        user="$newdir"

        steamapps_path="$WATCH_BASE/$user/Steam/.steam/debian-installation/steamapps"

        echo "[INFO] Creating path for $user..."
        mkdir -p "/user-data/$user/steamapps-upper" \
                 "/user-data/$user/steamapps-workdir" \
                 "$steamapps_path"

        chown $owner:$group $WATCH_BASE/$user/Steam -R
        echo "[INFO] Adding mount line to fstab if not existing..."
        if ! grep -q "Userdata_$user" /etc/fstab; then
            echo "overlay   $steamapps_path    overlay   defaults,noauto,lowerdir=$STEAM_APPS,upperdir=/user-data/$user/steamapps-upper,workdir=/user-data/$user/steamapps-workdir,comment=Userdata_$user    0   2" >> /etc/fstab
        fi

        echo "[INFO] Mounting overlay for $user..."
        mount "$steamapps_path"
    fi
done

Edit WATCH_BASE, STEAM_APPS, owner & group as needed, this is an example where you could have your "master" steamapps folder
You can then enable and start the service (systemctl enable monitor-steamapps && systemctl start monitor-steamapps)

Now if userA downloads a game, it will be saved under "/user-data/userA/steamapps-upper/" and if this does not exist under the master you could simply copy or move the games files to your master steamapps (move is instant, copy takes space), could be done automatically with docker events.

Let me know if you want an example of that.

This one here starts a monitor which keeps track of wolf steam clients who die

/etc/systemd/system/monitor-wolf-steam-clients.service

[Unit]
Description=Monitors Wolf Clients for steam data
After=docker.service
Requires=docker.service

[Service]
ExecStart=/usr/local/bin/monitor-steamapps-sync.sh
Restart=always
RestartSec=5
User=root

[Install]
WantedBy=multi-user.target

This is the monitor script used by the service

/usr/local/bin/monitor-steamapps-sync.sh

#!/bin/bash

docker events --filter event=die --filter container=WolfSteam --format '{{json .}}' | while read -r event; do
    # Extract container name from the event JSON
    #container_name=$(docker inspect --format '{{.Name}}' $(echo "$event" | jq -r .id) | sed 's|/||')
    container_name=$(echo "$event" | jq -r '.Actor.Attributes.name // empty')

    if [[ $container_name =~ WolfSteam_([0-9]+) ]]; then
        clientid="${BASH_REMATCH[1]}"
        echo "Container died with clientid: $clientid"

        # Call your sync script for this client
        sync-steamapps.sh "$clientid"
    fi
done

This is the script that moves gamedata from client to master folder when client ends their session

/usr/local/bin/sync-steamapps.sh

#!/bin/bash
clientid="$1"

SRC="/user-data/$clientid/steamapps-upper/"
DST="/games/steamapps"

for manifest in "$SRC"/appmanifest_*.acf; do
    [ -f "$manifest" ] || continue

    gameid=$(basename "$manifest" | sed -E 's/appmanifest_([0-9]+)\.acf/\1/')

    # Read installdir from ACF-file
    installdir=$(awk -F'"' '/"installdir"/ { print $4; exit }' "$manifest")

    # Check if destination doesn't have appmanifest
    if [ ! -f "$DST/appmanifest_${gameid}.acf" ]; then
        echo "[INFO] Moving appmanifest for $gameid"
        mv "$manifest" "$DST/"

        # Also move games files if exists
        if [ -n "$installdir" ] && [ -d "$SRC/common/$installdir" ]; then
            echo "[INFO] Moving game data for $gameid ($installdir)"
            mv "$SRC/common/$installdir" "$DST/common/"
            echo "[INFO] Gamedata for $gameid ($installdir) moved"
        else
            echo "[WARN] Gamefolder for $gameid ($installdir) missing"
        fi
    fi
done

These scripts needs to be executable:
chmod +x /usr/local/bin/monitor-steamapps-sync.sh /usr/local/bin/sync-steamapps.sh
and the service needs to be enabled and started:
systemctl enable monitor-wolf-steam-clients.service
systemctl start monitor-wolf-steam-clients.service

EDIT: updated the fstab part with a "noauto" and added a mount on boot loop in the service as in unique situations the fstab can make your host system unbootable.

EDIT2: Fixed some permission issues

EDIT3: Added service for client session monitor and game install transfer from client to master

<!-- gh-comment-id:3159740264 --> @kearoth commented on GitHub (Aug 6, 2025): I had a go at setting up overlayfs for sharing steamgames between clients To automate this task i used ionotifywait (on ubuntu sudo apt install inotify-tools -y) I also put together a systemd service which launches a monitor script on boot. #Systemd service (nano /etc/systemd/system/monitor-steamapps.service) ## Service start ## ``` [Unit] Description=Watch for steamapps creation and mount overlay After=local-fs.target [Service] ExecStart=/usr/local/bin/mount_steam_overlay.sh Restart=always User=root [Install] WantedBy=multi-user.target ``` This uses a script (/usr/local/bin/mount_steam_overlay.sh) Said script (nano /usr/local/bin/mount_steam_overlay.sh && chmod +x /usr/local/bin/mount_steam_overlay.sh) ## Script start ## ``` #!/bin/bash # Mount at boot overlays=$(cat /etc/fstab | grep overlay | cut -f4 -d' ') for overlay in $overlays; do mount $overlay done WATCH_BASE="/etc/wolf" STEAM_APPS="/games/steamapps" owner="ownername" group="groupname" # Watches the directory for new folders (numerical names) inotifywait -m -e create --format '%f' "$WATCH_BASE" 2>/dev/null | while read -r newdir; do if [[ "$newdir" =~ ^[0-9]+$ ]]; then echo "[INFO] New user found: $newdir" user="$newdir" steamapps_path="$WATCH_BASE/$user/Steam/.steam/debian-installation/steamapps" echo "[INFO] Creating path for $user..." mkdir -p "/user-data/$user/steamapps-upper" \ "/user-data/$user/steamapps-workdir" \ "$steamapps_path" chown $owner:$group $WATCH_BASE/$user/Steam -R echo "[INFO] Adding mount line to fstab if not existing..." if ! grep -q "Userdata_$user" /etc/fstab; then echo "overlay $steamapps_path overlay defaults,noauto,lowerdir=$STEAM_APPS,upperdir=/user-data/$user/steamapps-upper,workdir=/user-data/$user/steamapps-workdir,comment=Userdata_$user 0 2" >> /etc/fstab fi echo "[INFO] Mounting overlay for $user..." mount "$steamapps_path" fi done ``` Edit WATCH_BASE, STEAM_APPS, owner & group as needed, this is an example where you could have your "master" steamapps folder You can then enable and start the service (systemctl enable monitor-steamapps && systemctl start monitor-steamapps) Now if userA downloads a game, it will be saved under "/user-data/userA/steamapps-upper/" and if this does not exist under the master you could simply copy or move the games files to your master steamapps (move is instant, copy takes space), could be done automatically with docker events. ~~Let me know if you want an example of that.~~ This one here starts a monitor which keeps track of wolf steam clients who die ## /etc/systemd/system/monitor-wolf-steam-clients.service ``` [Unit] Description=Monitors Wolf Clients for steam data After=docker.service Requires=docker.service [Service] ExecStart=/usr/local/bin/monitor-steamapps-sync.sh Restart=always RestartSec=5 User=root [Install] WantedBy=multi-user.target ``` This is the monitor script used by the service ## /usr/local/bin/monitor-steamapps-sync.sh ``` #!/bin/bash docker events --filter event=die --filter container=WolfSteam --format '{{json .}}' | while read -r event; do # Extract container name from the event JSON #container_name=$(docker inspect --format '{{.Name}}' $(echo "$event" | jq -r .id) | sed 's|/||') container_name=$(echo "$event" | jq -r '.Actor.Attributes.name // empty') if [[ $container_name =~ WolfSteam_([0-9]+) ]]; then clientid="${BASH_REMATCH[1]}" echo "Container died with clientid: $clientid" # Call your sync script for this client sync-steamapps.sh "$clientid" fi done ``` This is the script that moves gamedata from client to master folder when client ends their session ## /usr/local/bin/sync-steamapps.sh ``` #!/bin/bash clientid="$1" SRC="/user-data/$clientid/steamapps-upper/" DST="/games/steamapps" for manifest in "$SRC"/appmanifest_*.acf; do [ -f "$manifest" ] || continue gameid=$(basename "$manifest" | sed -E 's/appmanifest_([0-9]+)\.acf/\1/') # Read installdir from ACF-file installdir=$(awk -F'"' '/"installdir"/ { print $4; exit }' "$manifest") # Check if destination doesn't have appmanifest if [ ! -f "$DST/appmanifest_${gameid}.acf" ]; then echo "[INFO] Moving appmanifest for $gameid" mv "$manifest" "$DST/" # Also move games files if exists if [ -n "$installdir" ] && [ -d "$SRC/common/$installdir" ]; then echo "[INFO] Moving game data for $gameid ($installdir)" mv "$SRC/common/$installdir" "$DST/common/" echo "[INFO] Gamedata for $gameid ($installdir) moved" else echo "[WARN] Gamefolder for $gameid ($installdir) missing" fi fi done ``` These scripts needs to be executable: **chmod +x /usr/local/bin/monitor-steamapps-sync.sh /usr/local/bin/sync-steamapps.sh** and the service needs to be enabled and started: **systemctl enable monitor-wolf-steam-clients.service** **systemctl start monitor-wolf-steam-clients.service** EDIT: updated the fstab part with a "noauto" and added a mount on boot loop in the service as in unique situations the fstab can make your host system unbootable. EDIT2: Fixed some permission issues EDIT3: Added service for client session monitor and game install transfer from client to master
Author
Owner

@salty2011 commented on GitHub (Aug 8, 2025):

hey @kearoth — great work on the overlayFS mapping. This is exactly the direction I had in mind. The one place I think we should not go is syncing “user-side changes” back into the shared (read-only) library. A few gotchas I’ve hit:
• Some titles write saves/configs inside the install tree. If we promote those files back into the shared library, we leak one player’s state to everyone.
• Proton prefixes live under steamapps/compatdata (library-relative). Sharing or “merging” those between users is a recipe for broken permissions and cross-user contamination. The Proton/Steam trackers call this out pretty plainly. 

Instead, I’d keep the model to: shared, read-only base → per-user writable overlay, and only install/update the base via a central service (no background sync from user profiles).

# Host (example)
/srv/wolf/
  games/
    steam/
      steamapps/
        common/
          <GameFolder>/            # LOWER: shared install for this game (ro)
        # (Do NOT expose all of steamapps; mount just the title you need)
  users/
    <userA>/
      home/                         # user's $HOME in the container
      compatdata/<appid>/           # Proton/Wine prefix for this title (rw)
      overlay/
        <appid>/                    # per-game overlay scope
          upper/                    # UPPER for writes into <GameFolder>
          work/                     # WORK
    <userB>/
      home/
      compatdata/<appid>/
      overlay/<appid>/{upper,work}

Inside the Steam container (per user)

# Read-only base for JUST this game
/mnt/lower   -> /srv/wolf/games/steam/steamapps/common/<GameFolder>      (ro)

# Per-user overlay layer for writes inside the game dir
/mnt/upper   -> /srv/wolf/users/<user>/overlay/<appid>/upper              (rw)
/mnt/work    -> /srv/wolf/users/<user>/overlay/<appid>/work               (rw)

# Proton prefix (per-user, per-app) – must live under the SAME library root:
# (adjust if your library root isn’t /home/retro/steam)
/home/retro/steam/steamapps/compatdata/<appid> -> /srv/wolf/users/<user>/compatdata/<appid>  (rw)

# App manifest so Steam “sees” the install:
# (bind the single file from your shared base library)
/home/retro/steam/steamapps/appmanifest_<appid>.acf -> /srv/wolf/games/steam/steamapps/appmanifest_<appid>.acf  (ro)

# User HOME (configs, logs, etc.)
# NOTE: Wolf already mounts this as /home/retro; don’t double-mount unless you’re running a custom container.
/home/retro -> ${HOST_APPS_STATE_FOLDER}/<state_folder>/<app_title>  (rw)

We can then leverage WolfManager to do the actual game installation and setup in Wolf. Next steps would be to take the overlayFS automation you’ve built and wire it into that flow.

Optional (Steam UI listing): in some cases the Steam client won’t list the title until the metadata is present. Ensuring the matching appmanifest_.acf is bound in (as above) usually handles it. To have the game appear in the client without the need to click install, we would also need to generate the relevant Steam metadata (e.g., a user shortcut entry) at runtime. That avoids users “installing” over the shared base while still letting Wolf launch the game directly.

<!-- gh-comment-id:3167132176 --> @salty2011 commented on GitHub (Aug 8, 2025): hey @kearoth — great work on the overlayFS mapping. This is exactly the direction I had in mind. The one place I think we should not go is syncing “user-side changes” back into the shared (read-only) library. A few gotchas I’ve hit: • Some titles write saves/configs inside the install tree. If we promote those files back into the shared library, we leak one player’s state to everyone. • Proton prefixes live under steamapps/compatdata (library-relative). Sharing or “merging” those between users is a recipe for broken permissions and cross-user contamination. The Proton/Steam trackers call this out pretty plainly.  Instead, I’d keep the model to: shared, read-only base → per-user writable overlay, and only install/update the base via a central service (no background sync from user profiles). ``` # Host (example) /srv/wolf/ games/ steam/ steamapps/ common/ <GameFolder>/ # LOWER: shared install for this game (ro) # (Do NOT expose all of steamapps; mount just the title you need) users/ <userA>/ home/ # user's $HOME in the container compatdata/<appid>/ # Proton/Wine prefix for this title (rw) overlay/ <appid>/ # per-game overlay scope upper/ # UPPER for writes into <GameFolder> work/ # WORK <userB>/ home/ compatdata/<appid>/ overlay/<appid>/{upper,work} ``` Inside the Steam container (per user) ``` # Read-only base for JUST this game /mnt/lower -> /srv/wolf/games/steam/steamapps/common/<GameFolder> (ro) # Per-user overlay layer for writes inside the game dir /mnt/upper -> /srv/wolf/users/<user>/overlay/<appid>/upper (rw) /mnt/work -> /srv/wolf/users/<user>/overlay/<appid>/work (rw) # Proton prefix (per-user, per-app) – must live under the SAME library root: # (adjust if your library root isn’t /home/retro/steam) /home/retro/steam/steamapps/compatdata/<appid> -> /srv/wolf/users/<user>/compatdata/<appid> (rw) # App manifest so Steam “sees” the install: # (bind the single file from your shared base library) /home/retro/steam/steamapps/appmanifest_<appid>.acf -> /srv/wolf/games/steam/steamapps/appmanifest_<appid>.acf (ro) # User HOME (configs, logs, etc.) # NOTE: Wolf already mounts this as /home/retro; don’t double-mount unless you’re running a custom container. /home/retro -> ${HOST_APPS_STATE_FOLDER}/<state_folder>/<app_title> (rw) ``` We can then leverage WolfManager to do the actual game installation and setup in Wolf. Next steps would be to take the overlayFS automation you’ve built and wire it into that flow. Optional (Steam UI listing): in some cases the Steam client won’t list the title until the metadata is present. Ensuring the matching appmanifest_<appid>.acf is bound in (as above) usually handles it. To have the game appear in the client without the need to click install, we would also need to generate the relevant Steam metadata (e.g., a user shortcut entry) at runtime. That avoids users “installing” over the shared base while still letting Wolf launch the game directly.
Author
Owner

@kearoth commented on GitHub (Aug 8, 2025):

@salty2011 Since it's basically only me, myself and i on my wolf host, the idea of leaking players states didn't occur to me.

I do think the ideal situation would be that you chose a game from the Steam UI listing and if it was preinstalled & updated it would launch direcly (mounting the required overlays on demand) otherwise a background download & update service handles it and maybe shows a progress bar to the user.

Problem with steamcli is that you need a login, either anon or a user that owns rights to a specific game to be able to download/update it.

Other than handling the login to steamcli(when required) smoothly i see no problem with the background service and can problably have that fixed in the next few days. As i already thought about setting up a background service for downloading/updating games as i don't want to have a client connected 24/7.

<!-- gh-comment-id:3167209532 --> @kearoth commented on GitHub (Aug 8, 2025): @salty2011 Since it's basically only me, myself and i on my wolf host, the idea of leaking players states didn't occur to me. I do think the ideal situation would be that you chose a game from the Steam UI listing and if it was preinstalled & updated it would launch direcly (mounting the required overlays on demand) otherwise a background download & update service handles it and maybe shows a progress bar to the user. Problem with steamcli is that you need a login, either anon or a user that owns rights to a specific game to be able to download/update it. Other than handling the login to steamcli(when required) smoothly i see no problem with the background service and can problably have that fixed in the next few days. As i already thought about setting up a background service for downloading/updating games as i don't want to have a client connected 24/7.
Author
Owner

@salty2011 commented on GitHub (Aug 8, 2025):

Steamcli isn't needed for downloading the games. I poked around PlaytronOS since they had a universal launcher that did all this and discovered they were using SteamKit2 an opensource project which allows for authentication using the qr code method through the steam mobile app etc. was able to successfully get a POC working for that.

Since Wolf by design is focused on on multi user scenarios the solution I've been working on is centred around this expanded scope. I agree the ideal situation would be to just use the steam UI however it's not exactly practical in a multi user setup for the previously mentioned issues.

Also not sure I am following the part on the steam ui listing and background downloading. As in the way I am reading it your suggesting to use the steam ui but if you want to install a game it somehow captures the request and handles it in the background?

For your situation of one user, why even bother with the overlayfs stuff? Would it be easier to just map the steam folder directly in at read/write?

<!-- gh-comment-id:3167242863 --> @salty2011 commented on GitHub (Aug 8, 2025): Steamcli isn't needed for downloading the games. I poked around PlaytronOS since they had a universal launcher that did all this and discovered they were using SteamKit2 an opensource project which allows for authentication using the qr code method through the steam mobile app etc. was able to successfully get a POC working for that. Since Wolf by design is focused on on multi user scenarios the solution I've been working on is centred around this expanded scope. I agree the ideal situation would be to just use the steam UI however it's not exactly practical in a multi user setup for the previously mentioned issues. Also not sure I am following the part on the steam ui listing and background downloading. As in the way I am reading it your suggesting to use the steam ui but if you want to install a game it somehow captures the request and handles it in the background? For your situation of one user, why even bother with the overlayfs stuff? Would it be easier to just map the steam folder directly in at read/write?
Author
Owner

@kearoth commented on GitHub (Aug 8, 2025):

@salty2011 My reason for the overlay stuff is because my clients that i use have very different res, controller input and other stuff that i want to further isolate. It might not be the best solution to my specific problem but it might be a good solution overall for wolf and it piqued my interest.

I'm not sure at how steam handles the shadercache if it is tied to your resolution at all but that might also be a thing to isolate at client level.

Ah, my bad about the steamUI, i meant the wolfmanager/wolfUI.

So a first time client connects to wolf host, sees a UI. Authenticates against steam with the SteamKit2/Qr code. a list of "owned games" are fetched and added to a game library.
Client selects a game and if it is preinstalled it launches otherwise a background service downloads it and adds just the game to a master archive.
This way, only games that you own would be displayed on your client UI.

The way i handle it at the moment isn't ideal, since if userA installs an Adult game and userB is 6 years old it really shouldn't display the game.
But it was a way to quickly confirm how the overlayfs work. I'll rework it to a better & safer version and in my case i'll stick to steamcli for now.

EDIT: fixed a funny typo

<!-- gh-comment-id:3167344520 --> @kearoth commented on GitHub (Aug 8, 2025): @salty2011 My reason for the overlay stuff is because my clients that i use have very different res, controller input and other stuff that i want to further isolate. It might not be the best solution to my specific problem but it might be a good solution overall for wolf and it piqued my interest. I'm not sure at how steam handles the shadercache if it is tied to your resolution at all but that might also be a thing to isolate at client level. Ah, my bad about the steamUI, i meant the wolfmanager/wolfUI. So a first time client connects to wolf host, sees a UI. Authenticates against steam with the SteamKit2/Qr code. a list of "owned games" are fetched and added to a game library. Client selects a game and if it is preinstalled it launches otherwise a background service downloads it and adds just the game to a master archive. This way, only games that you own would be displayed on your client UI. The way i handle it at the moment isn't ideal, since if userA installs an Adult game and userB is 6 years old it really shouldn't display the game. But it was a way to quickly confirm how the overlayfs work. I'll rework it to a better & safer version and in my case i'll stick to steamcli for now. EDIT: fixed a funny typo
Author
Owner

@duskmoss commented on GitHub (Aug 27, 2025):

Glad to see this is still being considered! My use cases ended up not panning out at the time I was looking into it in #69 but but I'm interested in wolf again and hopeful something comes of this!

<!-- gh-comment-id:3229647480 --> @duskmoss commented on GitHub (Aug 27, 2025): Glad to see this is still being considered! My use cases ended up not panning out at the time I was looking into it in #69 but but I'm interested in wolf again and hopeful something comes of this!
Author
Owner

@salty2011 commented on GitHub (Aug 27, 2025):

Hey @kearoth

You're better off sticking to SteamKit2 over steamcli as its auth method is more secure. The QR code auth means the user is authenticating using an official steam app and issues a token to the client.

I'm wanting to integrate library management into WolfManager but community plugins. So basically anyone could make a library plugin that interfaces with WolfManager.

What's stopping me initially was WolfUI progression as that introduces the profiles api which enables the assignment of games, folder management. All things that make it easier for WolfManager.

Last parts sadly has been time on my side had a few situations that required my focus

<!-- gh-comment-id:3229770604 --> @salty2011 commented on GitHub (Aug 27, 2025): Hey @kearoth You're better off sticking to SteamKit2 over steamcli as its auth method is more secure. The QR code auth means the user is authenticating using an official steam app and issues a token to the client. I'm wanting to integrate library management into WolfManager but community plugins. So basically anyone could make a library plugin that interfaces with WolfManager. What's stopping me initially was WolfUI progression as that introduces the profiles api which enables the assignment of games, folder management. All things that make it easier for WolfManager. Last parts sadly has been time on my side had a few situations that required my focus
Author
Owner

@ABeltramo commented on GitHub (Aug 27, 2025):

Welcome back @duskmoss !

Re-reading your original issue I think you might find that the WIP wolf-ui might fill your needs 😉

<!-- gh-comment-id:3229867000 --> @ABeltramo commented on GitHub (Aug 27, 2025): Welcome back @duskmoss ! Re-reading your original issue I think you might find that the WIP [wolf-ui](https://github.com/games-on-whales/wolf/pull/179#issuecomment-3058215348) might fill your needs 😉
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
games-on-whales/wolf#58
No description provided.