diff --git a/.env b/.env new file mode 100644 index 0000000..d00050e --- /dev/null +++ b/.env @@ -0,0 +1,18 @@ +STEAMAPPID=232330 +STEAMAPP=css +SRCDS_TOKEN=C02633B3395EA6BEF7D8DFBA440ABB7F +SRCDS_RCONPW="changeme" +SRCDS_PW="changeme" +SRCDS_PORT=27015 +SRCDS_TV_PORT=27020 +SRCDS_IP="0.0.0.0" +SRCDS_FPSMAX=300 +SRCDS_TICKRATE=66 +SRCDS_MAXPLAYERS=32 +SRCDS_REGION=3 +SRCDS_STARTMAP="ctf_2fort" +SRCDS_HOSTNAME="megastructure surf" +SRCDS_WORKSHOP_AUTHKEY="" +SRCDS_CFG="server.cfg" +SRCDS_MAPCYCLE="mapcycle_default.txt" +SRCDS_SECURED=0 diff --git a/.gitignore b/.gitignore index f625bb6..c04b99b 100755 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,8 @@ *.sql.gz *.tar.gz +data/ + surf.sublime-workspace diff --git a/Justfile b/Justfile new file mode 100644 index 0000000..0e9941f --- /dev/null +++ b/Justfile @@ -0,0 +1,11 @@ +build-css: + docker build -f css/css.dockerfile css/ -t megastructure/css + +up: + docker compose -f surf.yaml up + +down: + docker compose -f surf.yaml down -v --remove-orphans + +srcds-sh: + docker compose -f surf.yaml run -it srcds bash \ No newline at end of file diff --git a/css/css.dockerfile b/css/css.dockerfile new file mode 100644 index 0000000..1a3e712 --- /dev/null +++ b/css/css.dockerfile @@ -0,0 +1,81 @@ +########################################################### +# Dockerfile that builds a CSS Gameserver +########################################################### +FROM cm2network/steamcmd:root AS build_stage + +LABEL maintainer="ntr@megastructure.games" + +ENV STEAMAPPID 232330 +ENV STEAMAPP css +ENV STEAMAPPDIR "${HOMEDIR}/${STEAMAPP}-dedicated" + +COPY "etc/entry_x64.sh" "${HOMEDIR}/entry_x64.sh" +COPY "etc/cfg" "${STEAMAPPDIR}/${STEAMAPP}/cfg/" + +RUN set -x \ + # Install, update & upgrade packages + && apt-get update \ + && apt-get install -y --no-install-recommends --no-install-suggests \ + wget=1.21.3-1+deb12u1 \ + ca-certificates=20230311 \ + zlib1g=1:1.2.13.dfsg-1 \ + libncurses5=6.4-4 \ + libbz2-1.0=1.0.8-5+b1 \ + libtinfo5=6.4-4 \ + libcurl3-gnutls=7.88.1-10+deb12u5 \ + && mkdir -p "${STEAMAPPDIR}" \ + # Create autoupdate config + && { \ + echo '@ShutdownOnFailedCommand 1'; \ + echo '@NoPromptForPassword 1'; \ + echo 'force_install_dir '"${STEAMAPPDIR}"''; \ + echo 'login anonymous'; \ + echo 'app_update '"${STEAMAPPID}"''; \ + echo 'quit'; \ + } > "${HOMEDIR}/${STEAMAPP}_update.txt" \ + && chmod +x "${HOMEDIR}/entry_x64.sh" \ + && chown -R "${USER}:${USER}" "${HOMEDIR}/entry_x64.sh" "${STEAMAPPDIR}" "${HOMEDIR}/${STEAMAPP}_update.txt" \ + # Clean up + && rm -rf /var/lib/apt/lists/* + +FROM build_stage AS bookworm-base + +ENV SRCDS_FPSMAX=300 \ + SRCDS_TICKRATE=66 \ + SRCDS_PORT=27015 \ + SRCDS_TV_PORT=27020 \ + SRCDS_NET_PUBLIC_ADDRESS="0" \ + SRCDS_IP="0" \ + SRCDS_MAXPLAYERS=16 \ + SRCDS_TOKEN=0 \ + SRCDS_RCONPW="changeme" \ + SRCDS_PW="changeme" \ + SRCDS_STARTMAP="de_dust2" \ + SRCDS_REGION=3 \ + SRCDS_HOSTNAME="New \"${STEAMAPP}\" Server" \ + SRCDS_WORKSHOP_START_MAP=0 \ + SRCDS_HOST_WORKSHOP_COLLECTION=0 \ + SRCDS_WORKSHOP_AUTHKEY="" \ + SRCDS_CFG="server.cfg" \ + SRCDS_MAPCYCLE="mapcycle.txt" \ + SRCDS_SECURED=1 + +# Switch to user +USER ${USER} + +WORKDIR ${HOMEDIR} + +CMD ["bash", "entry_x64.sh"] + +# Expose ports +EXPOSE 27015/tcp \ + 27015/udp \ + 27020/udp + +FROM bookworm-base AS bookworm-metamod + +ENV METAMOD_VERSION 1.12 + +FROM bookworm-metamod AS bookworm-sourcemod + +ENV SOURCEMOD_VERSION 1.12 \ No newline at end of file diff --git a/css/etc/cfg/mapcycle.txt b/css/etc/cfg/mapcycle.txt new file mode 100644 index 0000000..b7ac6aa --- /dev/null +++ b/css/etc/cfg/mapcycle.txt @@ -0,0 +1,26 @@ +// Default mapcycle file for Counter-Strike. +// +// DO NOT MODIFY THIS FILE! +// Instead, copy it to mapcycle.txt and modify that file. If no custom mapcycle.txt file is found, +// this file will be used as the default. +// +// Also, note that the "mapcyclefile" convar can be used to specify a particular mapcycle file. + +cs_italy +de_dust +de_aztec +de_cbble +cs_office +de_chateau +de_dust2 +de_piranesi +cs_havana +de_prodigy +cs_compound +de_train +de_tides +de_port +de_inferno +cs_assault +de_nuke +cs_militia \ No newline at end of file diff --git a/css/etc/cfg/mapcycle_default.txt b/css/etc/cfg/mapcycle_default.txt new file mode 100644 index 0000000..b7ac6aa --- /dev/null +++ b/css/etc/cfg/mapcycle_default.txt @@ -0,0 +1,26 @@ +// Default mapcycle file for Counter-Strike. +// +// DO NOT MODIFY THIS FILE! +// Instead, copy it to mapcycle.txt and modify that file. If no custom mapcycle.txt file is found, +// this file will be used as the default. +// +// Also, note that the "mapcyclefile" convar can be used to specify a particular mapcycle file. + +cs_italy +de_dust +de_aztec +de_cbble +cs_office +de_chateau +de_dust2 +de_piranesi +cs_havana +de_prodigy +cs_compound +de_train +de_tides +de_port +de_inferno +cs_assault +de_nuke +cs_militia \ No newline at end of file diff --git a/css/etc/cfg/server.cfg b/css/etc/cfg/server.cfg new file mode 100644 index 0000000..92f151e --- /dev/null +++ b/css/etc/cfg/server.cfg @@ -0,0 +1,195 @@ +// General Settings // + +// Hostname for server. +hostname "{{SERVER_HOSTNAME}}" + +// Overrides the max players reported to prospective clients +sv_visiblemaxplayers 24 + +// Maximum number of rounds to play before server changes maps +mp_maxrounds 5 + +// Set to lock per-frame time elapse +host_framerate 0 + +// Set the pause state of the server +setpause 0 + +// Control where the client gets content from +// 0 = anywhere, 1 = anywhere listed in white list, 2 = steam official content only +sv_pure 0 + +// Is the server pausable +sv_pausable 0 + +// Type of server 0=internet 1=lan +sv_lan 0 + +// Collect CPU usage stats +sv_stats 1 + + + +// Execute Banned Users // +exec banned_user.cfg +exec banned_ip.cfg +writeid +writeip + + + +// Contact & Region // + +// Contact email for server sysop +sv_contact test@example.com + +// The region of the world to report this server in. +// -1 is the world, 0 is USA east coast, 1 is USA west coast +// 2 south america, 3 europe, 4 asia, 5 australia, 6 middle east, 7 africa +sv_region -1 + + + +// Rcon Settings // + +// Password for rcon authentication (Remote CONtrol) +rcon_password changeme + +// Number of minutes to ban users who fail rcon authentication +sv_rcon_banpenalty 1440 + +// Max number of times a user can fail rcon authentication before being banned +sv_rcon_maxfailures 5 + + + +// Log Settings // + +// Enables logging to file, console, and udp < on | off >. +log on + +// Log server information to only one file. +sv_log_onefile 0 + +// Log server information in the log file. +sv_logfile 1 + +// Log server bans in the server logs. +sv_logbans 1 + +// Echo log information to the console. +sv_logecho 1 + + + +// Rate Settings // + +// Frame rate limiter +fps_max 600 + +// Min bandwidth rate allowed on server, 0 == unlimited +sv_minrate 0 + +// Max bandwidth rate allowed on server, 0 == unlimited +sv_maxrate 20000 + +// Minimum updates per second that the server will allow +sv_minupdaterate 66 + +// Maximum updates per second that the server will allow +sv_maxupdaterate 66 + + + +// Download Settings // + +// Allow clients to upload customizations files +sv_allowupload 1 + +// Allow clients to download files +sv_allowdownload 1 + +// Maximum allowed file size for uploading in MB +net_maxfilesize 15 + + + +// Team Balancing // + +// Enable team balancing +mp_autoteambalance 1 + +// Time after the teams become unbalanced to attempt to switch players. +mp_autoteambalance_delay 60 + +// Time after the teams become unbalanced to print a balance warning +mp_autoteambalance_warning_delay 30 + +// Teams are unbalanced when one team has this many more players than the other team. (0 disables check) +mp_teams_unbalance_limit 1 + + + +// Round and Game Times // + +// Enable timers to wait between rounds. WARNING: Setting this to 0 has been known to cause a bug with setup times lasting 5:20 (5 minutes 20 seconds) on some servers! +mp_enableroundwaittime 1 + +// Time after round win until round restarts +mp_bonusroundtime 8 + +// If non-zero, the current round will restart in the specified number of seconds +mp_restartround 0 + +// Enable sudden death +mp_stalemate_enable 1 + +// Timelimit (in seconds) of the stalemate round. +mp_stalemate_timelimit 300 + +// Game time per map in minutes +mp_timelimit 35 + + + +// Client CVars // + +// Restricts spectator modes for dead players +mp_forcecamera 0 + +// Toggles whether the server allows spectator mode or not +mp_allowspectators 1 + +// Toggles footstep sounds +mp_footsteps 1 + +// Toggles game cheats +sv_cheats 0 + +// After this many seconds without a message from a client, the client is dropped +sv_timeout 900 + +// Maximum time a player is allowed to be idle (in minutes), made this and sv_timeout equal same time? +mp_idlemaxtime 15 + +// Deals with idle players 1=send to spectator 2=kick +mp_idledealmethod 2 + +// Time (seconds) between decal sprays +decalfrequency 30 + + + +// Communications // + +// enable voice communications +sv_voiceenable 1 + +// Players can hear all other players, no team restrictions 0=off 1=on +sv_alltalk 0 + +// Amount of time players can chat after the game is over +mp_chattime 10 + +// Enable party mode +tf_birthday 0 \ No newline at end of file diff --git a/css/etc/entry_x64.sh b/css/etc/entry_x64.sh new file mode 100644 index 0000000..b9cf871 --- /dev/null +++ b/css/etc/entry_x64.sh @@ -0,0 +1,58 @@ +#!/bin/bash + +set -eux + +mkdir -p "${STEAMAPPDIR}" || true + +bash "${STEAMCMDDIR}/steamcmd.sh" +force_install_dir "${STEAMAPPDIR}" \ + +login anonymous \ + +app_update "${STEAMAPPID}" \ + +quit + +# Are we in a metamod container and is the metamod folder missing? +if [ ! -z "$METAMOD_VERSION" ] && [ ! -d "${STEAMAPPDIR}/${STEAMAPP}/addons/metamod" ]; then + LATESTMM=$(wget -qO- https://mms.alliedmods.net/mmsdrop/"${METAMOD_VERSION}"/mmsource-latest-linux) + wget -qO- https://mms.alliedmods.net/mmsdrop/"${METAMOD_VERSION}"/"${LATESTMM}" | tar xvzf - -C "${STEAMAPPDIR}/${STEAMAPP}" +fi + +# Are we in a sourcemod container and is the sourcemod folder missing? +if [ ! -z "$SOURCEMOD_VERSION" ] && [ ! -d "${STEAMAPPDIR}/${STEAMAPP}/addons/sourcemod" ]; then + LATESTSM=$(wget -qO- https://sm.alliedmods.net/smdrop/"${SOURCEMOD_VERSION}"/sourcemod-latest-linux) + wget -qO- https://sm.alliedmods.net/smdrop/"${SOURCEMOD_VERSION}"/"${LATESTSM}" | tar xvzf - -C "${STEAMAPPDIR}/${STEAMAPP}" +fi + +# Is the config missing? +if [ -f "${STEAMAPPDIR}/${STEAMAPP}/cfg/server.cfg" ]; then + # Change hostname on first launch (you can comment this out if it has done its purpose) + sed -i -e 's/{{SERVER_HOSTNAME}}/'"${SRCDS_HOSTNAME}"'/g' "${STEAMAPPDIR}/${STEAMAPP}/cfg/server.cfg" +fi + +# Believe it or not, if you don't do this srcds_run shits itself +cd "${STEAMAPPDIR}" + +SERVER_SECURITY_FLAG=""; + +if [ "$SRCDS_SECURED" -eq 0 ]; then + SERVER_SECURITY_FLAG="-insecure"; +fi + +bash "${STEAMAPPDIR}/srcds_run_64" -game "${STEAMAPP}" -console -autoupdate \ + -steam_dir "${STEAMCMDDIR}" \ + -steamcmd_script "${HOMEDIR}/${STEAMAPP}_update.txt" \ + -usercon \ + +fps_max "${SRCDS_FPSMAX}" \ + -tickrate "${SRCDS_TICKRATE}" \ + -port "${SRCDS_PORT}" \ + +tv_port "${SRCDS_TV_PORT}" \ + +clientport "${SRCDS_CLIENT_PORT}" \ + +maxplayers "${SRCDS_MAXPLAYERS}" \ + +map "${SRCDS_STARTMAP}" \ + +sv_setsteamaccount "${SRCDS_TOKEN}" \ + +rcon_password "${SRCDS_RCONPW}" \ + +sv_password "${SRCDS_PW}" \ + +sv_region "${SRCDS_REGION}" \ + -ip "${SRCDS_IP}" \ + -authkey "${SRCDS_WORKSHOP_AUTHKEY}" \ + +servercfgfile "${SRCDS_CFG}" \ + +mapcyclefile "${SRCDS_MAPCYCLE}" \ + ${SERVER_SECURITY_FLAG} \ No newline at end of file diff --git a/surf.yaml b/surf.yaml new file mode 100644 index 0000000..8e350cf --- /dev/null +++ b/surf.yaml @@ -0,0 +1,8 @@ +services: + srcds: + image: megastructure/css:latest + volumes: + - ./css/etc/entry_x64.sh:/home/steam/entry_x64.sh + - ./css/etc/cfg:/home/steam/css-dedicated/css/cfg + - ./data/css-dir:/home/steam/css-dedicated +