mirror of
https://github.com/nestriness/nestri.git
synced 2025-12-11 08:15:38 +02:00
✨ feat: Add server Dockerfile (#2)
## Description **What(what issue does this code solve/what feature does it add):** We are adding the `Dockerfile` with all the scripts and programs to run our games in. **How(how does it solve it):** 1. Add `serverDockerfile` which contains all the docker code. 2. Add `.scripts` folder where we will store all the scripts; for example in our case, where proton installation script will reside. ## Required Checklist: - [ ] I have added any necessary documentation and comments in my code (where appropriate) - [ ] I have added tests to make sure my code runs in all contexts ## Further comments
This commit is contained in:
93
.github/workflows/server.yml
vendored
Normal file
93
.github/workflows/server.yml
vendored
Normal file
@@ -0,0 +1,93 @@
|
||||
#Tabs not spaces, you moron :)
|
||||
|
||||
name: CI for netris:server
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- "server.Dockerfile"
|
||||
- ".github/workflows/server.yml"
|
||||
schedule:
|
||||
- cron: 0 0 * * * # At the end of everyday
|
||||
push:
|
||||
branches: [main]
|
||||
paths:
|
||||
- "server.Dockerfile"
|
||||
- ".github/workflows/server.yml"
|
||||
tags:
|
||||
- v*.*.*
|
||||
release:
|
||||
types: [created]
|
||||
|
||||
env:
|
||||
REGISTRY: ghcr.io
|
||||
IMAGE_NAME: wanjohiryan/netris
|
||||
BASE_TAG_PREFIX: server
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref == 'refs/heads/main' && github.run_id || github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
build-docker-pr:
|
||||
name: Build image on pr
|
||||
runs-on: ubuntu-latest
|
||||
if: ${{ github.event_name == 'pull_request' }}
|
||||
steps:
|
||||
-
|
||||
name: Checkout repo
|
||||
uses: actions/checkout@v4
|
||||
-
|
||||
name: Setup Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
-
|
||||
name: Build Docker image
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
file: server.Dockerfile
|
||||
context: ./
|
||||
push: false
|
||||
load: true
|
||||
tags: netris:server
|
||||
|
||||
build-docker-main:
|
||||
name: Build image on merge to main
|
||||
if: ${{github.ref == 'refs/heads/main'}}
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
steps:
|
||||
-
|
||||
name: Checkout repo
|
||||
uses: actions/checkout@v4
|
||||
-
|
||||
name: Log into registry ${{ env.REGISTRY }}
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ${{ env.REGISTRY }}
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
-
|
||||
name: Extract Container metadata
|
||||
id: meta
|
||||
uses: docker/metadata-action@v5
|
||||
with:
|
||||
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}/${{ env.BASE_TAG_PREFIX }}
|
||||
#
|
||||
#tag on release, and a nightly build for 'dev'
|
||||
tags: |
|
||||
type=raw,value=nightly,enable={{is_default_branch}}
|
||||
type=ref,event=tag
|
||||
type=semver,pattern={{version}}
|
||||
type=semver,pattern={{major}}.{{minor}}
|
||||
type=semver,pattern={{major}}
|
||||
-
|
||||
name: Build Docker image
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
file: server.Dockerfile
|
||||
context: ./
|
||||
push: true
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
358
.scripts/proton
Normal file
358
.scripts/proton
Normal file
@@ -0,0 +1,358 @@
|
||||
#!/bin/bash
|
||||
# Version 0.0.1
|
||||
|
||||
#Big thanks to github/@noabody
|
||||
#For his wmstart script https://github.com/noabody/unibuild/blob/master/data/wstart
|
||||
|
||||
#Dependencies: git, jq, curl, vulkan & wget
|
||||
|
||||
# top level linux steam dir
|
||||
pntop="$HOME/.steam"
|
||||
# steamapps subdir
|
||||
pnapp="$pntop/steam/steamapps"
|
||||
# proton subdir normally under top/app
|
||||
pnbin="$pnapp/common"
|
||||
# proton prefix subdir normally under top/app
|
||||
pnpfx="$pnapp/compatdata"
|
||||
# proton ge
|
||||
pnpge="$pntop/root/compatibilitytools.d"
|
||||
# Program Files standard subdir
|
||||
progs="drive_c/Program Files"
|
||||
# windows steam client subdir under progs
|
||||
stcmn="Steam/steamapps/common"
|
||||
# temp folder
|
||||
temp="$HOME/Downloads"
|
||||
|
||||
# store cmdline args minus first option
|
||||
clprm=("${@:2}")
|
||||
|
||||
xcmd=()
|
||||
i_mnus=()
|
||||
myprnt=()
|
||||
i_syms=()
|
||||
# scalable built-in programs menu
|
||||
pmenu=("Command Prompt/wineconsole.exe" "Control Panel/control.exe" "Registry Editor/regedit.exe" "Task Manager/taskmgr.exe" "Windows Explorer/explorer.exe" "Wine Configuration/winecfg.exe")
|
||||
# prevent shell inheritance of env vars we use
|
||||
unset WINEARCH WINEDLLPATH WINEPREFIX STEAM_COMPAT_CLIENT_INSTALL_PATH STEAM_COMPAT_DATA_PATH
|
||||
|
||||
xarg="$1"
|
||||
|
||||
xnint() {
|
||||
xnbin="$pnbin"
|
||||
xnpfx="$pnpfx"
|
||||
dpth=(4 3)
|
||||
}
|
||||
|
||||
xpge() {
|
||||
test -d "$pnpge" || mkdir -p "$pnpge"
|
||||
test -d "$pnbin" || mkdir -p "$pnbin"
|
||||
|
||||
if [[ ! -d "$(dirname "$pnpge")" ]]; then
|
||||
echo -e "Could not create folder 'compatibilitytools.d/protonge' in:\n $(dirname "$pnpge")\n because that path does not exist.\nVerify script variable 'pnpge'"
|
||||
elif [[ ! -d "$pnbin" ]]; then
|
||||
echo -e "Could not create sym-link 'protonge' in:\n $pnbin\n because that path does not exist.\nVerify script variable 'pnbin'"
|
||||
else
|
||||
gedl="$(curl -sL https://api.github.com/repos/GloriousEggroll/proton-ge-custom/releases/latest | jq -r ".tag_name")"
|
||||
# gedl="$(gh release list -R GloriousEggroll/proton-ge-custom -L 1 | grep -Pio '^ge[^ ]+')"
|
||||
gever="$(echo "$gedl" | grep -Pio '(?<=ge-proton).*')"
|
||||
if [[ -f "$pnpge/protonge/version" ]]; then
|
||||
if [[ -z "$(grep -Pio "$gever" "$pnpge/protonge/version")" ]]; then
|
||||
echo -e "Available Proton GE $gever differs from installed, updating...\n"
|
||||
chse=y
|
||||
else
|
||||
echo -e "Available Proton GE $gever matches installed, nothing to do.\n"
|
||||
fi
|
||||
else
|
||||
echo -e "Proton GE not found, installing...\n"
|
||||
chse=y
|
||||
fi
|
||||
fi
|
||||
if [[ -n "$chse" ]]; then
|
||||
wget "$(curl -s https://api.github.com/repos/GloriousEggroll/proton-ge-custom/releases/latest | grep browser_download_url | cut -d\" -f4 | grep .tar.gz)" -P "$temp"/
|
||||
|
||||
rm -rf "$pnpge/protonge"
|
||||
tar -xf "$temp/$gedl".tar.gz -C "$pnpge/"
|
||||
mv "$pnpge"/*roton* "$pnpge/protonge"
|
||||
rm -f "$temp/$gedl".tar.gz
|
||||
grep -Piq "$gever" "$pnpge/protonge/version" || perl -pi -e "s|(?<=ge-proton).*|$gever|gi" "$pnpge/protonge/version"
|
||||
test -h "$pnbin/protonge" || ln -sf "$pnpge/protonge" "$pnbin"
|
||||
fi
|
||||
}
|
||||
|
||||
xn64() {
|
||||
xstrt="wine64"
|
||||
xnldl="$xnbin/lib64:$xnbin/lib"
|
||||
xndll="$xnbin/lib64/wine:$xnbin/lib/wine"
|
||||
}
|
||||
|
||||
xn32() {
|
||||
xstrt="wine"
|
||||
xnldl="$xnbin/lib"
|
||||
xndll="$xnbin/lib/wine"
|
||||
}
|
||||
|
||||
w_menu() {
|
||||
PS3="Please enter your choice: "
|
||||
select answer in "${i_mnus[@]}"; do
|
||||
for item in "${i_mnus[@]}"; do
|
||||
if [[ $item == "$answer" ]]; then
|
||||
break 2
|
||||
fi
|
||||
done
|
||||
done
|
||||
# repeating menu requires valid selection from array
|
||||
if [[ "$answer" = "quit" ]]; then
|
||||
# pop quit from end of array for menu option
|
||||
exit
|
||||
else
|
||||
xmrtn="$answer"
|
||||
fi
|
||||
unset i_mnus
|
||||
clear
|
||||
}
|
||||
|
||||
xnexe() {
|
||||
# menu installed wine/proton or exit
|
||||
readarray -t i_mnus < <(
|
||||
find -L "$xnbin" -maxdepth "${dpth[0]}" -type f -iname 'wine' ! \( -ipath '*/sbin*' \) 2>/dev/null | perl -pe "s|\Q$xnbin\E/(.*)[/]*bin/wine|\1| ; s|/$||" | sort
|
||||
echo "quit"
|
||||
)
|
||||
if [[ ${#i_mnus[@]} -gt 2 ]]; then
|
||||
clear
|
||||
w_menu
|
||||
xnbin="$(realpath "$xnbin/$xmrtn")"
|
||||
unset xmrtn
|
||||
elif [[ ${#i_mnus[@]} -eq 2 ]]; then
|
||||
xnbin="$(realpath "$xnbin/${i_mnus[0]}")"
|
||||
else
|
||||
echo "No installed Wine/Proton found."
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
xnenv() {
|
||||
# core env vars allow proper targetting of wine/proton
|
||||
xpath="$xnbin/bin:$PATH"
|
||||
xcmd=(env PATH="$xpath" WINEDLLPATH="$xndll" LD_LIBRARY_PATH="$xnldl" WINEPREFIX="$xnpfx")
|
||||
|
||||
xcmd+=(STEAM_COMPAT_DATA_PATH="${xnpfx///pfx}" STEAM_COMPAT_CLIENT_INSTALL_PATH="$pntop")
|
||||
}
|
||||
|
||||
xlnch() {
|
||||
#command line launcher
|
||||
if [[ -z "$dbg" ]]; then
|
||||
("${xcmd[@]}" >/dev/null 2>&1 &)
|
||||
else
|
||||
if [[ "$dbg" = "1" ]]; then
|
||||
("${xcmd[@]}" &)
|
||||
elif [[ "$dbg" = "2" ]]; then
|
||||
(WINEDEBUG="warn+all" "${xcmd[@]}" &)
|
||||
fi
|
||||
fi
|
||||
# prepend cmd with dbg=1 to see command and default debug output
|
||||
# dbg=2 to see command and all debug output, dbg=? for command only
|
||||
}
|
||||
|
||||
xbld() {
|
||||
# cross-function custom prefix builder
|
||||
pnpfx="$pnpfx/${clprm[0]}"
|
||||
xnint
|
||||
|
||||
if [[ -z "${clprm[0]}" ]]; then
|
||||
echo -e "\n Proton prefix name required, use an appid from Steam: (e.g. 0, 730 ) \n"
|
||||
elif [[ -d "$xnpfx" ]]; then
|
||||
echo -e "\n Proton Prefix exists: $xnpfx \n"
|
||||
else
|
||||
xnexe
|
||||
echo "Creating Proton Prefix: ${clprm[0]}"
|
||||
|
||||
xnenv
|
||||
mkdir -p "$xnpfx"
|
||||
xcmd+=(STEAM_COMPAT_DATA_PATH="$xnpfx" "${xnbin%/*}/proton" "run")
|
||||
|
||||
xlnch
|
||||
fi
|
||||
}
|
||||
|
||||
xnpre() {
|
||||
if [[ -d "$xnpfx/$progs (x86)" ]]; then
|
||||
xn64
|
||||
else
|
||||
xn32
|
||||
fi
|
||||
}
|
||||
|
||||
xndef() {
|
||||
# create default prefix cross-function
|
||||
if [[ -z "$prfx" ]]; then
|
||||
echo "INFO: to use a specific prefix, append prfx='your prefix' to this command"
|
||||
if [[ ! -d "$xnpfx/0" ]]; then
|
||||
# always create default 0 prefix
|
||||
xnpfx="$xnpfx/0"
|
||||
echo "Creating default prefix: $xnpfx"
|
||||
mkdir -p "$xnpfx"
|
||||
STEAM_COMPAT_DATA_PATH="$xnpfx" "${xnbin%/*}/proton" run >/dev/null 2>&1 &
|
||||
xnpfx="$xnpfx/pfx"
|
||||
else
|
||||
xnpfx="$xnpfx/0"
|
||||
xnpfx="$xnpfx/pfx"
|
||||
fi
|
||||
else
|
||||
xnpfx="$xnpfx/$prfx"
|
||||
if [[ ! -d "$xnpfx" ]]; then
|
||||
echo "Creating default prefix: $xnpfx"
|
||||
mkdir -p "$xnpfx"
|
||||
STEAM_COMPAT_DATA_PATH="$xnpfx" "${xnbin%/*}/proton" run >/dev/null 2>&1 &
|
||||
xnpfx="$xnpfx/pfx"
|
||||
else
|
||||
xnpfx="$xnpfx/pfx"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
fewoth() {
|
||||
# filtered list of variable type in standard paths
|
||||
readarray -t i_mnus < <(
|
||||
env pedir="$pedir" find "$pedir" -maxdepth 7 -type f -regextype posix-extended ! \( -ipath '*cache*' -o -ipath '*/microsoft*' -o -ipath '*/windows*' -o -ipath '*/temp*' \) ! \( -iregex '.*(capture|clokspl|helper|iexplore|install|internal|kernel|[^ ]launcher|legacypm|overlay|proxy|redist|renderer|(crash|error)reporter|serv(er|ice)|setup|streaming|tutorial|unins|update).*' \) -iname "$xflt" 2>/dev/null | perl -pe "s|\Q$pedir\E/(.*)|\1|" | sort
|
||||
echo "quit"
|
||||
)
|
||||
}
|
||||
|
||||
fewexe() {
|
||||
# filtered list of exe in standard paths
|
||||
readarray -t i_mnus < <(
|
||||
env pedir="$pedir" find "$pedir" -maxdepth 7 -type f -regextype posix-extended ! \( -ipath '*cache*' -o -ipath '*/microsoft*' -o -ipath '*/windows*' -o -ipath '*/temp*' \) ! \( -iregex '.*(capture|clokspl|helper|iexplore|install|internal|kernel|[^ ]launcher|legacypm|overlay|proxy|redist|renderer|(crash|error)reporter|serv(er|ice)|setup|streaming|tutorial|unins|update).*' \) -iname '*.exe' -exec sh -c '(readpe -h optional "$1" 2>/dev/null | grep -Piq '0x2.*gui') && (wrestool "$1" 2>/dev/null | grep -Piq 'type=icon') && echo "$1" 2>/dev/null | perl -pe "s|\Q$pedir\E/(.*)|\1|"' -- {} \; 2>/dev/null | sort
|
||||
echo "quit"
|
||||
)
|
||||
# valid exe will have gui and icon
|
||||
}
|
||||
|
||||
alloth() {
|
||||
# unfiltered list of variable type in specified path
|
||||
readarray -t i_mnus < <(
|
||||
find "$pedir" -maxdepth 7 -type f -regextype posix-extended -iname "$xflt" 2>/dev/null | perl -pe "s|\Q$pedir\E/(.*)|\1|" | sort
|
||||
echo "quit"
|
||||
)
|
||||
}
|
||||
|
||||
allexe() {
|
||||
# unfiltered list of exe in specified path
|
||||
if [[ -n "$(stat --file-system --format=%T "$(stat --format=%m "$pedir" 2>/dev/null)" 2>/dev/null | grep -Pio 'fuse')" ]]; then
|
||||
readarray -t i_mnus < <(
|
||||
find "$pedir" -maxdepth 7 -type f -regextype posix-extended -iname '*.exe' 2>/dev/null | perl -pe "s|\Q$pedir\E/(.*)|\1|" | sort
|
||||
echo "quit"
|
||||
)
|
||||
# skip exe validity tests if file is on network drive
|
||||
else
|
||||
readarray -t i_mnus < <(
|
||||
env pedir="$pedir" find "$pedir" -maxdepth 7 -type f -regextype posix-extended -iname '*.exe' -exec sh -c '(readpe -h optional "$1" 2>/dev/null | grep -Piq '0x2.*gui') && (wrestool "$1" 2>/dev/null | grep -Piq 'type=icon') && echo "$1" 2>/dev/null | perl -pe "s|\Q$pedir\E/(.*)|\1|"' -- {} \; 2>/dev/null | sort
|
||||
echo "quit"
|
||||
)
|
||||
# perform exe validity tests if file is on local drive
|
||||
fi
|
||||
}
|
||||
|
||||
xpmn() {
|
||||
# use specified exe, menu specified folder, or menu system
|
||||
if [[ -f "${clprm[0]}" ]]; then
|
||||
# parse 1st cmdline arg, queue if valid file
|
||||
pedir="$(realpath "${clprm[0]}")"
|
||||
xmrtn="$(basename "$pedir")"
|
||||
pedir="$(dirname "$pedir")"
|
||||
else
|
||||
if [[ -d "${clprm[0]}" ]]; then
|
||||
# parse 1st cmdline arg, use as path if valid
|
||||
pedir="$(realpath "${clprm[0]}")"
|
||||
test -z "$xflt" && allexe || alloth
|
||||
else
|
||||
# if no cmdline path, use prefix drive_c
|
||||
pedir="$xnpfx/drive_c"
|
||||
test -z "$xflt" && fewexe || fewoth
|
||||
fi
|
||||
# create menu, from path, of file
|
||||
test ${#i_mnus[@]} -gt 1 && w_menu
|
||||
fi
|
||||
}
|
||||
|
||||
xnldr() {
|
||||
# loader default to proton as applicable, otherwise wine
|
||||
if [[ -z "$wn" ]]; then
|
||||
xcmd+=("${xnbin%/*}/proton" "run")
|
||||
else
|
||||
if [[ "$wn" = "true" ]]; then
|
||||
xcmd+=("$xstrt")
|
||||
else
|
||||
echo "unrecognised run option"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
xlyt() {
|
||||
# prepare layout for launch
|
||||
# 64-bit prefix, 32-bit prefix header, reset env to 32
|
||||
if [[ -n "$(readpe -h optional "$pedir/$xmrtn" 2>/dev/null | grep -Pi 'magic number.*0x10b')" && -d "$xnpfx/$progs (x86)" ]]; then
|
||||
xn32
|
||||
xnenv
|
||||
fi
|
||||
xnldr
|
||||
# if 1st arg is file/folder, skip it and run selection + remaining args
|
||||
if [[ -e "${clprm[0]}" ]]; then
|
||||
xcmd+=("$pedir/$xmrtn" "${clprm[@]:1}")
|
||||
else
|
||||
xcmd+=("$pedir/$xmrtn" "${clprm[@]}")
|
||||
fi
|
||||
}
|
||||
|
||||
xnset() {
|
||||
# set cross-fuction
|
||||
xnint
|
||||
# proton menu
|
||||
xnexe
|
||||
# create default prefix as required
|
||||
xndef
|
||||
# proton prefix
|
||||
xnpre
|
||||
# proton env vars
|
||||
xnenv
|
||||
}
|
||||
|
||||
usage() {
|
||||
echo -e "\n$(basename $0): ERROR - $*" 1>&2
|
||||
echo -e "\nusage: $(basename $0)\n [-i,--install] [-b,--build] [-r,--run] \n \n (install) install proton-ge \n (build) build a custom proton prefix \n (run) run an .exe program \n \n" 1>&2
|
||||
}
|
||||
|
||||
if [[ $# -lt 1 ]]; then
|
||||
usage "one option required!"
|
||||
else
|
||||
case $xarg in
|
||||
-i | --install)
|
||||
# proton ge
|
||||
xpge
|
||||
;;
|
||||
-p | --prefix)
|
||||
# prefix builder
|
||||
xbld
|
||||
;;
|
||||
-r | --run)
|
||||
# second arg should be the prefix to use.
|
||||
# run program - 1st arg valid file to run, folder to menu,
|
||||
# neither (sys menu), 2nd arg... passed to exe
|
||||
xnset
|
||||
xpmn
|
||||
if [[ -n "$xmrtn" ]]; then
|
||||
xlyt
|
||||
# change to exe dir before run
|
||||
cd "$(dirname "$pedir/$xmrtn")"
|
||||
xlnch
|
||||
fi
|
||||
;;
|
||||
-* | \* | *)
|
||||
# do_usage
|
||||
usage "invalid option $1"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
|
||||
#FIXME: it won't run anything AAAArgh!
|
||||
36
server.Dockerfile
Normal file
36
server.Dockerfile
Normal file
@@ -0,0 +1,36 @@
|
||||
#This contains all the necessary libs for the server to work.
|
||||
#NOTE: KEEP THIS IMAGE AS LEAN AS POSSIBLE.
|
||||
|
||||
FROM ubuntu:latest
|
||||
|
||||
#FIXME: install Vulkan drivers (should be done in the .scripts/gpu)
|
||||
#FIXME: install https://git.dec05eba.com/gpu-screen-recorder (should be done in the .scripts/stream)
|
||||
|
||||
ENV DEBIAN_FRONTEND=noninteractive \
|
||||
TIMEZONE=Africa/Nairobi
|
||||
|
||||
#Install base libs
|
||||
RUN apt update && \
|
||||
dpkg --add-architecture i386 && \
|
||||
apt install -y \
|
||||
software-properties-common \
|
||||
curl \
|
||||
wget \
|
||||
git \
|
||||
jq \
|
||||
locales \
|
||||
&& rm -rf /var/lib/apt/lists/* \
|
||||
&& locale-gen en_US.UTF-8
|
||||
|
||||
#Set language variables
|
||||
ENV LANG=en_US.UTF-8 \
|
||||
LANGUAGE=en_US:en \
|
||||
LC_ALL=en_US.UTF-8
|
||||
|
||||
COPY .scripts/ /usr/bin/netris/
|
||||
|
||||
RUN ls -la /usr/bin/netris \
|
||||
&& chmod +x /usr/bin/netris/proton
|
||||
|
||||
#Install proton
|
||||
RUN /usr/bin/netris/proton -i
|
||||
Reference in New Issue
Block a user