Skip to content

Commit b9e9308

Browse files
authored
feat: add PUID and GUID (#82)
* feat(docker): add configurable user and group IDs for non-root user * Introduced `ARG PUID` and `ARG PGID` to allow customization of user and group IDs. * Updated user creation command to use these arguments for better flexibility. * feat(dockerfiles): add bootstrap step for SteamCMD * Added a `RUN steamcmd +login anonymous +quit || true` command to bootstrap SteamCMD in the Dockerfiles for Ubuntu 20.04, 22.04, and 24.04. * This ensures that SteamCMD is properly initialized during the image build process. * feat(readme): update tags section with support details * Enhanced the `Tags` section to include detailed support information for each Ubuntu release. * Added notes on standard support end dates and legacy support for older versions. * Improved clarity on the usage of the Docker image and data persistence instructions. * feat(docker): enhance Dockerfiles and add entrypoint script * Added `gosu` to Dockerfiles for better user switching. * Updated user creation and command execution to run as the `steam` user. * Introduced `docker-entrypoint.sh` to handle UID/GID adjustments at runtime. * Modified README to clarify app installation instructions and data persistence. * fix(readme): correct volume mount syntax in usage examples * Updated volume mount paths in the README to use consistent quoting. * Ensures clarity and correctness for users running Docker commands. * docs: update README to move Notes section * Moved the Notes section to the end of the document for better organization. * Clarified the container's basis on the `steamcmd` container and its primary use for `LinuxGSM` game servers. * fix(readme): correct GitHub Actions workflow link * Updated the GitHub Actions workflow link in the README to reflect the correct path.
1 parent 5fbf06b commit b9e9308

File tree

5 files changed

+276
-13
lines changed

5 files changed

+276
-13
lines changed

Dockerfile.ubuntu-2004

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
FROM ubuntu:20.04
22

33
ARG DEBIAN_FRONTEND=noninteractive
4+
ARG PUID=1000
5+
ARG PGID=1000
46
ARG BUILD_DATE
57
ARG VCS_REF
68

@@ -29,6 +31,7 @@ RUN echo "**** Install SteamCMD ****" \
2931
libsdl2-2.0-0:i386 \
3032
tzdata \
3133
steamcmd \
34+
gosu \
3235
&& ln -s /usr/games/steamcmd /usr/bin/steamcmd \
3336
&& locale-gen en_US.UTF-8 \
3437
&& apt-get -y autoremove \
@@ -39,5 +42,20 @@ RUN echo "**** Install SteamCMD ****" \
3942
# Add unicode support
4043
ENV LANG=en_US.UTF-8
4144

42-
ENTRYPOINT ["steamcmd"]
45+
# Create non-root user (default IDs; can be adjusted at runtime by entrypoint)
46+
RUN groupadd -g "${PGID}" steam \
47+
&& useradd -l -u "${PUID}" -g steam -m -d /home/steam -s /bin/bash steam \
48+
&& mkdir -p /home/steam/Steam \
49+
&& chown -R steam:steam /home/steam
50+
51+
WORKDIR /home/steam
52+
53+
# Bootstrap SteamCMD as steam user
54+
RUN su -s /bin/bash - steam -c 'steamcmd +login anonymous +quit || true'
55+
56+
# Copy entrypoint
57+
COPY docker-entrypoint.sh /docker-entrypoint.sh
58+
RUN chmod +x /docker-entrypoint.sh
59+
60+
ENTRYPOINT ["/docker-entrypoint.sh"]
4361
CMD ["+help", "+quit"]

Dockerfile.ubuntu-2204

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
FROM ubuntu:22.04
22

33
ARG DEBIAN_FRONTEND=noninteractive
4+
ARG PUID=1000
5+
ARG PGID=1000
46
ARG BUILD_DATE
57
ARG VCS_REF
68

@@ -29,6 +31,7 @@ RUN echo "**** Install SteamCMD ****" \
2931
libsdl2-2.0-0:i386 \
3032
tzdata \
3133
steamcmd \
34+
gosu \
3235
&& ln -s /usr/games/steamcmd /usr/bin/steamcmd \
3336
&& locale-gen en_US.UTF-8 \
3437
&& apt-get -y autoremove \
@@ -39,5 +42,20 @@ RUN echo "**** Install SteamCMD ****" \
3942
# Add unicode support
4043
ENV LANG=en_US.UTF-8
4144

42-
ENTRYPOINT ["steamcmd"]
45+
# Create non-root user (default IDs; can be adjusted at runtime by entrypoint)
46+
RUN groupadd -g "${PGID}" steam \
47+
&& useradd -l -u "${PUID}" -g steam -m -d /home/steam -s /bin/bash steam \
48+
&& mkdir -p /home/steam/Steam \
49+
&& chown -R steam:steam /home/steam
50+
51+
WORKDIR /home/steam
52+
53+
# Bootstrap SteamCMD as steam user
54+
RUN su -s /bin/bash - steam -c 'steamcmd +login anonymous +quit || true'
55+
56+
# Copy entrypoint
57+
COPY docker-entrypoint.sh /docker-entrypoint.sh
58+
RUN chmod +x /docker-entrypoint.sh
59+
60+
ENTRYPOINT ["/docker-entrypoint.sh"]
4361
CMD ["+help", "+quit"]

Dockerfile.ubuntu-2404

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ FROM ubuntu:24.04
44
RUN touch /var/mail/ubuntu && chown ubuntu /var/mail/ubuntu && userdel -r ubuntu
55

66
ARG DEBIAN_FRONTEND=noninteractive
7+
ARG PUID=1000
8+
ARG PGID=1000
79
ARG BUILD_DATE
810
ARG VCS_REF
911

@@ -32,6 +34,7 @@ RUN echo "**** Install SteamCMD ****" \
3234
libsdl2-2.0-0:i386 \
3335
tzdata \
3436
steamcmd \
37+
gosu \
3538
&& ln -s /usr/games/steamcmd /usr/bin/steamcmd \
3639
&& locale-gen en_US.UTF-8 \
3740
&& apt-get -y autoremove \
@@ -42,5 +45,20 @@ RUN echo "**** Install SteamCMD ****" \
4245
# Add unicode support
4346
ENV LANG=en_US.UTF-8
4447

45-
ENTRYPOINT ["steamcmd"]
48+
# Create non-root user (default IDs; can be adjusted at runtime by entrypoint)
49+
RUN groupadd -g "${PGID}" steam \
50+
&& useradd -l -u "${PUID}" -g steam -m -d /home/steam -s /bin/bash steam \
51+
&& mkdir -p /home/steam/Steam \
52+
&& chown -R steam:steam /home/steam
53+
54+
WORKDIR /home/steam
55+
56+
# Bootstrap SteamCMD as steam user
57+
RUN su -s /bin/bash - steam -c 'steamcmd +login anonymous +quit || true'
58+
59+
# Copy entrypoint
60+
COPY docker-entrypoint.sh /docker-entrypoint.sh
61+
RUN chmod +x /docker-entrypoint.sh
62+
63+
ENTRYPOINT ["/docker-entrypoint.sh"]
4664
CMD ["+help", "+quit"]

README.md

Lines changed: 187 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,36 +4,213 @@
44
<a href="https://developer.valvesoftware.com/wiki/SteamCMD"><img src="https://user-images.githubusercontent.com/4478206/197542699-ae13797a-78bb-4f37-81c2-d4880fd7709f.jpg" alt="SteamCMD"></a>
55
<br>
66
<a href="https://hub.docker.com/r/gameservermanagers/steamcmd"><img src="https://img.shields.io/docker/pulls/gameservermanagers/steamcmd.svg?style=flat-square&amp;logo=docker&amp;logoColor=white" alt="Docker Pulls"></a>
7-
<a href="https://github.com/GameServerManagers/docker-steamcmd/actions"><img alt="GitHub Workflow Status" src="https://img.shields.io/github/actions/workflow/status/GameServerManagers/docker-steamcmd/docker-publish.yml?style=flat-square"></a>
7+
<a href="https://github.com/GameServerManagers/docker-steamcmd/actions"><img alt="GitHub Workflow Status" src="https://img.shields.io/github/actions/workflow/status/GameServerManagers/docker-steamcmd/action-docker-publish.yml?style=flat-square"></a>
88
<a href="https://www.codacy.com/gh/GameServerManagers/docker-steamcmd/dashboard"><img src="https://img.shields.io/codacy/grade/42d400dcdd714ae080d77fcb40d00f1c?style=flat-square&logo=codacy&logoColor=white" alt="Codacy grade"></a>
99
<a href="https://developer.valvesoftware.com/wiki/SteamCMD"><img src="https://img.shields.io/badge/SteamCMD-000000?style=flat-square&amp;logo=Steam&amp;logoColor=white" alt="SteamCMD"></a>
1010
<a href="https://github.com/GameServerManagers/docker-steamcmd/blob/main/LICENSE"><img src="https://img.shields.io/github/license/gameservermanagers/docker-steamcmd?style=flat-square" alt="MIT License"></a></p>
1111

1212
## About
1313

14-
SteamCMD is a command-line version of the Steam client. It allows you to download and install games on a headless server. This container image builds daily and is available on [Docker Hub](https://hub.docker.com/r/gameservermanagers/steamcmd) as well as [GitHub Container Registry](https://github.com/GameServerManagers/docker-steamcmd/pkgs/container/steamcmd).
14+
SteamCMD is a command-line version of the Steam client. It allows you to download and install games/server apps on a headless server. This container image builds daily and is available on [Docker Hub](https://hub.docker.com/r/gameservermanagers/steamcmd) as well as [GitHub Container Registry](https://github.com/GameServerManagers/docker-steamcmd/pkgs/container/steamcmd).
1515

1616
## Tags
1717

18-
- `latest`, `ubuntu` - Latest Ubuntu LTS release
19-
- `ubuntu-24.04` - Ubuntu 24.04 LTS 'Noble Numbat'
20-
- `ubuntu-22.04` - Ubuntu 22.04 LTS 'Jammy Jackalope'
21-
- `ubuntu-20.04` - Ubuntu 20.04 LTS 'Focal Fossa'
18+
| Tag(s) | Ubuntu Release | Standard Support Ends\* | Notes |
19+
| ------------------ | --------------------------- | ----------------------- | ---------------------------------- |
20+
| `latest`, `ubuntu` | 24.04 LTS (Noble) | April 2029 | Current LTS |
21+
| `ubuntu-24.04` | 24.04 LTS (Noble Numbat) | April 2029 | Current LTS |
22+
| `ubuntu-22.04` | 22.04 LTS (Jammy Jackalope) | April 2027 | Previous LTS |
23+
| `ubuntu-20.04` | 20.04 LTS (Focal Fossa) | April 2025 | Legacy (receives security updates) |
24+
25+
\*Dates are end of standard (free) security updates per Canonical's published LTS schedule. Extended Security Maintenance (ESM) may continue beyond these dates, but images may be deprecated earlier if upstream packages (e.g. SteamCMD dependencies) become unavailable.
2226

2327
## Usage
2428

25-
Docker cli
29+
Pull the latest image and open SteamCMD interactive prompt:
30+
31+
```bash
32+
docker run -it --rm gameservermanagers/steamcmd:latest
33+
```
34+
35+
Download and update an app into the current host directory (example: Garry's Mod Dedicated Server - appid 4020):
36+
37+
```bash
38+
docker run -it --rm \
39+
-e PUID=$(id -u) -e PGID=$(id -g) \
40+
-v "$PWD:/data" \
41+
gameservermanagers/steamcmd:latest \
42+
+force_install_dir /data +login anonymous +app_update 4020 +quit
43+
```
44+
45+
## Data Persistence
46+
47+
SteamCMD stores its own library data (manifests, depots, workshop cache) in `/home/steam/.local/share/Steam`. We use `+force_install_dir` to place the app files in its own directory. If you omit `+force_install_dir` (or put it after the first `+app_update`) the app installs under:
48+
49+
```text
50+
/home/steam/.local/share/Steam/steamapps/common/<AppName>
51+
```
52+
53+
Using a distinct mount (e.g. `/data`) along with `+force_install_dir /data` keeps app files seperate from the Steam library cache.
54+
55+
### Bind Mount Example
56+
57+
```bash
58+
docker run -it --rm \
59+
-e PUID=$(id -u) -e PGID=$(id -g) \
60+
-v "$PWD:/data" \
61+
-v "/path/on/host/steamcmd-app:/home/steam/.local/share/Steam" \
62+
gameservermanagers/steamcmd:latest \
63+
+force_install_dir /data +login anonymous +app_update 4020 +quit
64+
```
65+
66+
### Docker Volume Example
2667

2768
```bash
28-
docker run -it gameservermanagers/steamcmd:latest
69+
docker volume create steamcmd-data
70+
docker volume create steamcmd-app
71+
docker run -it --rm \
72+
-v "steamcmd-data:/data" \
73+
-v "steamcmd-app:/home/steam/.local/share/Steam" \
74+
gameservermanagers/steamcmd:latest \
75+
+force_install_dir /data +login anonymous +app_update 4020 +quit
2976
```
3077

31-
Download Counter Strike: Global Offensive Dedicated Server to current host directory.
78+
## User, UID & GID (PUID / PGID)
79+
80+
The image uses a non-root user `steam` (default UID:GID 1000:1000). You can override these IDs at runtime with environment variables `PUID` and `PGID`; the entrypoint will map the user/group before executing SteamCMD so created files match your host user.
81+
82+
### Runtime Override (recommended)
3283

3384
```bash
34-
docker run -it -v $PWD:/data gameservermanagers/steamcmd:latest +force_install_dir /data +login anonymous +app_update 740 +quit
85+
docker run --rm \
86+
-e PUID=1001 -e PGID=1001 \
87+
-v "$PWD/steam-app:/home/steam/.local/share/Steam" \
88+
-v "$PWD/server-data:/data" \
89+
gameservermanagers/steamcmd:latest \
90+
+force_install_dir /data +login anonymous +app_update 4020 +quit
3591
```
3692

93+
### Build-Time Defaults (optional)
94+
95+
You can still bake alternate defaults (not required for most users):
96+
97+
```bash
98+
docker build --build-arg PUID=1001 --build-arg PGID=1001 -t steamcmd:uid1001 -f Dockerfile.ubuntu-2404 .
99+
```
100+
101+
### Troubleshooting permissions
102+
103+
| Symptom | Cause | Fix |
104+
| ------------------------------ | --------------------------------------------------- | --------------------------------------------- |
105+
| Files not showing in directory | Host dir owned by different UID | Run with matching PUID/PGID or chown host dir |
106+
| Steam Guard code every run | Sentry file not persisted (no volume or unwritable) | Mount and ensure ownership of Steam data dir |
107+
| Root-owned files in host mount | Ran container with `--user root` | Remove `--user`; use PUID/PGID env vars |
108+
109+
## Login Examples
110+
111+
SteamCMD supports anonymous and authenticated logins. Use anonymous wherever possible.
112+
113+
### Anonymous (preferred)
114+
115+
```bash
116+
docker run --rm \
117+
-e PUID=$(id -u) -e PGID=$(id -g) \
118+
-v "$PWD/steam-app:/home/steam/.local/share/Steam" \
119+
-v "$PWD/server-data:/data" \
120+
gameservermanagers/steamcmd:latest \
121+
+force_install_dir /data +login anonymous +app_update 4020 +quit
122+
```
123+
124+
### Authenticated (username/password)
125+
126+
Some apps (e.g. certain private branches, tools, or beta depots) require a Steam account.
127+
128+
#### Stateless (no persistent Steam data)
129+
130+
This will almost always trigger Steam Guard on first use and again later because nothing is persisted:
131+
132+
```bash
133+
docker run --rm \
134+
-e PUID=$(id -u) -e PGID=$(id -g) \
135+
-v "$PWD/server-data:/data" \
136+
gameservermanagers/steamcmd:latest \
137+
+@ShutdownOnFailedCommand 1 +force_install_dir /data \
138+
+login "${STEAM_USER}" "${STEAM_PASS}" +app_update 223350 +quit
139+
```
140+
141+
#### Persistent (recommended)
142+
143+
Persist `/home/steam/.local/share/Steam` so the sentry (guard) file is cached and subsequent runs skip the code prompt.
144+
145+
```bash
146+
docker run --rm \
147+
-e PUID=$(id -u) -e PGID=$(id -g) \
148+
-v "$PWD/steam-app:/home/steam/.local/share/Steam" \
149+
-v "$PWD/server-data:/data" \
150+
gameservermanagers/steamcmd:latest \
151+
+@ShutdownOnFailedCommand 1 \
152+
+force_install_dir /data \
153+
+login "${STEAM_USER}" "${STEAM_PASS}" +app_update 223350 +quit
154+
```
155+
156+
Recommendations:
157+
158+
- Always mount persistent Steam data for authenticated workflows (see Data Persistence section) to avoid repeated Steam Guard prompts.
159+
- Pass credentials via environment variables or a one‑shot secret, not hard‑coded in compose files committed to source control.
160+
- After any Steam Guard (2FA / email) prompt, you can supply the code inline: `+login user pass CODE` (third argument) or run once interactively to cache the sentry file in the mounted Steam directory.
161+
- Use a dedicated throwaway account with only the required entitlements; never your main account.
162+
- Treat the mounted Steam data directory as sensitive (contains auth tokens / sentry files). Do not publish it.
163+
164+
### Handling Steam Guard / 2FA
165+
166+
1. Run interactively once with a persistent Steam data mount.
167+
2. Enter the code when prompted (do NOT add it to scripts).
168+
3. Subsequent scripted runs succeed without further prompts because the sentry file is stored.
169+
170+
## SteamCMD Commands
171+
172+
Common commands / flags you can chain after the image name (order matters; see notes below):
173+
174+
| Command / Flag | Purpose | Example Snippet |
175+
| ---------------------------------------------- | ------------------------------------------------------------------- | ---------------------------------------------- |
176+
| `+login anonymous` | Anonymous login (most dedicated servers allow) | `+login anonymous` |
177+
| `+login <user> <pass>` | Authenticated login (needed for some apps / private betas) | `+login myuser mypass` |
178+
| `+@NoPromptForPassword 1` | Suppress interactive password/guard prompts (fail fast) | `+@NoPromptForPassword 1 +login myuser mypass` |
179+
| `+@ShutdownOnFailedCommand 1` | Abort remaining commands if one fails | `+@ShutdownOnFailedCommand 1` |
180+
| `+force_install_dir <path>` | Set target directory for app files (must come before `+app_update`) | `+force_install_dir /data` |
181+
| `+app_update <appid>` | Install or update an app (server / game) | `+app_update 896660` |
182+
| `+app_update <appid> validate` | Integrity check & re-download missing/corrupt files (slower) | `+app_update 740 validate` |
183+
| `+app_status <appid>` | Print install status / progress (debug) | `+app_status 896660` |
184+
| `+app_info_update 1` | Refresh app info cache (used before querying details) | `+app_info_update 1` |
185+
| `+workshop_download_item <appid> <itemid>` | Download a specific workshop item | `+workshop_download_item 4020 3418671232` |
186+
| `+download_depot <appid> <depotid> <manifest>` | Fetch a specific depot/manifest (version pinning) | `+download_depot 90 90 402078904020789` |
187+
| `+sSteamCmdForcePlatformType <os>` | Force platform (linux / windows / macos) for content | `+sSteamCmdForcePlatformType windows` |
188+
| `+runscript <file>` | Execute batch of commands from script file | `+runscript /scripts/install.txt` |
189+
| `+quit` | Exit steamcmd when previous commands complete | `+quit` |
190+
191+
### Command Notes
192+
193+
- Recommended order: `+@ShutdownOnFailedCommand 1 +@NoPromptForPassword 1 +force_install_dir /data +login ... +app_update <appid> validate +quit`
194+
- Always place `+force_install_dir` before the first `+app_update` or files go to the default library (`/home/steam/Steam/steamapps`).
195+
- Append `validate` sparingly; use it for initial install or when corruption is suspected.
196+
- Use a script file (`+runscript`) for complex multi-app workflows; each line should mirror the inline form (without shell quoting issues).
197+
- For workshop items, ensure the base app (server) is installed first; workshop content lands under the app's workshop directory.
198+
- `+download_depot` may require authenticated login and correct branch access; manifests are version-specific.
199+
200+
## FAQ
201+
202+
**Q: How do I find an appid?**
203+
Search [SteamDB](https://steamdb.info) and use the numeric App ID shown.
204+
205+
**Q: Why do I get "Failed to connect" or SSL errors?**
206+
Usually transient network or firewall DPI interference. Retry, or ensure outbound TCP 27015/27036 & HTTPS ports are open.
207+
208+
**Q: Can I run multiple updates in one container invocation?**
209+
Yes, either chain multiple `+app_update` commands or use a runscript file with one per line.
210+
211+
**Q: Do I need to expose any ports?**
212+
No for downloading content. Game server ports are handled by the separate server container you build/run using the downloaded files.
213+
37214
## Notes
38215

39216
This container is based off of the [steamcmd](https://github.com/steamcmd/docker) container and is primarily used for [LinuxGSM](https://linuxgsm.com) game servers.

docker-entrypoint.sh

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
#!/usr/bin/env bash
2+
set -euo pipefail
3+
4+
# Allow runtime override of steam user UID/GID via PUID/PGID env vars.
5+
# If they differ from current numeric IDs, we modify /etc/passwd & /etc/group accordingly
6+
# before executing steamcmd. This requires the container to start as root.
7+
8+
CURRENT_UID="$(id -u steam)"
9+
CURRENT_GID="$(id -g steam)"
10+
DESIRED_UID="${PUID:-$CURRENT_UID}"
11+
DESIRED_GID="${PGID:-$CURRENT_GID}"
12+
13+
if [[ "${DESIRED_GID}" != "${CURRENT_GID}" ]]; then
14+
echo "Updating steam group GID: ${CURRENT_GID} -> ${DESIRED_GID}" >&2
15+
groupmod -o -g "${DESIRED_GID}" steam
16+
# Fix any files owned by old GID inside home (best effort)
17+
find /home/steam -xdev -group "${CURRENT_GID}" -exec chgrp -h "${DESIRED_GID}" {} + || true
18+
fi
19+
20+
if [[ "${DESIRED_UID}" != "${CURRENT_UID}" ]]; then
21+
echo "Updating steam user UID: ${CURRENT_UID} -> ${DESIRED_UID}" >&2
22+
usermod -o -u "${DESIRED_UID}" steam
23+
find /home/steam -xdev -user "${CURRENT_UID}" -exec chown -h "${DESIRED_UID}" {} + || true
24+
fi
25+
26+
# Ensure ownership of Steam data root (non-recursive check first, then minimal fix if needed)
27+
if [[ ! -w /home/steam ]]; then
28+
echo "Warning: /home/steam not writable after UID/GID adjustment" >&2
29+
fi
30+
31+
# Drop to steam user and run steamcmd
32+
exec gosu steam:steam steamcmd "$@"

0 commit comments

Comments
 (0)