Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Permission error #25

Closed
tapir opened this issue May 18, 2022 · 13 comments
Closed

Permission error #25

tapir opened this issue May 18, 2022 · 13 comments

Comments

@tapir
Copy link

tapir commented May 18, 2022

Trying to run it through docker-compose and I get this error also the host folder volume is bound to is empty after the installation.

  csgo:
    image: timche/csgo:sourcemod
    container_name: csgo-server
    restart: unless-stopped
    depends_on:
      - mariadb
    volumes:
      - ${HOME}/csgo-data:/home/csgo/server
      - ${HOME}/data:/usr/csgo
    environment:
      - CSGO_PW=xxxx
      - CSGO_RCON_PW=xxxx
      - CSGO_GSLT=xxxxx
      - CSGO_WS_API_KEY=xxxx
    ports:
      - "27015:27015/tcp"
      - "27015:27015/udp"
      - "27020:27020/udp"
Success! App '740' fully installed.
Work thread 'CHTTPClientThreadPool:1' is marked exited, but we could not immediately join prior to deleting -- proceeding without join
+ set +x
> Done
touch: cannot touch '/home/csgo/server/installed.lock': Permission denied
> Installing server ...
+ /home/csgo/Steam/steamcmd.sh +force_install_dir /home/csgo/server +login anonymous +app_update 740 validate +quit
WARNING: setlocale('en_US.UTF-8') failed, using locale: 'C'. International characters may not work.
Redirecting stderr to '/home/csgo/Steam/logs/stderr.txt'
[  0%] Checking for available updates...
[----] Verifying installation...
Steam Console Client (c) Valve Corporation - version 1652487999
-- type 'quit' to exit --
Loading Steam API...OK

Connecting anonymously to Steam Public...OK
Waiting for client config...OK
@Zerka30
Copy link

Zerka30 commented Jun 2, 2022

I get the same error. If we take a closer look at the user rights on the folder that is causing the error, we realize that the user does not have write permission on the folder.

csgo@server:~$ ls -al
drwxr-xr-x 1 csgo csgo 4096 Jun  2 14:31 .steam
drwxr-xr-x 1 csgo csgo 4096 Jun  2 14:31 Steam
drwxr-xr-x 2 root root 4096 Jun  2 13:52 server
-rwxr-xr-x 1 root root 4652 May 31 06:04 server.sh
-rwxr-xr-x 1 root root 3434 May 31 06:04 server_sourcemod.sh

I haven't tried it yet, but I run the command as root. Did you try as single user?

And have you found a solution since?

@tatupesonen
Copy link

Experiencing the same issue.

@Zerka30
Copy link

Zerka30 commented Jun 7, 2022

For information, there is a possibility to run the container in spite of this problem of permissions in a very specific case. I've managed to do it several times. I'm currently investigating because every other time I modify my docker-compose I get this error again 😓

I'll get back to you if I find a way to make it work every time

@Tardnicus
Copy link

I've been trying to set this container up in compose and have run into the same issue. I've done some investigating and I think I've narrowed the problem down.

The Problem

Firstly, the problem we're all getting is related to using bind mounts. Makes sense why we want to use them, as we want to have access to the server files on the host filesystem. Unfortunately though, it seems that no matter how hard you try, as soon as you instruct the bind mount to be made, the directory IN THE CONTAINER gets the user:group permissions of the directory from the host machine.

This is similar to what @Zerka30 pointed out, though from my experience it's not always root. On my server, I log in using an unprivileged user (named server), instead of root or another privileged server. When I build the container from that user's context and examine the filesystem, I get this:

csgo@5327198328cb:~$ ls -l
total 24
drwxr-xr-x 1 csgo csgo 4096 Jun 20 07:12 Steam
drwxr-xr-x 2 1001 1001 4096 Jun 20 07:10 server
-rwxr-xr-x 1 1001 1001 4652 Jun 20 07:11 server.sh
-rwxr-xr-x 1 root root 3434 Jun 11 18:04 server_sourcemod.sh

On my machine, the user ID and group ID of my server user are both 1001, so this checks out. Note that it's showing as ids instead of names because the container knows nothing about how my users are set up.

What I Tried

