Featured image of post Linux System: Share Steam Games Among Multiple Users (Ubuntu as an Example)

Linux System: Share Steam Games Among Multiple Users (Ubuntu as an Example)

Share Steam games among multiple users on Linux system to avoid redownloading

Motivation

I installed the Steam game platform and Proton compatibility layer on my Ubuntu computer before, which allows running Windows games on Linux. However, I didn’t play games much, so I didn’t study it carefully. I just knew that the Proton compatibility layer is quite powerful, and most games run without any problems, even if the “system requirements” of the game only show support for Windows systems.

OS Requirements

Later, I installed an Nvidia RTX 4060 Ti graphics card, mainly to learn CUDA programming and deep learning. Recently, “Black Myth: Wukong” became very popular, and my roommate wanted to play on my computer, so he logged into his Steam account on my computer and downloaded “Black Myth: Wukong”. He found that it ran without any problems.

After watching my roommate play for a while, I also wanted to try it, but I didn’t want to switch Steam accounts back and forth. So I created another system account on Ubuntu, started and logged into Steam, but I found that the games downloaded by my roommate on another account did not appear on my account. Since these games are very large, I don’t want to download them again, so I tried to run the games downloaded by my roommate on my account. In the process, I encountered one problem after another, and finally solved it. Here I record it for reference for those who encounter the same problem.

Prerequisites

If you only want to play Steam games on Linux by yourself, you only need to install Steam and Proton. You can follow the steps in my previous article “Nvidia GPU Settings on Ubuntu: Games, CUDA, Deep Learning, Docker, etc.”. If you don’t want to click in and read, I’ll list the steps here briefly:

Install Steam

  1. Download the Steam installation package:
1
wget https://cdn.cloudflare.steamstatic.com/client/installer/steam.deb
  1. Install Steam:
1
sudo dpkg -i steam.deb
  1. Install missing dependencies:
1
sudo apt-get install -f
  1. Run Steam:
1
steam
  1. Log in to your Steam account

Steam

Install Proton

In Steam, select games that can run on Linux, then click Settings, in the Steam Play tab, check Enable Steam Play for supported titles and Enable Steam Play for all other titles, then select a Proton version from the Steam Play drop-down menu, and click OK.

After Proton is installed, you can run Windows games on Linux.

Install Games

If you are using Steam for the first time and have not purchased any games, you can choose some free games for testing, such as “Dota 2”, “Counter-Strike: Global Offensive”, etc.

Dota 2

Share Games Among Multiple Users

If you want multiple users to play the same game, and don’t want to download it again (after all, a large game may have tens of GBs or even hundreds of GBs), you can continue to see how I operate.

Steam Runtime Environment

Before creating a second user and sharing the same game files, we need to understand the runtime environment of Steam on Linux and the location of the main files.

After installing Steam and Proton according to the steps above, Steam is installed in the system directory, so all users can use the Steam client.

When a user user1 starts the Steam client, Steam will create a .steam directory in the home directory of the user1 user, which contains the user’s Steam configuration files, game files, etc. In the .steam directory, there is a steam directory, which contains the user’s Steam client program, and a steamapps directory, which contains the user’s downloaded game files.

Therefore, if we want to reuse a game, the essence is to let other users also access the game files in the /home/user1/.steam/steam/steamapps directory.

Create a Second User

  1. We create a new system account for the second user, add it to the sudo group, and set a password:

    1
    2
    3
    
    sudo adduser user2
    sudo usermod -aG sudo user2
    sudo passwd user2
    
  2. Switch to the user2 user:

    Click the user icon in the upper right corner of the screen, select Switch Account, and then select the user2 user to log in.

  3. Open and log in to Steam:

    After opening the Steam client, Steam will create a .steam directory in the home directory of the user2 user, but the .steam/steam/steamapps directory of the user2 user does not contain game files. Therefore, when you click the Library page, you will find that the library does not show the games downloaded by the user1 user.

    Next, we will mainly solve this problem, allowing the user2 user to access the game files downloaded by the user1 user and run the games normally.

