diff --git a/.github/docs/crowbar.png b/.github/docs/crowbar.png
deleted file mode 100644
index 0f54c39..0000000
Binary files a/.github/docs/crowbar.png and /dev/null differ
diff --git a/.github/docs/docker.svg b/.github/docs/docker.svg
new file mode 100644
index 0000000..1f07539
--- /dev/null
+++ b/.github/docs/docker.svg
@@ -0,0 +1,12 @@
+
diff --git a/.github/workflows/label.yml b/.github/workflows/label.yml
new file mode 100644
index 0000000..94f430e
--- /dev/null
+++ b/.github/workflows/label.yml
@@ -0,0 +1,95 @@
+name: Label Pull Requests 🏷️
+
+on:
+ pull_request:
+ types: [opened, reopened, labeled, unlabeled, synchronize]
+
+permissions:
+ pull-requests: write
+ contents: read
+
+jobs:
+ assign-labels:
+ runs-on: ubuntu-latest
+ name: Assign labels in pull request 🏷️
+ if: github.event.pull_request.merged == false
+ steps:
+ - name: Checkout 🛎️
+ uses: actions/checkout@v4
+
+ - name: Assign Labels 🏷️
+ id: action-assign-labels
+ uses: mauroalderete/action-assign-labels@v1
+ with:
+ pull-request-number: ${{ github.event.pull_request.number }}
+ github-token: ${{ secrets.GITHUB_TOKEN }}
+ conventional-commits: |
+ conventional-commits:
+ - type: 'fix'
+ nouns: ['FIX', 'Fix', 'fix', 'FIXED', 'Fixed', 'fixed']
+ labels: ['bug 🐝', 'fix 🐝']
+ - type: 'feature'
+ nouns: ['FEATURE', 'Feature', 'feature', 'FEAT', 'Feat', 'feat']
+ labels: ['feature ✨']
+ - type: 'breaking_change'
+ nouns: ['BREAKING CHANGE', 'BREAKING', 'MAJOR']
+ labels: ['breaking 💥']
+ - type: 'documentation'
+ nouns: ['doc', 'docu', 'docs', 'document', 'documentation']
+ labels: ['documentation 📖']
+ - type: 'build'
+ nouns: ['build', 'rebuild']
+ labels: ['build 🔧']
+ - type: 'chore'
+ nouns: ['chore', 'tidy', 'cleanup']
+ labels: ['chore 🧹']
+ - type: 'dependencies'
+ nouns: ['dependency', 'dependencies', 'package', 'packages', 'bump', 'dependabot']
+ labels: ['dependencies 🤖']
+ - type: 'duplicate'
+ nouns: ['duplicate', 'dupe', 'copy']
+ labels: ['duplicate 2️⃣']
+ - type: 'good_first_issue'
+ nouns: ['good first issue', 'beginner', 'newcomer', 'first-timer']
+ labels: ['good first issue 🍩']
+ - type: 'help_wanted'
+ nouns: ['help wanted', 'need help', 'assistance required']
+ labels: ['help wanted ❕']
+ - type: 'proposal'
+ nouns: ['proposal', 'suggest', 'suggestion']
+ labels: ['proposal 🔮']
+ - type: 'question'
+ nouns: ['question', 'inquiry', 'query']
+ labels: ['question ❓']
+ - type: 'test'
+ nouns: ['test', 'testing', 'tests']
+ labels: ['test 🧪']
+ - type: 'triage'
+ nouns: ['triage', 'sort', 'prioritize']
+ labels: ['triage ⚠️']
+ - type: 'wontfix'
+ nouns: ['wontfix', 'will not fix', 'not fixing']
+ labels: ['wontfix 🔨']
+ - type: 'style'
+ nouns: ['style', 'formatting', 'format']
+ labels: ['style 🎀']
+ - type: 'security'
+ nouns: ['security', 'secure', 'safety']
+ labels: ['security 🔒']
+ - type: 'performance'
+ nouns: ['performance', 'speed', 'optimization']
+ labels: ['performance 🚀']
+ - type: 'refactor'
+ nouns: ['refactor', 'refactoring', 'rework']
+ labels: ['refactor 🛠']
+ - type: 'release'
+ nouns: ['release', 'deploy', 'deployment']
+ labels: ['release 🚀']
+ - type: 'ci'
+ nouns: ['ci', 'continuous integration', 'CI/CD']
+ labels: ['ci 🚀']
+ - type: 'hacktoberfest'
+ nouns: ['hacktoberfest', 'october', 'open source']
+ labels: ['hacktoberfest 🎃']
+ maintain-labels-not-matched: false
+ apply-changes: true
diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml
index 1922ae4..8416064 100644
--- a/.github/workflows/publish.yml
+++ b/.github/workflows/publish.yml
@@ -111,7 +111,7 @@ jobs:
- name: Create Release 🚀
id: create_release
if: github.ref == 'refs/heads/main'
- uses: softprops/action-gh-release@v1
+ uses: softprops/action-gh-release@v2
with:
tag_name: ${{ steps.create_tag.outputs.new_tag }}
name: ${{ steps.create_tag.outputs.new_tag }}
diff --git a/.github/workflows/sponsors.yml b/.github/workflows/sponsors.yml
new file mode 100644
index 0000000..46f93b3
--- /dev/null
+++ b/.github/workflows/sponsors.yml
@@ -0,0 +1,29 @@
+name: Publish Sponsors 💖
+
+on:
+ workflow_dispatch:
+ schedule:
+ - cron: 30 15 * * 0-6
+permissions:
+ contents: write
+jobs:
+ generate-sponsors:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout 🛎️
+ uses: actions/checkout@v4
+
+ - name: Generate Sponsors 💖
+ uses: JamesIves/github-sponsors-readme-action@v1
+ with:
+ token: ${{ secrets.PAT }}
+ file: "README.md"
+ template: ' '
+ active-only: false
+
+ - name: Deploy to GitHub Pages
+ uses: JamesIves/github-pages-deploy-action@v4
+ with:
+ branch: beta
+ folder: "."
+ commit-message: "chore: Update sponsors 💖 [skip ci]"
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index d9e8d9a..2131dcf 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -1,8 +1,8 @@
-# Contributing ✨
+# Contributing
I appreciate your interest in contributing to this project. Please review the general process and scope before starting a contribution.
-## Scope 🔍
+## Scope
The four main requirements for this project are:
@@ -11,12 +11,12 @@ The four main requirements for this project are:
3. Have the ability to run servers for custom mods.
4. Only support legal usage of Steam and Valve's titles. **It will not, and never will, support the ability to circumvent any licensing or other restrictions Valve imposes.** The project maintainers will report any shady behaviour to Valve and GitHub.
-## Process ✈️
+## Process
1. File an issue on the [Issues board](https://github.com/JamesIves/hlds-docker/issues), or create a discussion on the [Discussions board](https://github.com/JamesIves/hlds-docker/discussions).
2. Once discussed and agreed upon, clone the project.
3. Make your changes.
-4. Validate your changes; at the very least, please build the image and start a server.
+4. Validate your changes; at the very least, please build the image and start a server. [You can learn how to build the images using the guide located here](docs/BUILDING_AN_IMAGE.md).
5. Submit a pull request to the `beta` branch.
6. Once reviewed, your changes will be made available on DockerHub via the `-beta` tag, for example `jives/hlds:cstrike-beta`.
7. After some more tests, changes will be made sent to the `main` branch where the production images will be published.
diff --git a/README.md b/README.md
index 6175026..4895dbc 100644
--- a/README.md
+++ b/README.md
@@ -1,51 +1,37 @@
-# Half-Life Dedicated Server With Docker 🐋 📦
+
-
+# hlds-docker
-Creates a [Half-Life Dedicated Server](https://help.steampowered.com/en/faqs/view/081A-106F-B906-1A7A) instance using [Docker](https://www.docker.com). You can run any games the Half-Life Dedicated Server client supports out of the box, including the ability to add custom configurations, mods and plugins.
+[Half-Life Dedicated Server](https://help.steampowered.com/en/faqs/view/081A-106F-B906-1A7A) powered by [Docker](https://www.docker.com). It supports all the classic [GoldSrc](https://developer.valvesoftware.com/wiki/GoldSrc) Half-Life games and mods, including the ability to add custom configurations and plugins.
Special thank you to all the past and present [GitHub Sponsors](https://github.com/sponsors/JamesIves) 💖.
-## Setup ⚙️
+## Getting Started 🚀
Before starting, ensure you have the [Docker daemon](https://www.docker.com/) and the [Docker CLI tool](https://docs.docker.com/engine/reference/commandline/cli/) installed and available.
> [!IMPORTANT]
> The following steps will not work if you use an ARM architecture system. For best results, use a system running x86-64.
-### Pre-Built Images
+You can run the following in your terminal to get started as quickly as possible. Adjust the image name (`jives/hlds`) so the tag corresponds with the game you want to use. Additionally, you can adjust the server startup arguments by modifying the `command` property; [for a list of available arguments, visit the Valve Developer Wiki](https://developer.valvesoftware.com/wiki/Half-Life_Dedicated_Server).
-If you're just looking to start a server as quickly as possible you can follow these steps to use a pre-built image on [Docker Hub](https://hub.docker.com/repository/docker/jives/hlds) or the [GitHub Container Registry](https://github.com/JamesIves/hlds-docker/pkgs/container/hlds).
-
-1. Create a `docker-compose.yml` file by copying and pasting the example below. Adjust the `image` property so the tag name corresponds with the game you want to use. Additionally you can adjust the server startup arguments by modifying the `command` property; [for a list of available arguments, visit the Valve Developer Wiki](https://developer.valvesoftware.com/wiki/Half-Life_Dedicated_Server).
-
-> [!NOTE]
-> In the majority of cases you'll need to specify `+map` for the server to be joinable.
-
-```yml
-services:
- hlds:
- build: docker
- # 📣 Adjust the image value here with the desired game you want the server to use.
- image: jives/hlds:cstrike
- volumes:
- - "./config:/temp/config"
- - "./mods:/temp/mods"
- ports:
- - "27015:27015/udp"
- - "27015:27015"
- - "26900:2690/udp"
- environment:
- - GAME=${GAME}
- # 📣 Modify your server startup commands here.
- # 📣 Remember: Stating map is based on the game, and will likely be different between images.
- command: +maxplayers 12 +map cs_italy
+```bash
+docker run -d \
+ --name hlds \
+ -v "$(pwd)/config:/temp/config" \
+ -v "$(pwd)/mods:/temp/mods" \
+ -p 27015:27015/udp \
+ -p 27015:27015 \
+ -p 26900:26900/udp \
+ -e GAME=${GAME} \
+ jives/hlds:cstrike \
+ "+maxplayers 12 +map cs_italy" # 📣 Modify your server startup commands here. You can specify the image with the desired game you want the server to run in the line above.
```
> [!TIP]
-> Available images include:
+> The available images are below. When changing the game, be sure to adjust the `+map` parameter, as it may cause the server not to be joinable if the map is unavailable.
>
> - `jives/hlds:valve` ([Half-Life Deathmatch](https://store.steampowered.com/app/70/HalfLife/))
> - `jives/hlds:cstrike` ([Counter-Strike](https://store.steampowered.com/app/10/CounterStrike/))
@@ -55,94 +41,22 @@ services:
> - `jives/hlds:ricohet` ([Ricochet](https://store.steampowered.com/app/60/Ricochet/))
> - `jives/hlds:dod` ([Day of Defeat](https://store.steampowered.com/app/30/Day_of_Defeat/))
> - `jives/hlds:tfc` ([Team Fortress Classic](https://store.steampowered.com/app/20/Team_Fortress_Classic/))
-
-2. Start the image. Once the Half-Life Dedicated Server client starts, you'll receive a stream of messages, including the server's public IP address and any startup errors.
-
-```bash
-docker compose up
-```
-
-3. Connect to your server via the IP address by loading the game on [Steam](https://store.steampowered.com/) and start playing. You must own a copy of the game on Steam in order to play. ⌨️
-
-### Building an Image
-
-If you want to build an image yourself, you can follow the steps below. This can be useful in cases where you want to make changes to the build scripts.
-
-1. Clone this project.
-2. Define the game you want the server to run. You can do this by setting an environment variable on your command line.
-
-```bash
-export GAME=cstrike
-```
-
-Before continuing to the next steps, verify that the environment variable is set by running `echo $GAME` in your terminal. It should send back the variable you just set.
-
-> [!TIP]
-> Available options include:
>
-> - `valve` ([Half-Life Deathmatch](https://store.steampowered.com/app/70/HalfLife/))
-> - `cstrike` ([Counter-Strike](https://store.steampowered.com/app/10/CounterStrike/))
-> - `czero` ([Counter-Strike Condition Zero](https://store.steampowered.com/app/80/CounterStrike_Condition_Zero/))
-> - `dmc` ([Deathmatch Classic](https://store.steampowered.com/app/40/Deathmatch_Classic/))
-> - `gearbox` ([Half-Life Opposing Force](https://store.steampowered.com/app/50/HalfLife_Opposing_Force/))
-> - `ricohet` ([Ricochet](https://store.steampowered.com/app/60/Ricochet/))
-> - `dod` ([Day of Defeat](https://store.steampowered.com/app/30/Day_of_Defeat/))
-> - `tfc` ([Team Fortress Classic](https://store.steampowered.com/app/20/Team_Fortress_Classic/))
-
-3. Build the image.
-
-```sh
-docker compose build
-```
+> Container images are alternatively available on the [GitHub Container Registry](https://github.com/JamesIves/hlds-docker/pkgs/container/hlds).
-4. If you want to modify the server startup arguments, you can provide a `command` property within `docker-compose.yml`; [for a list of available arguments, visit the Valve Developer Wiki](https://developer.valvesoftware.com/wiki/Half-Life_Dedicated_Server).
+Once the command finishes, you can connect to your server via the public IP address by loading the game on [Steam](https://steampowered.com). **You must own a copy of the game on Steam to play**.
> [!NOTE]
-> In the majority of cases you'll need to specify `+map` for the server to be joinable.
+> If you cannot join the server, you can check for errors in the server logs by running `docker ps` to get the container id followed by `docker logs `.
-```yml
-services:
- hlds:
- command: +maxplayers 16 +map cs_italy
-```
+### Docker Compose
-5. Start the image. Once the Half-Life Dedicated Server client starts, you'll receive a stream of messages, including the server's public IP address and any startup errors.
+If you'd prefer to configure your server using [Docker Compose](https://docs.docker.com/compose/), you can pull down the project repository to your system and run `docker compose up` from the root. Make any modifications you need, such as changing the game image and server startup commands in [docker-compose.yml](docker-compose.yml) before running `docker compose up`.
-```bash
-docker compose up
-```
-
-6. Connect to your server via the IP address by loading the game on [Steam](https://store.steampowered.com/) and start playing. You must own a copy of the game on Steam in order to play. ⌨️
-
-## Server Configuration 🔧
-
-### Configs and Plugins
-
-If you wish to add server configurations, such as add-ons, plugins, map rotations, etc, you can add them to the `config` directory. Any configuration files will be copied into the container on start and placed within the folder for the specified game. For example, if you set the game as `cstrike`, the contents of the config folder will be placed within the `cstrike` directory on the server.
-
-### Custom Mods
-
-If you want to run a custom mod, you can do so with the `mods` directory. Similar to the `config` directory, this folder will be copied into your container on start alongside the other game folders.
-
-1. Add your mod files as a sub-directory of `mods`. For example if the mod name is `decay`, you'd place it in `mods/decay`.
-2. Define the `GAME` environment variable so it points to your mod name. This works if you're using a pre-built image `docker-compose.yml` or by building one yourself.
-
-```bash
-export GAME=decay
-```
-
-3. Build the image. If you don't want to build the image, I suggest using the pre-built `jives/hlds:valve` image.
-
-```bash
-docker compose build
-```
-
-4. Start the image. Most Half-Life mods require _specific_ startup arguments, refer to the [Valve Developer Wiki](https://developer.valvesoftware.com/wiki/Half-Life_Dedicated_Server) and the instructions for the mod you're trying to run for more details. You can find details about how to add these above.
-
-```bash
-docker compose up
-```
+## Advanced Setup ⚙️
-## Ownership 🧰
+To customize the server client further, please check out the following advanced setup guides.
-The Half-Life Dedicated Server client, Steam, SteamCMD and the titles themselves are property and ownership of [Valve Software](https://valvesoftware.com). All this software does is make it easier to interface with their provided tooling.
+- [Server Configs and Plugins](docs/SERVER_CONFIGS_AND_PLUGINS.md)
+- [Custom Mods](docs/CUSTOM_MODS.md)
+- [Building a Custom Image](docs/BUILDING_AN_IMAGE.md)
diff --git a/docker-compose.local.yml b/docker-compose.local.yml
new file mode 100644
index 0000000..5b5ed16
--- /dev/null
+++ b/docker-compose.local.yml
@@ -0,0 +1,16 @@
+services:
+ hlds:
+ build:
+ context: .
+ args:
+ - GAME=${GAME}
+ volumes:
+ - "./config:/temp/config"
+ - "./mods:/temp/mods"
+ ports:
+ - "27015:27015/udp"
+ - "27015:27015"
+ - "26900:2690/udp"
+ environment:
+ - GAME=${GAME}
+ command: +maxplayers 12 +log on
diff --git a/docker-compose.yml b/docker-compose.yml
index 5b5ed16..04d3041 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -1,9 +1,9 @@
services:
hlds:
- build:
- context: .
- args:
- - GAME=${GAME}
+ build: docker
+ # 📣 Adjust the image value here with the desired game you want the server to use.
+ image: jives/hlds:cstrike
+ # 📣 Learn more about these volumes in the advanced setup guides.
volumes:
- "./config:/temp/config"
- "./mods:/temp/mods"
@@ -13,4 +13,6 @@ services:
- "26900:2690/udp"
environment:
- GAME=${GAME}
- command: +maxplayers 12 +log on
+ # 📣 Modify your server startup commands here.
+ # 📣 Remember: Stating map is based on the game, and will likely be different between images.
+ command: +maxplayers 12 +map cs_italy
diff --git a/docs/BUILDING_AN_IMAGE.md b/docs/BUILDING_AN_IMAGE.md
new file mode 100644
index 0000000..d75ea47
--- /dev/null
+++ b/docs/BUILDING_AN_IMAGE.md
@@ -0,0 +1,50 @@
+# Building an Image
+
+If you want to build an image yourself, follow the steps below. This can be useful in cases where you want to make changes to the build scripts or add custom functionality. It is also useful for testing changes before submitting a contribution to the project.
+
+1. Clone this project locally.
+2. Define the game you want the server to run. You can do this by setting an environment variable on your command line.
+
+```bash
+export GAME=cstrike
+```
+
+Before continuing to the following steps, verify that the environment variable is set by running `echo $GAME` in your terminal. It should send back the variable you just set.
+
+> [!TIP]
+> Available options include the following, these names are recognized by the `app_set_config 90 mod` command in `hlds.txt`.
+>
+> - `valve` ([Half-Life Deathmatch](https://store.steampowered.com/app/70/HalfLife/))
+> - `cstrike` ([Counter-Strike](https://store.steampowered.com/app/10/CounterStrike/))
+> - `czero` ([Counter-Strike Condition Zero](https://store.steampowered.com/app/80/CounterStrike_Condition_Zero/))
+> - `dmc` ([Deathmatch Classic](https://store.steampowered.com/app/40/Deathmatch_Classic/))
+> - `gearbox` ([Half-Life Opposing Force](https://store.steampowered.com/app/50/HalfLife_Opposing_Force/))
+> - `ricohet` ([Ricochet](https://store.steampowered.com/app/60/Ricochet/))
+> - `dod` ([Day of Defeat](https://store.steampowered.com/app/30/Day_of_Defeat/))
+> - `tfc` ([Team Fortress Classic](https://store.steampowered.com/app/20/Team_Fortress_Classic/))
+
+3. Build the image.
+
+```sh
+docker compose -f docker-compose.local.yml build
+```
+
+4. If you want to modify the server startup arguments, you can provide a `command` property within `docker-compose.local.yml`; [for a list of available arguments, visit the Valve Developer Wiki](https://developer.valvesoftware.com/wiki/Half-Life_Dedicated_Server).
+
+> [!NOTE]
+> In most cases, you'll need to specify `+map` for the server to be joinable.
+
+```yml
+services:
+ hlds:
+ command: +maxplayers 16 +map cs_italy
+```
+
+5. Start the image. Once the Half-Life Dedicated Server client starts, you'll receive a stream of messages, including the server's public IP address and any startup errors.
+
+```bash
+docker compose -f docker-compose.local.yml up
+```
+
+6. Connect to your server via the public IP address by loading the game on [Steam](https://store.steampowered.com/). To play, you must own a copy of the game on Steam.
+7. _Optional_: If you want to start a custom mod, you can modify your `$GAME` environment variable once the image is built before running `docker compose -f docker-compose.local.yml up`. This allows you to add custom scripts to the server image while telling the dedicated server client what mod to use.
diff --git a/docs/CUSTOM_MODS.md b/docs/CUSTOM_MODS.md
new file mode 100644
index 0000000..bcb8124
--- /dev/null
+++ b/docs/CUSTOM_MODS.md
@@ -0,0 +1,19 @@
+# Custom Mods
+
+If you want to run a custom mod, you can do so with the `mods` directory.
+
+> [!NOTE]
+> The startup examples posted in the project README already have this directory volume mapped accordingly. If you've strayed from the suggested setup, [please refer back to it to get started](../README.md).
+
+1. Create a folder called `mods` that lives alongside where you would normally start the server process.
+2. Add your mod files as a sub-directory of `mods`. For example if the mod name is `decay`, you'd place it in `mods/decay`.
+3. Define the `GAME` environment variable for your mod name. The dedicated server client will use this to ensure that it starts a server for the correct mod, which corresponds with the directory name that was just created.
+
+```bash
+export GAME=decay
+```
+
+4. Start the image as you normally would, either with `docker run` or `docker compose up`. Most Half-Life mods require specific startup arguments. For more details, refer to the [Valve Developer Wiki](https://developer.valvesoftware.com/wiki/Half-Life_Dedicated_Server) and the instructions for the mod you're trying to run.
+
+> [!TIP]
+> When using a pre-built image, you'll likely want to use the `valve` image (`jives/hlds:valve`), but this ultimately depends on the mod.
diff --git a/docs/SERVER_CONFIGS_AND_PLUGINS.md b/docs/SERVER_CONFIGS_AND_PLUGINS.md
new file mode 100644
index 0000000..f617971
--- /dev/null
+++ b/docs/SERVER_CONFIGS_AND_PLUGINS.md
@@ -0,0 +1,17 @@
+# Configs and Plugins
+
+If you wish to add server configurations, such as add-ons, plugins, map rotations, etc, you can add them to the `config` directory.
+
+> [!NOTE]
+> The startup examples posted in the project README already have this directory volume mapped accordingly. If you've strayed from the suggested setup, [please refer back to it to get started](../README.md).
+
+Any configuration files will be copied into the container on start from the `config` directory and placed within the folder for the specified game. For example, if you set the game as `cstrike`, the contents of the `config` folder will be placed within the `cstrike` directory on the server.
+
+> [!TIP]
+> As an example if you have `config/mapcycle.txt`, on the server that will be placed in the `hlds/cstrike/mapcycle.txt` directory which is where the Half-Life Dedicated Server client expects these types of files to be placed. You can use this to install server plugins such as AMX Mod, Meta Mod, etc, as the directory can handle nested folders too, for example these can be placed in `config/addons/amxmodx` etc.
+
+1. Create a folder called `config` that lives alongside where you would typically start the server process.
+2. Add your config files to the directory.
+3. Start the image as you normally would, either with `docker run` or `docker compose up`.
+
+For a list of all the available server configuration types, [refer to the Valve Developer Wiki](https://developer.valvesoftware.com/wiki/Main_Page).