diff --git a/.github/release-notes/v2.4.5.md b/.github/release-notes/v2.4.5.md new file mode 100644 index 0000000..f06535c --- /dev/null +++ b/.github/release-notes/v2.4.5.md @@ -0,0 +1,8 @@ +### Release Notes + +* While running under Docker, the script will now change the ownership of the runtime directory mounted into the container to be in line with the UID and GID values specified through environment variables `DRPP_UID` and `DRPP_GID`, if both are set (#77). Refer to the [UID and GID section](https://github.com/phin05/discord-rich-presence-plex/blob/v2.4.5/README.md#uid-and-gid) of the README for more information. + +### Installation Instructions + +* [Regular](https://github.com/phin05/discord-rich-presence-plex/blob/v2.4.5/README.md#installation) +* [Docker](https://github.com/phin05/discord-rich-presence-plex/blob/v2.4.5/README.md#run-with-docker) diff --git a/README.md b/README.md index 378db00..de7561a 100644 --- a/README.md +++ b/README.md @@ -184,7 +184,7 @@ Images are available for the following platforms: Mount a directory for persistent data (config file, cache file and log file) at `/app/data`. -The directory where Discord stores its inter-process communication Unix socket file needs to be mounted into the container at `/run/app`. The path for this would be the first non-null value from the values of the following environment variables: ([source](https://github.com/discord/discord-rpc/blob/963aa9f3e5ce81a4682c6ca3d136cddda614db33/src/connection_unix.cpp#L29C33-L29C33)) +The runtime directory where Discord stores its inter-process communication Unix socket file needs to be mounted into the container at `/run/app`. The path for this would be the first non-null value from the values of the following environment variables in the environment Discord is running in: ([source](https://github.com/discord/discord-rpc/blob/963aa9f3e5ce81a4682c6ca3d136cddda614db33/src/connection_unix.cpp#L29C33-L29C33)) * XDG_RUNTIME_DIR * TMPDIR @@ -193,15 +193,35 @@ The directory where Discord stores its inter-process communication Unix socket f If all four environment variables aren't set, `/tmp` is used. -For example, if the environment variable `XDG_RUNTIME_DIR` is set to `/run/user/1000`, that would be the directory that needs to be mounted into the container at `/run/app`. If none of the environment variables are set, you need to mount `/tmp` into the container at `/run/app`. +For example, if the environment variable `XDG_RUNTIME_DIR` is set to `/run/user/1000`, that would be the runtime directory that needs to be mounted into the container at `/run/app`. If none of the environment variables are set, you need to mount `/tmp` into the container at `/run/app`. -### Example +### UID and GID +The environment variables `DRPP_UID` and `DRPP_GID` can be used to specify the UID and GID of the user Discord is running as. You can determine these by running `id` in your terminal as such user. + +If both of the above environment variables are set, the script will change the ownership of `/run/app` and its contents to be in line with the specified UID and GID to prevent issues caused due to insufficient permissions. To skip this ownership change, set the environment variable `DRPP_NO_RUNTIME_DIR_CHOWN` to `true`. Skipping this is necessary only in cases where the runtime directory isn't dedicated exclusively to a single user. + +The ownership of `/app` and its contents will be changed as well. If both of the above environment variables are set, they will determine the ownership. Otherwise, the existing ownership information of `/run/app` will be used. + +### Other Info + +If you're running the container for the first time (when there are no users in the config), set the `DRPP_PLEX_SERVER_NAME_INPUT` environment variable to the name of the Plex server to be added to the config file after user authentication, and check the container logs for the authentication link. + +### Docker Compose example + +```yaml +services: + drpp: + container_name: drpp + image: ghcr.io/phin05/discord-rich-presence-plex:latest + restart: unless-stopped + environment: + DRPP_UID: 1000 + DRPP_GID: 1000 + volumes: + - /run/user/1000:/run/app + - ./drpp:/app/data ``` -docker run -v ./drpp:/app/data -v /run/user/1000:/run/app:ro -d --restart unless-stopped --name drpp ghcr.io/phin05/discord-rich-presence-plex:latest -``` - -If you're running the container for the first time (when there are no users in the config), make sure that the `DRPP_PLEX_SERVER_NAME_INPUT` environment variable is set (see the [environment variables](#configuration---environment-variables) section above), and check the container logs for the authentication link. ### Containerised Discord diff --git a/config/constants.py b/config/constants.py index fa3305c..ed61571 100644 --- a/config/constants.py +++ b/config/constants.py @@ -2,7 +2,7 @@ import os import sys name = "Discord Rich Presence for Plex" -version = "2.4.4" +version = "2.4.5" plexClientID = "discord-rich-presence-plex" discordClientID = "413407336082833418" @@ -18,3 +18,7 @@ isInteractive = sys.stdin and sys.stdin.isatty() isInContainer = os.environ.get("DRPP_IS_IN_CONTAINER", "") == "true" runtimeDirectory = "/run/app" if isInContainer else os.environ.get("XDG_RUNTIME_DIR", os.environ.get("TMPDIR", os.environ.get("TMP", os.environ.get("TEMP", "/tmp")))) ipcPipeBase = runtimeDirectory if isUnix else r"\\?\pipe" +uid = int(os.environ.get("DRPP_UID", "-1")) +gid = int(os.environ.get("DRPP_GID", "-1")) +containerCwd = "/app" +noRuntimeDirChown = os.environ.get("DRPP_NO_RUNTIME_DIR_CHOWN", "") == "true" diff --git a/main.py b/main.py index 9b1fe76..05fd403 100644 --- a/main.py +++ b/main.py @@ -1,4 +1,4 @@ -from config.constants import isInContainer, runtimeDirectory +from config.constants import isInContainer, runtimeDirectory, uid, gid, containerCwd, noRuntimeDirChown from utils.logging import logger import os import sys @@ -7,10 +7,22 @@ if isInContainer: if not os.path.isdir(runtimeDirectory): logger.error(f"Runtime directory does not exist. Ensure that it is mounted into the container at {runtimeDirectory}") exit(1) - statResult = os.stat(runtimeDirectory) - os.system(f"chown -R {statResult.st_uid}:{statResult.st_gid} {os.path.dirname(os.path.realpath(__file__))}") - os.setgid(statResult.st_gid) # pyright: ignore[reportGeneralTypeIssues,reportUnknownMemberType] - os.setuid(statResult.st_uid) # pyright: ignore[reportGeneralTypeIssues,reportUnknownMemberType] + if os.geteuid() == 0: # pyright: ignore[reportGeneralTypeIssues,reportUnknownMemberType] + if uid == -1 or gid == -1: + logger.warning(f"Environment variable(s) DRPP_UID and/or DRPP_GID are/is not set. Manually ensure appropriate ownership of {runtimeDirectory}") + statResult = os.stat(runtimeDirectory) + uid, gid = statResult.st_uid, statResult.st_gid + else: + if noRuntimeDirChown: + logger.warning(f"DRPP_NO_RUNTIME_DIR_CHOWN is set to true. Manually ensure appropriate ownership of {runtimeDirectory}") + else: + os.system(f"chmod 700 {runtimeDirectory}") + os.system(f"chown -R {uid}:{gid} {runtimeDirectory}") + os.system(f"chown -R {uid}:{gid} {containerCwd}") + os.setgid(gid) # pyright: ignore[reportGeneralTypeIssues,reportUnknownMemberType] + os.setuid(uid) # pyright: ignore[reportGeneralTypeIssues,reportUnknownMemberType] + else: + logger.warning(f"Not running as the superuser. Manually ensure appropriate ownership of mounted contents") else: try: import subprocess