Share Game Files

  1. The game files downloaded by the user1 user are located in the /home/user1/.steam/steam/steamapps directory. However, we want multiple users to share these game files, so it is best to move these game files to a public directory, such as /opt/games/steam.

    1
    2
    
    sudo mkdir -p /opt/games/steam
    sudo mv /home/user1/.steam/steam/steamapps /opt/games/steam
    
  2. To allow the user2 user to access the game files in the /opt/games/steam directory, we need to set the permissions of the /opt/games/steam directory to 755:

    1
    
    sudo chmod 775 /opt/games/steam
    

    Next we create a new user group steam and add the user1 and user2 users to this user group:

    1
    2
    3
    
    sudo groupadd steam
    sudo usermod -aG steam user1
    sudo usermod -aG steam user2
    

    Then, we set the user group of the /opt/games/steam directory to steam:

    1
    
    sudo chown -R user1:steam /opt/games/steam
    

    Finally, we need to set the setgid permission for the shared folder, so that any files and directories created in the shared folder will have the same user group as the user group of the shared folder. That is, the user group of /opt/games/steam is steam, and the user group of files and directories created in /opt/games/steam will also be steam:

    1
    
    sudo chmod g+s /opt/games/steam
    
  3. To allow the Steam client of the user1 user to access the game files in the /opt/games/steam directory, we need to create a symbolic link in the home directory of the user1 user:

    1
    
    ln -s /opt/games/steam/steamapps /home/user1/.steam/steam/steamapps
    

    Then we open the Steam client under user1, click the Library page, and you will find that the previously downloaded game files are there. If you don’t see it, try restarting the Steam client or restarting the computer.

  4. Similarly for the user2 user, we need to create a symbolic link in the home directory of the user2 user:

    1
    
    ln -s /opt/games/steam/steamapps /home/user2/.steam/steam/steamapps
    

    Then we open the Steam client under user2 (you may need to restart the Steam client or restart the computer first), click the Library page, and you should see the previously downloaded game files.

    However, if you click the Play button, you will find that the game does not start, and there may be no prompts. If you want to find the problem through error logs, you can exit the Steam client, and then run the Steam client in the terminal, so you can see the output information of Steam in the terminal, something like this:

    1
    
    pressure-vessel-wrap[44758]: E: openat(/opt/games/steam/steamapps/common/SteamLinuxRuntime_sniper/sniper_platform_0.20240806.97927/files/.ref): Permission denied
    

    Or like this:

    1
    2
    3
    4
    5
    
    pressure-vessel-wrap[4109614]: W: For best results, "/opt/games/steam/steamapps/common/SteamLinuxRuntime_sniper/sniper_platform_0.20240820.99315/files" and "/opt/games/steam/steamapps/common/SteamLinuxRuntime_sniper/var/tmp-7P6EU2/usr" should both be on the same fully-featured Linux filesystem.
    Adding process 4109770 for gameID 1264970
    wineserver: /opt/games/steam/steamapps/compatdata/1264970/pfx is not owned by you
    wine: using kernel write watches, use_kernel_writewatch 1.
    wine: '/opt/games/steam/steamapps/compatdata/1264970/pfx' is not owned by you
    

    You can also right-click on the game in the Library page, then select Properties, click Verify Integrity in the Local Files tab, and you will find that the integrity check fails.

  5. The above problem is quite strange, because we have set the permissions of the /opt/games/steam directory to 755, and added the user1 and user2 users to the steam user group, but the error message above indicates that the Steam client under the user2 user still cannot access the /opt/games/steam/steamapps/common/SteamLinuxRuntime_sniper/sniper_platform_0.20240806.97927/files/.ref file. Even more strange is that the size of this file is 0! I don’t know what this file is for, but after some exploration, I found some related discussions online:

    These discussions mainly propose two solutions:

    1. After switching system accounts, change the ownership of the /opt/games/steam directory to the current user:

      1
      
      sudo chown -R user2:steam /opt/games/steam
      

      This way, the user2 user can access all files in the /opt/games/steam directory.

      However, this solution is a temporary solution, because every time you switch system accounts, you need to change the ownership of the /opt/games/steam directory, which is obviously inconvenient.

    2. The essence of the above problem is that the Wine used by the Proton compatibility layer does not allow users to access prefix directories owned by other users for security reasons. Therefore, the solution is to create different prefix directories for different users when starting Steam. The prefix directory of Wine is an important concept of the Proton compatibility layer, which stores the game’s configuration files, cache files, etc. By default, Proton stores the prefix directory in the ~/.steam/steam/steamapps/compatdata/ directory, but we can modify the Proton code to create different prefix directories according to the current user.

      To implement this solution, we need to modify the Proton code and then recompile Proton. In fact, there are only two lines of code to modify, see Proton pull request #4861. This pull request was created on GitHub in May 2021, but it has not been merged so far. I don’t know why the Proton developers have not merged this simple but useful pull request. Since the official has not added this feature, we will implement it ourselves next.