The first thing I tried were the suggestions from this GH issue. However, as you can probably guess that was a bit of a red herring because that issue concerned volumes, not bind mounts.

That took me a while to diagnose (and the steps in that issue comment didn't seem to affect anything anyway) so I tried a more focused search and came to this WP article discussing bind mounts. The steps in this article did in fact work, although if you want a quick fix, you'll have to accept some jank.

The (Temporary) Solution

Here's what you have to change:

In the Dockerfile:

@@ -8,8 +8,10 @@ RUN apt-get update \
     rsync=3.1.3-6 \
     unzip=6.0-23+deb10u2 \
     wget=1.20.1-1.1 \
-    && rm -rf /var/lib/apt/lists/* \
-    && useradd -m csgo
+    && rm -rf /var/lib/apt/lists/*
+
+RUN useradd -u 1001 -o -m csgo && \
+    groupmod -g 1001 csgo

 USER csgo

Basically, just hardcode the user's UID/GID that matches the user on the host that owns the directory, and the bind mount will not have the same permission problems when using the container thereafter. However, the solution is kind of janky, as mentioned.

Alternate Solutions

While this works for now, some better ways to do this are to:

  1. Use volumes entirely (and forego the convenience of having access to the server files on your host)
  2. Still use bind mounts, but have something configurable a la https://hub.docker.com/r/wolveix/satisfactory-server
    • This method solves the problem by allowing you to specify a UID/GID in the environment variables, which allows you to have a consistent Dockerfile. I've been using this container for a bit and it seems like a pretty good system.

If we wanted to integrate something like 2. into this image the Dockerfile would of course need some tweaking. We could have it such that it reverts to the "stock" behavior when the environment variables are not specified.

If @timche thinks it's a good idea, I could make a PR for it. If not, I suppose I'll just fork the project and make the changes there.

@Zerka30
Copy link

Zerka30 commented Jun 20, 2022

Nice work man,

I had not been so far in my analysis, probably due to lack of experience 😅

But I can confirm that I could also see that using an unprivileged user did not magically solve the problem.

Now we have the real reason, and I hope that timche will accept the changes.

@timche
Copy link
Owner

timche commented Jun 20, 2022

Thanks for looking into it @Tardnicus! https://hub.docker.com/r/wolveix/satisfactory-server also uses root which is bad security practice, but they've explained it.

Before I can make a decision, I'd like to get a better understand of the following:

  1. Why do you need to use bind mount and can't use a volume instead?
  2. What's missing at the custom files dir (/usr/csgo) that you've to opt in for a bind mount?

@Tardnicus
Copy link

No problem! Happy to help. I actually missed that part in the documentation about root, so thanks for pointing that out.

  1. Bind mounts are a bit more convenient in a server-hosting setting IMO, since you'll have quick access to the files you need to edit on your own system, with your own tools (I frequently edit these files). When the files you need to edit are in volumes, it's a bit harder to edit them if you need to, though it's obviously not impossible. You either need to exec bash it if it's running, or mount it in busybox. Both are workable, but it's definitely more convenient if the files are on your host OS.

  2. Nothing actually, and you have a good point. I would normally argue the point I made in 1. but because of the way you've set up the overrides directory, there's no need for it. The bind mount that would be created for /usr/csgo doesn't suffer from the same problem because the default mode for files/directories for everyone are r--/r-x, which means that the image will have no issues reading anything there.

In fact, when looking back at it now, when trying to convert the docker run command listed in the README here, I misread the -v flags and thought they both were bind mounts, which is I think how we all encountered this issue. @tapir definitely did the same thing I did in their OP.

So, to recap -- I think you have it set up reasonably, with a volume for the csgo server data and a bind mount for override files. Since we have the overrides dir on the host filesystem, there's no reason to edit the data in the volume directly. I think the initial confusion on which is a volume and which is a bind mount caused this issue to crop up and we all think it's a problem with the way it's set up here rather than our own misunderstanding.

Perhaps adding an example docker-compose.yml with the proper bind mount/volume to the README could go a long way for people who (1) want to set it up using compose and (2) would miss the bind/volume discrepancy.

I finally have a working setup using my newfound knowledge, so I can make a documentation PR, if you'd like.

@timche
Copy link
Owner

timche commented Jun 23, 2022

Thanks for elaborating @Tardnicus.

I highly recommend to not modify the server files directly in the volume/bind mount. The reason why the custom files dir feature has been added is:

  1. It follows the Docker philosophy of being able to replicate servers (containers) on any host by just providing a "config".
  2. The custom server files can be version controlled.
    • You don't want to backup a 20GB folder when you only need the configs.
  3. It allows updates of the server and mods which may overwrite previously modified server files in the process.
    • Updating SourceMod is horrible as you've to extract the whole archive and have to manually check which files you want to overwrite if you do it that way.
    • Your modified SourceMod files will definitely be overwritten when you trigger an update and when you don't have backups, all the work is gone.

@Tardnicus
Copy link

What you said is perfectly fair, and I see more why you've chosen to implement it this way. I definitely agree with you on the updating Sourcemod front. Good god, that was a nightmare when I had the unfortunate task of manually updating it.

Not sure if this is out of the scope of this issue, but I was wondering if there was any special behavior for controlling when a file is deleted? For example, when trying out different SM plugins, after deleting it from my overrides directory the change is not reflected in the volume after restart (i.e. the mod I removed is still there). Of course, this makes perfect sense, as rsync is not configured to delete files from the target directory that don't exist in the source directory -- that would go against the point of an overrides directory. With mods I realize there are the SOURCEMOD_PLUGINS_ENABLED and SOURCEMOD_PLUGINS_DISABLED env vars, though it's not a perfect solution if my aim is to remove them entirely.

I mention this because this is one of the remaining use-cases that would require me to mess around in the volume itself. Perhaps I am missing a smarter way of doing this? I could blow up the volume but that would require me to download the game again (~30 GB).

@castanley
Copy link

castanley commented Sep 20, 2022

Hitting this too - is there an equivalent of
-e PUID=1000
-e PGID=1000

We should be using on instantiation of the container?

@Tardnicus
Copy link

@castanley Sorry for the late response. Assuming I understand your question right, no there is no way to specify the PID/GID on this particular container that would make it work as expected within a bind mount, without rewriting/augmenting it somehow.

Like I mentioned in my above comment, you could either hardcode the PID/GID, or could try to modify the Dockerfile like https://hub.docker.com/r/wolveix/satisfactory-server does it, such that it'll take the environment variables and create the user based on them. This container isn't really set up OOB that way, and just sort of assumes you have write access to everything.

I have this server deployed no problem using a volume, after discovering that bind mounts don't work as well. This is definitely the intended way to do it, especially given the custom files dir feature. In most cases you won't need to do any editing outside that custom dir. I still do, occasionally (for example, if I wanted to delete a mod and not have it take up space, or delete a config entirely after I've deleted it from the custom dir folder).

If you're looking for a working example of a docker-compose.yml file, here you go:

version: '3'
services:
    my-csgo-server:
        image: 'timche/csgo:sourcemod'
        network_mode: host
        volumes:
            - 'my-csgo-server:/home/csgo/server'
            - '/home/.../my-csgo-server/overrides:/usr/csgo'
        environment:
            - CSGO_GSLT=${LOGIN_TOKEN}
            # ...etc
        restart: 'unless-stopped'
        stdin_open: true
        tty: true

volumes:
    my-csgo-server:

@castanley
Copy link

I have it working but I had to modify it myself which was why I was asking if there was a way natively. Though I should have just looked at the source :)

I don’t run docker because of some security implications and instead run under rootless podman, along with proper SELinux context labels and a restricted UID and GUID. In the event the container gets compromised, access is limited. With my setup I take a least privileged approach so assuming write access everywhere doesn’t work for me 😄

Anywho I got it working - thanks for the reply!

@timche
Copy link
Owner

timche commented Jan 14, 2023

The way how custom files are synchronized now have been changed. It's now using soft links and deleted custom server files are now also removed from the csgo folder. I don't think there's any reason anymore to use bind mounts at all, especially with security in mind.

https://github.com/timche/docker-csgo/releases/tag/4.0.0

@timche timche closed this as completed Jan 14, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants