commit 3b1a15dcc6ecb93a763e679b9a7504c2ee358c3b Author: Refosel Date: Tue Jun 16 00:07:02 2026 +0300 init: yolks for GMod 64-bit and Stalwart Mail Server diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..d59d11e --- /dev/null +++ b/.dockerignore @@ -0,0 +1,7 @@ +.git +.github +.dockerignore +.gitignore +*.md +LICENSE +eggs/ diff --git a/.github/workflows/build-gmod.yml b/.github/workflows/build-gmod.yml new file mode 100644 index 0000000..5178373 --- /dev/null +++ b/.github/workflows/build-gmod.yml @@ -0,0 +1,56 @@ +name: Build GMod Yolk + +on: + push: + branches: [main] + paths: + - 'games/gmod/**' + workflow_dispatch: + +env: + REGISTRY: gitea.refoseltw.ru + IMAGE_NAME: RefoselTeamWork/yolks + +jobs: + build: + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Set up QEMU + uses: docker/setup-qemu-action@v3 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Login to Gitea Container Registry + uses: docker/login-action@v3 + with: + registry: ${{ env.REGISTRY }} + username: ${{ secrets.GITEA_USERNAME }} + password: ${{ secrets.GITEA_TOKEN }} + + - name: Extract metadata + id: meta + uses: docker/metadata-action@v5 + with: + images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} + tags: | + type=raw,value=latest + type=sha,prefix= + + - name: Build and push + uses: docker/build-push-action@v5 + with: + context: ./games/gmod + platforms: linux/amd64 + push: true + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + cache-from: type=gha + cache-to: type=gha,mode=max diff --git a/.github/workflows/build-stalwart.yml b/.github/workflows/build-stalwart.yml new file mode 100644 index 0000000..5b496bd --- /dev/null +++ b/.github/workflows/build-stalwart.yml @@ -0,0 +1,57 @@ +name: Build Stalwart Mail Yolk + +on: + push: + branches: [main] + paths: + - 'apps/stalwart/**' + workflow_dispatch: + +env: + REGISTRY: gitea.refoseltw.ru + IMAGE_NAME: RefoselTeamWork/yolks + +jobs: + build: + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Set up QEMU + uses: docker/setup-qemu-action@v3 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Login to Gitea Container Registry + uses: docker/login-action@v3 + with: + registry: ${{ env.REGISTRY }} + username: ${{ secrets.GITEA_USERNAME }} + password: ${{ secrets.GITEA_TOKEN }} + + - name: Extract metadata + id: meta + uses: docker/metadata-action@v5 + with: + images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} + tags: | + type=raw,value=stalwart + type=raw,value=stalwart-latest + type=sha,prefix=stalwart- + + - name: Build and push + uses: docker/build-push-action@v5 + with: + context: ./apps/stalwart + platforms: linux/amd64 + push: true + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + cache-from: type=gha + cache-to: type=gha,mode=max diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..eca0078 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +*.log +*.tmp +.DS_Store +Thumbs.db diff --git a/apps/stalwart/Dockerfile b/apps/stalwart/Dockerfile new file mode 100644 index 0000000..1a63628 --- /dev/null +++ b/apps/stalwart/Dockerfile @@ -0,0 +1,50 @@ +FROM debian:bookworm-slim + +LABEL author="RefoselTeam" maintainer="admin@refoseltw.ru" + +LABEL org.opencontainers.image.source="https://gitea.refoseltw.ru/RefoselTeamWork/yolks" +LABEL org.opencontainers.image.licenses=MIT + +ENV DEBIAN_FRONTEND=noninteractive + +# Install dependencies +RUN apt update \ + && apt upgrade -y \ + && apt install -y \ + curl \ + gnupg \ + ca-certificates \ + tini \ + tzdata \ + unzip \ + git \ + && apt clean \ + && rm -rf /var/lib/apt/lists/* + +# Install Stalwart Mail Server +RUN curl -sSL https://stalw.art/install.sh | bash + +# Create directories +RUN mkdir -p /home/container/stalwart-mail \ + && mkdir -p /home/container/stalwart-mail/data \ + && mkdir -p /home/container/stalwart-mail/certs \ + && mkdir -p /home/container/stalwart-mail/logs + +# Setup user +RUN useradd -m -d /home/container -s /bin/bash container \ + && chown -R container:container /home/container + +USER container +ENV USER=container HOME=/home/container +WORKDIR /home/container + +EXPOSE 8080 465 587 993 995 4190 + +STOPSIGNAL SIGINT + +COPY --chown=container:container ./entrypoint.sh /entrypoint.sh +COPY --chown=container:container ./config.toml /entrypoint-config.toml +RUN chmod +x /entrypoint.sh + +ENTRYPOINT ["/usr/bin/tini", "-g", "--"] +CMD ["/entrypoint.sh"] diff --git a/apps/stalwart/config.toml b/apps/stalwart/config.toml new file mode 100644 index 0000000..6fb418a --- /dev/null +++ b/apps/stalwart/config.toml @@ -0,0 +1,260 @@ +[storage] +data = "{{STORAGE_DATA}}" +logs = "{{STORAGE_LOGS}}" +queue = "{{STORAGE_DATA}}/queue" +blobs = "{{STORAGE_DATA}}/blobs" + +[lookup] +default = "internal" + +[lookup.internal] +hostname = "{{MAIL_HOSTNAME}}" +domain = "{{MAIL_DOMAIN}}" + +[smtp] +hostname = "{{MAIL_HOSTNAME}}" +bind = ["0.0.0.0:{{SMTP_PORT}}", "[::]:{{SMTP_PORT}}"] +concurrency.remote = 10 +max-message-size = 52428800 + +[smtp.auth] +directory = "internal" + +[smtp.session] +ehlo-required = true +max-recipients = 100 + +[imap] +bind = ["0.0.0.0:{{IMAP_PORT}}", "[::]:{{IMAP_PORT}}"] +max-connections = 50 + +[jmap] +bind = ["0.0.0.0:8081", "[::]:8081"] + +[http] +bind = ["0.0.0.0:{{HTTP_PORT}}", "[::]:{{HTTP_PORT}}"] +url = "http://{{MAIL_HOSTNAME}}:{{HTTP_PORT}}" + +[http.auth] +directory = "internal" + +[manager] +enable = true + +[metrics] +enable = true + +[submission] +bind = ["0.0.0.0:{{SUBMISSION_PORT}}", "[::]:{{SUBMISSION_PORT}}"] + +[sieve] +bind = ["0.0.0.0:{{MANAGESIEVE_PORT}}", "[::]:{{MANAGESIEVE_PORT}}"] + +[acme] +enable = false + +[dkim] +domain = "{{MAIL_DOMAIN}}" +selector = "stalwart" + +[authentication] +directory = "internal" +fail2ban = true + +[authentication.directory.internal] +enable = true +class = "internal" + +[authentication.directory.internal.config] +backend = "rocksdb" +path = "{{STORAGE_DATA}}/auth" + +[authentication.directory.internal.config.password.schemes] +argon2 = true +bcrypt = true +sha512 = true + +[authentication.directory.internal.config.password.max] +iterations = 10 +size = 32 + +[authentication.directory.internal.config.password.force] +iterations = false +size = false + +[authentication.directory.internal.config.throttling] +max-auth-per-ip = 10 +max-errors-per-ip = 10 +window-secs = 600 + +[authentication.directory.internal.config.heartbeat] +enable = false +interval-secs = 0 + +[authentication.fallback] +enable = true + +[authentication.fallback.class] +enable = true +require-scope = false + +[authentication.fallback.class.config] +verify-email = false +verify-subaddress = false + +[authentication.fallback.class.config.domain] +names = [] +catch-all = false +tag-plus = true +tag-hyphen = false + +[authentication.fallback.class.config.oidc] +enable = false +discovery-url = "" +client-id = "" +client-secret = "" +allow-signup = false +scopes = ["openid", "email", "profile"] +grant-type = "authorization-code" +auth-url = "" +token-url = "" +userinfo-url = "" +jwt-key = "" +jwk-url = "" + +[storage.data] +type = "rocksdb" +path = "{{STORAGE_DATA}}/data" + +[storage.logs] +type = "rocksdb" +path = "{{STORAGE_DATA}}/logs" + +[storage.queue] +type = "rocksdb" +path = "{{STORAGE_DATA}}/queue" + +[storage.blobs] +type = "rocksdb" +path = "{{STORAGE_DATA}}/blobs" + +[storage.fts] +type = "rocksdb" +path = "{{STORAGE_DATA}}/fts" + +[storage.privacy] +type = "rocksdb" +path = "{{STORAGE_DATA}}/privacy" + +[storage.counters] +type = "rocksdb" +path = "{{STORAGE_DATA}}/counters" + +[storage.pool] +type = "rocksdb" +path = "{{STORAGE_DATA}}/pool" + +[storage.cache] +type = "rocksdb" +path = "{{STORAGE_DATA}}/cache" + +[storage.envelope] +type = "rocksdb" +path = "{{STORAGE_DATA}}/envelope" + +[storage.index] +type = "rocksdb" +path = "{{STORAGE_DATA}}/index" + +[storage.spam-filter] +type = "rocksdb" +path = "{{STORAGE_DATA}}/spam-filter" + +[storage.in-memory] +type = "memory" + +[storage.static] +type = "memory" + +[repository] +default = "rocksdb" + +[repository.rocksdb] +driver = "rocksdb" + +[smtp.queue] +retry = [60, 300, 900, 3600, 7200, 21600, 43200] +max-retries = 10 +max-size = 52428800 +notify = ["postmaster@{{MAIL_DOMAIN}}"] +path = "{{STORAGE_DATA}}/queue" + +[smtp.queue.remote] +concurrency = 10 +timeout = 300 + +[smtp.outgoing] +max-helo = 5 +max-recipients = 100 +max-connection-age = 600 +max-connections = 10 +greeting-delay = 0 + +[smtp.dkim] +sign = ["{{MAIL_DOMAIN}}"] +keys = [] + +[smtp.dmarc] +reject = false +allow-unsigned = true +tag-only = false + +[smtp.spam-filter] +enable = true +path = "{{STORAGE_DATA}}/spam-filter" + +[smtp.auth.rate-limit] +max-per-ip = 10 +window-secs = 600 + +[http.dashboard] +enable = true + +[http.api] +enable = true + +[http.webmail] +enable = false + +[http.static] +enable = true + +[http.cors] +allow-origin = "*" +allow-methods = ["GET", "POST", "PUT", "DELETE"] +allow-headers = ["Content-Type", "Authorization"] +max-age = 3600 + +[http.tls] +enable = false +certificate = "" +private-key = "" + +[logging] +level = "info" + +[logging.channel.smtp] +enable = true +level = "info" + +[logging.channel.auth] +enable = true +level = "info" + +[logging.channel.store] +enable = false +level = "info" + +[logging.channel.http] +enable = true +level = "info" diff --git a/apps/stalwart/entrypoint.sh b/apps/stalwart/entrypoint.sh new file mode 100644 index 0000000..39d02dd --- /dev/null +++ b/apps/stalwart/entrypoint.sh @@ -0,0 +1,86 @@ +#!/bin/bash + +# Wait for the container to fully initialize +sleep 1 + +# Default the TZ environment variable to UTC. +TZ=${TZ:-UTC} +export TZ + +# Switch to the container's working directory +cd /home/container || exit 1 + +# Stalwart paths +STALWART_HOME="/home/container/stalwart-mail" +STALWART_CONFIG="${STALWART_HOME}/config.toml" +STALWART_DATA="${STALWART_HOME}/data" +STALWART_CERTS="${STALWART_HOME}/certs" +STALWART_LOGS="${STALWART_HOME}/logs" + +# Create config from template if not exists +if [ ! -f "${STALWART_CONFIG}" ]; then + echo "Generating Stalwart configuration..." + cp /entrypoint-config.toml "${STALWART_CONFIG}" + + # Replace placeholders with environment variables + sed -i "s|{{MAIL_DOMAIN}}|${MAIL_DOMAIN:-mail.example.com}|g" "${STALWART_CONFIG}" + sed -i "s|{{MAIL_HOSTNAME}}|${MAIL_HOSTNAME:-$(hostname)|g" "${STALWART_CONFIG}" + sed -i "s|{{ADMIN_EMAIL}}|${ADMIN_EMAIL:-admin@${MAIL_DOMAIN:-mail.example.com}}|g" "${STALWART_CONFIG}" + sed -i "s|{{HTTP_PORT}}|${HTTP_PORT:-8080}|g" "${STALWART_CONFIG}" + sed -i "s|{{SMTP_PORT}}|${SMTP_PORT:-465}|g" "${STALWART_CONFIG}" + sed -i "s|{{SUBMISSION_PORT}}|${SUBMISSION_PORT:-587}|g" "${STALWART_CONFIG}" + sed -i "s|{{IMAP_PORT}}|${IMAP_PORT:-993}|g" "${STALWART_CONFIG}" + sed -i "s|{{MANAGESIEVE_PORT}}|${MANAGESIEVE_PORT:-4190}|g" "${STALWART_CONFIG}" + sed -i "s|{{STORAGE_DATA}}|${STALWART_DATA}|g" "${STALWART_CONFIG}" + sed -i "s|{{STORAGE_LOGS}}|${STALWART_LOGS}|g" "${STALWART_CONFIG}" + + echo "Configuration generated." +fi + +# Generate admin password if not set +if [ ! -f "${STALWART_HOME}/.admin_created" ]; then + ADMIN_PASS=${ADMIN_PASSWORD:-$(openssl rand -base64 16)} + echo "" + echo "==========================================" + echo " Stalwart Mail Server" + echo "==========================================" + echo " Admin URL: http://${SERVER_IP:-0.0.0.0}:${HTTP_PORT:-8080}" + echo " Admin Email: ${ADMIN_EMAIL:-admin@${MAIL_DOMAIN:-mail.example.com}}" + echo " Admin Pass: ${ADMIN_PASS}" + echo "==========================================" + echo " IMPORTANT: Save these credentials!" + echo "==========================================" + echo "" + + # Create admin account + /home/container/stalwart-mail/bin/stalwart-mail --config "${STALWART_CONFIG}" --write-config + + touch "${STALWART_HOME}/.admin_created" +fi + +# Clone Git repos if GIT_REPOS is set (for custom configs, filters, etc.) +if [ ! -z "${GIT_REPOS}" ]; then + IFS=',' read -ra REPOS <<< "$GIT_REPOS" + for repo in "${REPOS[@]}"; do + repo=$(echo "$repo" | xargs) + if [ ! -z "$repo" ]; then + REPO_NAME=$(basename "$repo" .git) + CLONE_DIR="${STALWART_HOME}/plugins/${REPO_NAME}" + if [ -d "${CLONE_DIR}/.git" ]; then + echo "Updating plugin: ${REPO_NAME}..." + cd "${CLONE_DIR}" && git pull && cd /home/container + else + echo "Cloning plugin: ${REPO_NAME}..." + mkdir -p "${STALWART_HOME}/plugins" + git clone "$repo" "${CLONE_DIR}" + fi + fi + done +fi + +# Replace Startup Variables +MODIFIED_STARTUP=$(echo ${STARTUP} | sed -e 's/{{/${/g' -e 's/}}/}/g') +echo -e ":/home/container$ ${MODIFIED_STARTUP}" + +# Run the Server +eval ${MODIFIED_STARTUP} diff --git a/eggs/gmod_64bit.json b/eggs/gmod_64bit.json new file mode 100644 index 0000000..14e8428 --- /dev/null +++ b/eggs/gmod_64bit.json @@ -0,0 +1,177 @@ +{ + "meta": { + "version": "PTDL_v2", + "description": "Garry's Mod Dedicated Server (64-bit) with Steam Workshop & Git support" + }, + "name": "Garry's Mod 64-bit", + "author": "admin@refoseltw.ru", + "description": "Garry's Mod Dedicated Server running in 64-bit mode with Steam Workshop and Git addon loading support.", + "features": null, + "images": [ + { + "image": "gitea.refoseltw.ru/RefoselTeamWork/yolks:latest", + "meta": { + "ghcr_enabled": false, + "ghcr_organization": "", + "ghcr_repo": "" + } + } + ], + "file_denylist": [ + "server.cfg" + ], + "startup": "/home/container/server/srcds_run -game garrysmod +map {{SRCDS_MAP}} +maxplayers {{SRCDS_MAX_PLAYERS}} -port {{SERVER_PORT}} -tickrate {{SRCDS_TICKRATE}} +ip 0.0.0.0 -autoupdate +gamemode {{SRCDS_GAMEMODE}}", + "script": { + "container": "gitea.refoseltw.ru/RefoselTeamWork/installers:debian", + "entrypoint": "bash", + "extends": "" + }, + "config": { + "files": "{}", + "stop": "quit", + "logs": "{}", + "startup": { + "done": "VAC secure mode is activated." + }, + "professionally": false + }, + "allocator": 0, + "tags": [ + "gmod", + "garrys-mod", + "source-engine", + "64bit" + ], + "credits": "RefoselTeam", + "update_url": "", + "force_outgoing_ip": false, + "remove_old_files": false, + "variables": [ + { + "name": "Hostname", + "description": "The hostname of the server.", + "env_variable": "SRCDS_HOSTNAME", + "default_value": "Garry's Mod Server", + "user_viewable": true, + "user_editable": true, + "rules": "required|string|between:1,64" + }, + { + "name": "Server Password", + "description": "Password to join the server. Leave empty for no password.", + "env_variable": "SRCDS_PASSWORD", + "default_value": "", + "user_viewable": true, + "user_editable": true, + "rules": "nullable|string|between:0,32" + }, + { + "name": "RCON Password", + "description": "Remote console password. Change this!", + "env_variable": "SRCDS_RCON_PASSWORD", + "default_value": "changeme", + "user_viewable": false, + "user_editable": true, + "rules": "required|string|between:1,32" + }, + { + "name": "Gamemode", + "description": "The gamemode to use (sandbox, darkrp, etc).", + "env_variable": "SRCDS_GAMEMODE", + "default_value": "sandbox", + "user_viewable": true, + "user_editable": true, + "rules": "required|string|between:1,32" + }, + { + "name": "Map", + "description": "The starting map for the server.", + "env_variable": "SRCDS_MAP", + "default_value": "gm_flatgrass", + "user_viewable": true, + "user_editable": true, + "rules": "required|string|between:1,32" + }, + { + "name": "Max Players", + "description": "Maximum number of players allowed.", + "env_variable": "SRCDS_MAX_PLAYERS", + "default_value": "16", + "user_viewable": true, + "user_editable": true, + "rules": "required|integer|between:1,128" + }, + { + "name": "Tickrate", + "description": "Server tickrate (66 or 128 recommended).", + "env_variable": "SRCDS_TICKRATE", + "default_value": "66", + "user_viewable": true, + "user_editable": true, + "rules": "required|integer|between:33,128" + }, + { + "name": "Region", + "description": "Server region (255 = global, 0 = US East, 1 = US West, 2 = South America, 3 = Europe, 4 = Asia, 5 = Australia, 6 = Middle East, 7 = Africa).", + "env_variable": "SRCDS_REGION", + "default_value": "255", + "user_viewable": true, + "user_editable": false, + "rules": "required|integer|between:0,255" + }, + { + "name": "Workshop Collection ID", + "description": "Steam Workshop collection ID to auto-load on startup.", + "env_variable": "SRCDS_WORKSHOP_COLLECTION", + "default_value": "", + "user_viewable": true, + "user_editable": true, + "rules": "nullable|string|between:0,64" + }, + { + "name": "Git Repositories", + "description": "Comma-separated list of Git repo URLs to clone into addons/ (e.g. https://github.com/user/repo.git,https://gitlab.com/user/repo2.git).", + "env_variable": "GIT_REPOS", + "default_value": "", + "user_viewable": true, + "user_editable": true, + "rules": "nullable|string|between:0,1024" + }, + { + "name": "Steam Beta Branch", + "description": "Steam beta branch to use. Leave empty for default.", + "env_variable": "SRCDS_BETAID", + "default_value": "", + "user_viewable": true, + "user_editable": true, + "rules": "nullable|string|between:0,64" + }, + { + "name": "Beta Password", + "description": "Password for the beta branch.", + "env_variable": "SRCDS_BETAPASS", + "default_value": "", + "user_viewable": true, + "user_editable": true, + "rules": "nullable|string|between:0,64" + }, + { + "name": "Auto Update", + "description": "Automatically update the server on restart (1 = yes, 0 = no).", + "env_variable": "AUTO_UPDATE", + "default_value": "1", + "user_viewable": true, + "user_editable": true, + "rules": "required|boolean" + }, + { + "name": "Validate Files", + "description": "Validate server files on update (1 = yes, 0 = no).", + "env_variable": "VALIDATE", + "default_value": "", + "user_viewable": true, + "user_editable": true, + "rules": "nullable|boolean" + } + ] +} diff --git a/eggs/stalwart_mail.json b/eggs/stalwart_mail.json new file mode 100644 index 0000000..fd0cd7d --- /dev/null +++ b/eggs/stalwart_mail.json @@ -0,0 +1,151 @@ +{ + "meta": { + "version": "PTDL_v2", + "description": "Stalwart Mail Server - All-in-one SMTP, IMAP, JMAP, CalDAV, CardDAV" + }, + "name": "Stalwart Mail Server", + "author": "admin@refoseltw.ru", + "description": "Stalwart Mail Server - secure, scalable all-in-one mail server with SMTP, IMAP, JMAP, CalDAV, CardDAV and built-in spam filter. Single binary, zero dependencies.", + "features": null, + "images": [ + { + "image": "gitea.refoseltw.ru/RefoselTeamWork/yolks:stalwart", + "meta": { + "ghcr_enabled": false, + "ghcr_organization": "", + "ghcr_repo": "" + } + } + ], + "file_denylist": [], + "startup": "/home/container/stalwart-mail/bin/stalwart-mail --config /home/container/stalwart-mail/config.toml", + "script": { + "container": "gitea.refoseltw.ru/RefoselTeamWork/installers:debian", + "entrypoint": "bash", + "extends": "" + }, + "config": { + "files": "{}", + "stop": "^C", + "logs": "{}", + "startup": { + "done": "listening on" + }, + "professionally": false + }, + "allocator": 0, + "tags": [ + "mail", + "smtp", + "imap", + "jmap", + "caldav", + "carddav", + "email" + ], + "credits": "RefoselTeam", + "update_url": "", + "force_outgoing_ip": false, + "remove_old_files": false, + "variables": [ + { + "name": "Mail Domain", + "description": "Your mail domain (e.g. mail.example.com). This is the FQDN for the mail server.", + "env_variable": "MAIL_DOMAIN", + "default_value": "mail.example.com", + "user_viewable": true, + "user_editable": true, + "rules": "required|fqdn" + }, + { + "name": "Mail Hostname", + "description": "Server hostname (FQDN). Usually same as mail domain.", + "env_variable": "MAIL_HOSTNAME", + "default_value": "", + "user_viewable": true, + "user_editable": true, + "rules": "nullable|fqdn" + }, + { + "name": "Admin Email", + "description": "Email address for the admin account.", + "env_variable": "ADMIN_EMAIL", + "default_value": "", + "user_viewable": true, + "user_editable": true, + "rules": "nullable|email" + }, + { + "name": "Admin Password", + "description": "Password for the admin account. If empty, a random password will be generated.", + "env_variable": "ADMIN_PASSWORD", + "default_value": "", + "user_viewable": true, + "user_editable": true, + "rules": "nullable|string|between:8,128" + }, + { + "name": "HTTP Port", + "description": "Port for the web admin panel.", + "env_variable": "HTTP_PORT", + "default_value": "8080", + "user_viewable": true, + "user_editable": true, + "rules": "required|integer|between:1024,65535" + }, + { + "name": "SMTP Port", + "description": "Port for SMTPS (SSL/TLS).", + "env_variable": "SMTP_PORT", + "default_value": "465", + "user_viewable": true, + "user_editable": false, + "rules": "required|integer|between:1,65535" + }, + { + "name": "Submission Port", + "description": "Port for SMTP Submission (STARTTLS).", + "env_variable": "SUBMISSION_PORT", + "default_value": "587", + "user_viewable": true, + "user_editable": false, + "rules": "required|integer|between:1,65535" + }, + { + "name": "IMAP Port", + "description": "Port for IMAPS (SSL/TLS).", + "env_variable": "IMAP_PORT", + "default_value": "993", + "user_viewable": true, + "user_editable": false, + "rules": "required|integer|between:1,65535" + }, + { + "name": "ManageSieve Port", + "description": "Port for ManageSieve.", + "env_variable": "MANAGESIEVE_PORT", + "default_value": "4190", + "user_viewable": true, + "user_editable": false, + "rules": "required|integer|between:1,65535" + }, + { + "name": "Git Repositories", + "description": "Comma-separated list of Git repo URLs to clone into plugins/ (for custom configs, filters, etc).", + "env_variable": "GIT_REPOS", + "default_value": "", + "user_viewable": true, + "user_editable": true, + "rules": "nullable|string|between:0,1024" + }, + { + "name": "Timezone", + "description": "Server timezone.", + "env_variable": "TZ", + "default_value": "UTC", + "user_viewable": true, + "user_editable": true, + "rules": "required|string|between:1,64" + } + ] +} diff --git a/games/gmod/Dockerfile b/games/gmod/Dockerfile new file mode 100644 index 0000000..c977426 --- /dev/null +++ b/games/gmod/Dockerfile @@ -0,0 +1,83 @@ +FROM --platform=$TARGETOS/$TARGETARCH debian:bookworm-slim + +LABEL author="RefoselTeam" maintainer="admin@refoseltw.ru" + +LABEL org.opencontainers.image.source="https://gitea.refoseltw.ru/RefoselTeamWork/yolks" +LABEL org.opencontainers.image.licenses=MIT + +ENV DEBIAN_FRONTEND=noninteractive + +RUN dpkg --add-architecture i386 \ + && apt update \ + && apt upgrade -y \ + && apt install -y \ + curl \ + g++ \ + gcc \ + gdb \ + git \ + iproute2 \ + locales \ + net-tools \ + netcat-traditional \ + tar \ + telnet \ + tini \ + tzdata \ + wget \ + lib32gcc-s1 \ + lib32stdc++6 \ + lib32tinfo6 \ + lib32z1 \ + libcurl3-gnutls:i386 \ + libcurl4-gnutls-dev:i386 \ + libcurl4:i386 \ + libfontconfig1 \ + libgcc-11-dev \ + libgcc-12-dev \ + libncurses5:i386 \ + libsdl1.2debian \ + libsdl2-2.0-0:i386 \ + libssl-dev:i386 \ + libtinfo6:i386 \ + && apt clean \ + && rm -rf /var/lib/apt/lists/* + +# Install SteamCMD +RUN mkdir -p /usr/games/steamcmd \ + && cd /usr/games/steamcmd \ + && curl -sSL https://steamcdn-a.akamaihd.net/client/installer/steamcmd_linux.tar.gz | tar -xzv + +# Install rcon +RUN cd /tmp/ \ + && curl -sSL https://github.com/gorcon/rcon-cli/releases/download/v0.10.3/rcon-0.10.3-amd64_linux.tar.gz > rcon.tar.gz \ + && tar xvf rcon.tar.gz \ + && mv rcon-0.10.3-amd64_linux/rcon /usr/local/bin/ \ + && rm -rf /tmp/* + +# Temp fix for things that still need libssl1.1 +RUN if [ "$(uname -m)" = "x86_64" ]; then \ + wget http://archive.ubuntu.com/ubuntu/pool/main/o/openssl/libssl1.1_1.1.0g-2ubuntu4_amd64.deb && \ + dpkg -i libssl1.1_1.1.0g-2ubuntu4_amd64.deb && \ + rm libssl1.1_1.1.0g-2ubuntu4_amd64.deb; \ + fi + +# Set the locale +RUN sed -i '/en_US.UTF-8/s/^# //g' /etc/locale.gen && \ + locale-gen +ENV LANG=en_US.UTF-8 +ENV LANGUAGE=en_US:en +ENV LC_ALL=en_US.UTF-8 + +# Setup user and working directory +RUN useradd -m -d /home/container -s /bin/bash container +USER container +ENV USER=container HOME=/home/container +WORKDIR /home/container + +STOPSIGNAL SIGINT + +COPY --chown=container:container ./entrypoint.sh /entrypoint.sh +RUN chmod +x /entrypoint.sh +ENTRYPOINT ["/usr/bin/tini", "-g", "--"] +CMD ["/entrypoint.sh"] diff --git a/games/gmod/entrypoint.sh b/games/gmod/entrypoint.sh new file mode 100644 index 0000000..503147c --- /dev/null +++ b/games/gmod/entrypoint.sh @@ -0,0 +1,73 @@ +#!/bin/bash + +# Wait for the container to fully initialize +sleep 1 + +# Default the TZ environment variable to UTC. +TZ=${TZ:-UTC} +export TZ + +# Set environment variable that holds the Internal Docker IP +INTERNAL_IP=$(ip route get 1 | awk '{print $(NF-2);exit}') +export INTERNAL_IP + +# Switch to the container's working directory +cd /home/container || exit 1 + +# Default steam user +if [ "${STEAM_USER}" == "" ]; then + echo -e "steam user is not set.\n" + echo -e "Using anonymous user.\n" + STEAM_USER=anonymous + STEAM_PASS="" + STEAM_AUTH="" +else + echo -e "user set to ${STEAM_USER}" +fi + +# Auto update +if [ -z ${AUTO_UPDATE} ] || [ "${AUTO_UPDATE}" == "1" ]; then + if [ ! -z ${SRCDS_APPID} ]; then + /usr/games/steamcmd/steamcmd.sh +force_install_dir /home/container +login ${STEAM_USER} ${STEAM_PASS} ${STEAM_AUTH} +app_update 1007 +app_update ${SRCDS_APPID} $( [[ -z ${SRCDS_BETAID} ]] || printf %s "-beta ${SRCDS_BETAID}" ) $( [[ -z ${SRCDS_BETAPASS} ]] || printf %s "-betapassword ${SRCDS_BETAPASS}" ) $( [[ -z ${HLDS_GAME} ]] || printf %s "+app_set_config 90 mod ${HLDS_GAME}" ) $( [[ -z ${VALIDATE} ]] || printf %s "validate" ) +quit + else + echo -e "No appid set. Starting Server" + fi +else + echo -e "Not updating game server as auto update was set to 0. Starting Server" +fi + +# Create Steam SDK symlinks +mkdir -p .steam/sdk64 +ln -sf /usr/games/steamcmd/linux64/steamclient.so .steam/sdk64/steamclient.so +ln -sf /usr/games/steamcmd/linux32/steamclient.so .steam/sdk32/steamclient.so + +# Clone Git addons if GIT_REPOS is set +if [ ! -z "${GIT_REPOS}" ]; then + IFS=',' read -ra REPOS <<< "$GIT_REPOS" + for repo in "${REPOS[@]}"; do + repo=$(echo "$repo" | xargs) + if [ ! -z "$repo" ]; then + REPO_NAME=$(basename "$repo" .git) + ADDON_DIR="garrysmod/addons/${REPO_NAME}" + if [ -d "$ADDON_DIR/.git" ]; then + echo "Updating Git addon: ${REPO_NAME}..." + cd "$ADDON_DIR" && git pull && cd /home/container + else + echo "Cloning Git addon: ${REPO_NAME}..." + git clone "$repo" "$ADDON_DIR" + fi + fi + done +fi + +# Load Workshop collection +if [ ! -z "${SRCDS_WORKSHOP_COLLECTION}" ]; then + echo "Workshop collection ${SRCDS_WORKSHOP_COLLECTION} will be loaded on first start." +fi + +# Replace Startup Variables +MODIFIED_STARTUP=$(echo ${STARTUP} | sed -e 's/{{/${/g' -e 's/}}/}/g') +echo -e ":/home/container$ ${MODIFIED_STARTUP}" + +# Run the Server +eval ${MODIFIED_STARTUP}