Modify and Compile Proton

  1. First, we need to download the source code of Proton:

    1
    2
    
    git clone --recurse-submodules https://github.com/ValveSoftware/Proton.git proton
    cd proton
    
  2. Then, we need to switch to a stable branch, such as proton_9.0. We also need to update the submodules:

    1
    2
    
    git checkout proton_9.0
    git submodule update --init --recursive
    
  3. Next, we need to modify the code of Proton. To do this, we create a new branch, for example, called myfeature-pr4861:

    1
    
    git checkout -b myfeature-pr4861
    

    Open the proton file in the root directory of the Proton project (this is a Python file), find the initialization function __init__ of the CompatData class. We need to modify the line self.base_dir and add a line. The modified code is as follows:

    1
    2
    3
    4
    
    class CompatData:
        def __init__(self, compatdata):
            self.base_dir = compatdata + "/" + str(os.getuid()) + "/"
            os.makedirs(self.base_dir, exist_ok=True)
    

    We only need to modify these two lines of code, see Proton pull request #4861.

    This idea is actually very simple. The underlying layer of Proton uses Wine to run games, and the prefix directory of Wine is stored in the ~/.steam/steam/steamapps/compatdata/ directory. Before making the above modifications, when we run a game as user1, Proton will store the prefix directory in the ~/.steam/steam/steamapps/compatdata/ directory, and its ownership is user1. When we run the same game as user2, Wine will try to access the prefix directory in the ~/.steam/steam/steamapps/compatdata/ directory, but because its ownership is user1, Wine will refuse to access it.

    The above modification is to let Proton create different prefix directories according to the current user. For example, if the uid of user1 is 1000 and the uid of user2 is 1001, when user1 runs a game, Proton will store the prefix directory in the ~/.steam/steam/steamapps/compatdata/1000/ directory, and its ownership is user1; when user2 runs the game, Proton will store the prefix directory in the ~/.steam/steam/steamapps/compatdata/1001/ directory, and its ownership is user2. This solves the ownership conflict problem mentioned above.

  4. Next, we compile Proton. Proton uses container technology, so we need a container tool, such as Docker or Podman. Docker is already installed on my computer, but Docker generally requires sudo permission to run, which will cause a series of permission issues. Therefore, I recommend using Podman, which does not require sudo permission.

    • First, we need to install Podman:

      1
      
      sudo apt install podman
      
    • Then, we create a build folder, which can be placed at the same level as the Proton project:

      1
      2
      3
      
      cd ..
      mkdir build
      cd build
      
    • Next, we configure the build environment using the configuration tool provided by the Proton project:

      1
      
      ../proton/configure.sh --enable-ccache --build-name=myfeature-9.0-pr4861
      
    • Finally, we start compiling Proton:

      1
      
      make
      
  5. After the compilation is completed, we create the installation files of Proton:

    1
    
    make redist
    

    This way, a redist directory will be generated in the build directory, which contains the installation files of Proton.

  6. Install Proton. For user-defined compatibility layers, we can place them in the ~/.steam/root/compatibilitytools.d/ directory. We copy the redist directory to the ~/.steam/root/compatibilitytools.d/ directory:

    1
    
    cp -r redist ~/.steam/root/compatibilitytools.d/myfeature-9.0-pr4861
    

    Note that no matter which account uses Steam, we need to copy the redist directory to the ~/.steam/root/compatibilitytools.d/ directory and change the ownership of the directory to the current user. For example, if it is the user_x user, we can do this:

    1
    
    sudo chown -R user_x:user_x ~/.steam/root/compatibilitytools.d/myfeature-9.0-pr4861
    

Use Customized Proton

After completing the above steps, Steam will be able to detect our customized Proton version.

No matter which account uses Steam, we only need to select our customized Proton version in Steam. After opening Steam, click Steam in the upper left corner, then select Settings, select Compatibility in the sidebar, select our customized Proton version myfeature-9.0-pr4861 from the drop-down menu under Run other products with, and then click OK.

Finally, select a game and click Play, a dialog box will pop up asking you whether to run the game in compatibility mode. I found that it is actually okay not to select compatibility mode:

![Run in compatibility mode](https://img.jinli.io/images/2024/09/19/steam_compatible_mode.md.png)

Steam will spend some time compiling shaders, and then you can enter the game interface!

![Black Myth: Wukong](https://img.jinli.io/images/2024/09/19/black_myth_wukong.md.png)

A Small Issue

When playing games, I found that when the game plays a long cutscene, the monitor will display no input signal after about 30 seconds due to no operation. I suspect that it is caused by the power management mechanism of the graphics card. Running the xset -dpms command can disable power management, which ensures that the display signal will not be interrupted.

With xset q command, you can view the current power management settings, and with the xset command, you can view the help information of the xset command.

Licensed under CC BY-NC-SA 4.0
Last updated on Oct 14, 2024 00:00 UTC
comments powered by Disqus