From 4b60b6b8ade36863d6c110ca1e162cdb8f768ed0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?c=C4=83t=C4=83lin?= Date: Tue, 1 Apr 2025 19:24:08 +0200 Subject: [PATCH] feat: add valheim chart and argo app --- .pre-commit-config.yaml | 3 - .yamllint.yaml | 3 + k8s/argo-apps/valheim.yaml | 41 ++++ k8s/charts/valheim-server/.gitignore | 1 + k8s/charts/valheim-server/.helmignore | 23 ++ k8s/charts/valheim-server/Chart.yaml | 29 +++ k8s/charts/valheim-server/README.md | 193 +++++++++++++++ k8s/charts/valheim-server/README.md.gotmpl | 115 +++++++++ k8s/charts/valheim-server/templates/NOTES.txt | 40 +++ .../valheim-server/templates/_helpers.tpl | 51 ++++ .../valheim-server/templates/deployment.yaml | 208 ++++++++++++++++ k8s/charts/valheim-server/templates/pvc.yaml | 67 ++++++ .../valheim-server/templates/service.yaml | 34 +++ k8s/charts/valheim-server/values.yaml | 227 ++++++++++++++++++ k8s/services/valheim/sealedsecrets.yaml | 16 ++ 15 files changed, 1048 insertions(+), 3 deletions(-) create mode 100644 k8s/argo-apps/valheim.yaml create mode 100644 k8s/charts/valheim-server/.gitignore create mode 100644 k8s/charts/valheim-server/.helmignore create mode 100644 k8s/charts/valheim-server/Chart.yaml create mode 100644 k8s/charts/valheim-server/README.md create mode 100644 k8s/charts/valheim-server/README.md.gotmpl create mode 100644 k8s/charts/valheim-server/templates/NOTES.txt create mode 100644 k8s/charts/valheim-server/templates/_helpers.tpl create mode 100644 k8s/charts/valheim-server/templates/deployment.yaml create mode 100644 k8s/charts/valheim-server/templates/pvc.yaml create mode 100644 k8s/charts/valheim-server/templates/service.yaml create mode 100644 k8s/charts/valheim-server/values.yaml create mode 100644 k8s/services/valheim/sealedsecrets.yaml diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 0f141c8..c2bed7c 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -11,9 +11,6 @@ repos: - id: pretty-format-json - id: check-merge-conflict - id: check-symlinks - - id: check-yaml - args: - - --allow-multiple-documents - id: detect-private-key - id: trailing-whitespace diff --git a/.yamllint.yaml b/.yamllint.yaml index a8e1307..4ffc165 100644 --- a/.yamllint.yaml +++ b/.yamllint.yaml @@ -5,6 +5,9 @@ yaml-files: - '*.yml' - '.yamllint' +ignore: | + k8s/charts/ + extends: default rules: diff --git a/k8s/argo-apps/valheim.yaml b/k8s/argo-apps/valheim.yaml new file mode 100644 index 0000000..699f2f2 --- /dev/null +++ b/k8s/argo-apps/valheim.yaml @@ -0,0 +1,41 @@ +--- +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: valheim + namespace: argocd +spec: + destination: + name: '' + namespace: apps-fuku + server: https://kubernetes.default.svc + sources: + - path: k8s/charts/valheim-server + repoURL: https://git.roboces.dev/catalin/fukuops.git + targetRevision: main + helm: + valuesObject: + server: + name: "Huesoperrers Váljei" + public: 1 + timezone: Europe/Madrid + secret: + name: valheim-secrets + key: server-password + persistence: + saves: + accessMode: ReadWriteMany + server: + accessMode: ReadWriteMany + backups: + accessMode: ReadWriteMany + resources: + requests: + memory: 4Gi + cpu: 2000m + limits: + memory: 8Gi + cpu: 4000m + project: fuku + syncPolicy: + automated: {} diff --git a/k8s/charts/valheim-server/.gitignore b/k8s/charts/valheim-server/.gitignore new file mode 100644 index 0000000..f1a5990 --- /dev/null +++ b/k8s/charts/valheim-server/.gitignore @@ -0,0 +1 @@ +custom-values.yaml diff --git a/k8s/charts/valheim-server/.helmignore b/k8s/charts/valheim-server/.helmignore new file mode 100644 index 0000000..0e8a0eb --- /dev/null +++ b/k8s/charts/valheim-server/.helmignore @@ -0,0 +1,23 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ diff --git a/k8s/charts/valheim-server/Chart.yaml b/k8s/charts/valheim-server/Chart.yaml new file mode 100644 index 0000000..6c60582 --- /dev/null +++ b/k8s/charts/valheim-server/Chart.yaml @@ -0,0 +1,29 @@ +apiVersion: v2 +name: valheim-server +description: A Helm chart for deploying a Valheim dedicated server on Kubernetes +type: application +version: 1.0.0 +appVersion: "3.1.0" +home: https://www.valheimgame.com/ +icon: https://cdn2.steamgriddb.com/icon/d17892563a6984845a0e23df7841f903/32/256x256.png +maintainers: + - name: kriegalex + email: kriegalex@gmail.com +keywords: + - game + - valheim + - gameserver + - dedicated-server +sources: + - https://github.com/mbround18/valheim-docker + - https://github.com/kriegalex/k8s-charts/tree/main/charts/valheim-server +deprecated: false +annotations: + artifacthub.io/links: | + - name: Chart source + url: https://github.com/kriegalex/k8s-charts/tree/main/charts/valheim-server + - name: Docker image source + url: https://github.com/mbround18/valheim-docker + artifacthub.io/images: | + - name: valheim + image: mbround18/valheim:3.1.0 diff --git a/k8s/charts/valheim-server/README.md b/k8s/charts/valheim-server/README.md new file mode 100644 index 0000000..1b42e06 --- /dev/null +++ b/k8s/charts/valheim-server/README.md @@ -0,0 +1,193 @@ +# valheim-server + +![Version: 1.0.0](https://img.shields.io/badge/Version-1.0.0-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 3.1.0](https://img.shields.io/badge/AppVersion-3.1.0-informational?style=flat-square) + +A Helm chart for deploying a Valheim dedicated server on Kubernetes + +**Homepage:** + +## Maintainers + +| Name | Email | Url | +| ---- | ------ | --- | +| kriegalex | | | + +## Source Code + +* +* + +## Overview + +This Helm chart deploys a Valheim dedicated server based on the [mbround18/valheim-docker](https://github.com/mbround18/valheim-docker) project. + +## Features + +- Configurable server settings +- Automatic updates and backups +- Discord webhook notifications +- Persistent storage for game saves, server files, and backups +- Resource management for Kubernetes + +## Prerequisites + +- Kubernetes 1.29+ +- Helm 3.16.0+ +- PV provisioner support in the underlying infrastructure (for persistent storage) +- LoadBalancer support or an Ingress controller + +## TL;DR + +```bash +helm repo add k8s-charts https://kriegalex.github.io/k8s-charts/ +helm install my-valheim-server k8s-charts/valheim-server +``` + +## Important Security Notice +The default values for this chart include a placeholder password. For production use: + +1. Always specify a secure password +2. Consider using Kubernetes secrets for sensitive values +3. Restrict access to your server using appropriate network policies + +## Installation + +### Simple Install with Custom Password and Server Name + +```bash +helm upgrade --install my-valheim-server \ + --set server.password="YourStrongPassword" \ + --set server.name="Your Awesome Valheim Server" \ + k8s-charts/valheim-server +``` + +### Custom Configuration File +Create a YAML file with your custom values: + +```yaml +server: + name: "My Custom Valheim Server" + password: "SuperSecretPassword" + world: "MyWorld" + public: 1 + +persistence: + saves: + size: 5Gi + backups: + size: 20Gi + +automation: + autoBackup: 1 # disabled by default + autoBackupSchedule: "*/30 * * * *" + +resources: + requests: + memory: 4Gi + cpu: 2000m + limits: + memory: 12Gi + cpu: 4000m +``` + +Then install the chart: + +```bash +helm install my-valheim-server -f my-values.yaml k8s-charts/valheim-server +``` + +## Updating + +```bash +helm upgrade my-valheim-server k8s-charts/valheim-server +``` + +## Uninstallation + +```bash +helm uninstall my-valheim-server +``` + +Note: This will not delete the Persistent Volume Claims. To delete them: + +```bash +kubectl delete pvc -l app.kubernetes.io/instance=my-valheim-server +``` + +## Values + +| Key | Type | Default | Description | +|-----|------|---------|-------------| +| affinity | object | `{}` | Affinity for pod assignment | +| automation.autoBackup | int | `0` | Enable automatic backups (1=enabled, 0=disabled) | +| automation.autoBackupDaysToLive | int | `7` | Number of days to keep backups | +| automation.autoBackupOnShutdown | int | `0` | Create backup on server shutdown (1=enabled, 0=disabled) | +| automation.autoBackupOnUpdate | int | `1` | Create backup before updates (1=enabled, 0=disabled) | +| automation.autoBackupRemoveOld | int | `1` | Remove old backups automatically (1=enabled, 0=disabled) | +| automation.autoBackupSchedule | string | `"*/15 * * * *"` | Cron schedule for automatic backups | +| automation.autoUpdate | int | `1` | Enable automatic updates (1=enabled, 0=disabled) | +| automation.autoUpdateSchedule | string | `"0 1 * * *"` | Cron schedule for automatic updates | +| automation.updateOnStartup | int | `0` | Update server when container starts (1=enabled, 0=disabled) | +| extraEnv | list | `[]` | Additional environment variables for the Valheim server | +| fullnameOverride | string | `""` | Provide a full name override for resources | +| image.pullPolicy | string | `"IfNotPresent"` | Image pull policy | +| image.repository | string | `"mbround18/valheim"` | Docker repository to use | +| image.tag | string | `""` | Docker tag to use - use "latest" for most current version | +| initContainers | object | `{"args":[],"command":[],"enabled":false,"image":"busybox:latest"}` | Init container configuration for server preparation | +| initContainers.args | list | `[]` | Init container arguments | +| initContainers.command | list | `[]` | Init container command | +| initContainers.enabled | bool | `false` | Enable init container | +| initContainers.image | string | `"busybox:latest"` | Init container image | +| livenessProbe.enabled | bool | `false` | Enable liveness probe | +| livenessProbe.failureThreshold | int | 6 (allows up to 2 minutes for recovery) | Failure threshold | +| livenessProbe.initialDelaySeconds | int | `60` | Initial delay seconds | +| livenessProbe.periodSeconds | int | `20` | Period seconds | +| livenessProbe.timeoutSeconds | int | `5` | Timeout seconds | +| modding.bepInEx | int | `0` | Enable BepInEx for mods (1=enabled, 0=disabled) | +| modding.modPath | string | `"/home/steam/valheim/BepInEx"` | Path to mounted mod directory | +| modding.useConfigurationManager | bool | `false` | Enable mounting a ConfigurationManager config | +| nameOverride | string | `""` | Provide a name override for resources | +| nodeSelector | object | `{}` | Node selector for pod assignment | +| notifications.includePublicIp | int | `0` | Include the server's public IP in notifications (1=enabled, 0=disabled) | +| notifications.webhookUrl | string | `""` | Discord webhook URL for server notifications | +| persistence.backups.accessMode | string | `"ReadWriteOnce"` | Access mode for the PVC | +| persistence.backups.existingClaim | string | `""` | Existing claim to use (leave empty to create a new one) | +| persistence.backups.size | string | `"10Gi"` | Size of PVC for backups | +| persistence.enabled | bool | `true` | Enable persistent storage for server data | +| persistence.saves.accessMode | string | `"ReadWriteOnce"` | Access mode for the PVC | +| persistence.saves.existingClaim | string | `""` | Existing claim to use (leave empty to create a new one) | +| persistence.saves.size | string | `"1Gi"` | Size of PVC for game saves | +| persistence.server.accessMode | string | `"ReadWriteOnce"` | Access mode for the PVC | +| persistence.server.existingClaim | string | `""` | Existing claim to use (leave empty to create a new one) | +| persistence.server.size | string | `"4Gi"` | Size of PVC for server files | +| persistence.storageClass | string | use default storage class | Storage class to use (use null for default or "" for no storage class) | +| podSecurityContext.fsGroup | int | `1000` | File system group ID for volume mounts | +| readinessProbe.enabled | bool | `true` | Enable readiness probe | +| readinessProbe.failureThreshold | int | 20 (allows up to 5 minutes for readiness) | Failure threshold | +| readinessProbe.initialDelaySeconds | int | `60` | Initial delay seconds | +| readinessProbe.periodSeconds | int | `15` | Period seconds | +| readinessProbe.timeoutSeconds | int | `5` | Timeout seconds | +| replicaCount | int | `1` | Number of replicas to deploy (should typically stay at 1) | +| resources | object | `{}` | Resource requests and limits | +| securityContext.runAsGroup | int | `1000` | Group ID to run the container processes | +| securityContext.runAsNonRoot | bool | `true` | Force the container to run as a non-root user | +| securityContext.runAsUser | int | `111` | User ID to run the container processes. Should default to the steam user ID. | +| server.name | string | `"Valheim Server with Helm"` | Server name as displayed in-game | +| server.password | string | you MUST change this value | Server access password (minimum 5 characters) | +| server.port | int | `2456` | UDP port for game server (will use PORT, PORT+1, and PORT+2) | +| server.public | int | `0` | Set to 1 to make server visible publicly, 0 for private | +| server.timezone | string | `"UTC"` | Timezone for the server | +| server.world | string | `"Dedicated"` | World name used for save files | +| service.annotations | object | `{}` | Annotations for the service | +| service.loadBalancerIP | string | `""` | Set specific load balancer IP (depends on cloud provider support) | +| service.loadBalancerSourceRanges | list | `[]` | External source IP ranges allowed to access the server | +| service.type | string | `"LoadBalancer"` | Service type | +| startupProbe.enabled | bool | `true` | Enable startup probe | +| startupProbe.failureThreshold | int | 30 (allows up to 5 minutes for initial startup) | Failure threshold | +| startupProbe.initialDelaySeconds | int | `30` | Initial delay seconds | +| startupProbe.periodSeconds | int | `10` | Period seconds | +| startupProbe.timeoutSeconds | int | `5` | Timeout seconds | +| tolerations | list | `[]` | Tolerations for pod assignment | + +---------------------------------------------- +Autogenerated from chart metadata using [helm-docs v1.14.2](https://github.com/norwoodj/helm-docs/releases/v1.14.2) diff --git a/k8s/charts/valheim-server/README.md.gotmpl b/k8s/charts/valheim-server/README.md.gotmpl new file mode 100644 index 0000000..7199c29 --- /dev/null +++ b/k8s/charts/valheim-server/README.md.gotmpl @@ -0,0 +1,115 @@ +{{ template "chart.header" . }} +{{ template "chart.deprecationWarning" . }} + +{{ template "chart.badgesSection" . }} + +{{ template "chart.description" . }} + +{{ template "chart.homepageLine" . }} + +{{ template "chart.maintainersSection" . }} + +{{ template "chart.sourcesSection" . }} + +## Overview + +This Helm chart deploys a Valheim dedicated server based on the [mbround18/valheim-docker](https://github.com/mbround18/valheim-docker) project. + +## Features + +- Configurable server settings +- Automatic updates and backups +- Discord webhook notifications +- Persistent storage for game saves, server files, and backups +- Resource management for Kubernetes + +## Prerequisites + +- Kubernetes 1.29+ +- Helm 3.16.0+ +- PV provisioner support in the underlying infrastructure (for persistent storage) +- LoadBalancer support or an Ingress controller + +## TL;DR + +```bash +helm repo add k8s-charts https://kriegalex.github.io/k8s-charts/ +helm install my-valheim-server k8s-charts/valheim-server +``` + +## Important Security Notice +The default values for this chart include a placeholder password. For production use: + +1. Always specify a secure password +2. Consider using Kubernetes secrets for sensitive values +3. Restrict access to your server using appropriate network policies + +## Installation + +### Simple Install with Custom Password and Server Name + +```bash +helm upgrade --install my-valheim-server \ + --set server.password="YourStrongPassword" \ + --set server.name="Your Awesome Valheim Server" \ + k8s-charts/valheim-server +``` + +### Custom Configuration File +Create a YAML file with your custom values: + +```yaml +server: + name: "My Custom Valheim Server" + password: "SuperSecretPassword" + world: "MyWorld" + public: 1 + +persistence: + saves: + size: 5Gi + backups: + size: 20Gi + +automation: + autoBackup: 1 # disabled by default + autoBackupSchedule: "*/30 * * * *" + +resources: + requests: + memory: 4Gi + cpu: 2000m + limits: + memory: 12Gi + cpu: 4000m +``` + +Then install the chart: + +```bash +helm install my-valheim-server -f my-values.yaml k8s-charts/valheim-server +``` + +## Updating + +```bash +helm upgrade my-valheim-server k8s-charts/valheim-server +``` + +## Uninstallation + +```bash +helm uninstall my-valheim-server +``` + +Note: This will not delete the Persistent Volume Claims. To delete them: + +```bash +kubectl delete pvc -l app.kubernetes.io/instance=my-valheim-server +``` + +{{ template "chart.requirementsSection" . }} + +{{ template "chart.valuesSection" . }} + +{{ template "helm-docs.versionFooter" . }} diff --git a/k8s/charts/valheim-server/templates/NOTES.txt b/k8s/charts/valheim-server/templates/NOTES.txt new file mode 100644 index 0000000..95ed7db --- /dev/null +++ b/k8s/charts/valheim-server/templates/NOTES.txt @@ -0,0 +1,40 @@ +Thank you for installing the Valheim Dedicated Server Helm chart! + +Your server should be starting up now with the following settings: + +Server Name: {{ .Values.server.name }} +World: {{ .Values.server.world }} +Game Port: {{ .Values.server.port }} (UDP) + +{{- if eq .Values.service.type "LoadBalancer" }} +To connect to your server: + +1. Get the external IP address: + kubectl get svc {{ include "valheim-server.fullname" . }} --namespace {{ .Release.Namespace }} + +2. In Valheim, select "Join Game" and add the server manually using: + :{{ .Values.server.port }} + +3. Enter your server password when prompted. +{{- else if eq .Values.service.type "NodePort" }} +To connect to your server: + +1. Get the NodePort assigned to your service: + kubectl get svc {{ include "valheim-server.fullname" . }} --namespace {{ .Release.Namespace }} + +2. In Valheim, select "Join Game" and add the server manually using: + : + +3. Enter your server password when prompted. +{{- else }} +Note: You've deployed with service type "{{ .Values.service.type }}" which may not be accessible from outside the cluster. +You might need to set up port forwarding or ingress to access your server. +{{- end }} + +IMPORTANT SECURITY NOTES: +- Make sure your server password is at least 5 characters long +- Properly secure access to your Kubernetes cluster +- Consider changing the default port if your server is public + +For more information and troubleshooting, please visit: +{{ .Chart.Home }} diff --git a/k8s/charts/valheim-server/templates/_helpers.tpl b/k8s/charts/valheim-server/templates/_helpers.tpl new file mode 100644 index 0000000..50664a8 --- /dev/null +++ b/k8s/charts/valheim-server/templates/_helpers.tpl @@ -0,0 +1,51 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "valheim-server.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "valheim-server.fullname" -}} +{{- if .Values.fullnameOverride }} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default .Chart.Name .Values.nameOverride }} +{{- if contains $name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "valheim-server.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "valheim-server.labels" -}} +helm.sh/chart: {{ include "valheim-server.chart" . }} +{{ include "valheim-server.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "valheim-server.selectorLabels" -}} +app.kubernetes.io/name: {{ include "valheim-server.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} diff --git a/k8s/charts/valheim-server/templates/deployment.yaml b/k8s/charts/valheim-server/templates/deployment.yaml new file mode 100644 index 0000000..70a527e --- /dev/null +++ b/k8s/charts/valheim-server/templates/deployment.yaml @@ -0,0 +1,208 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "valheim-server.fullname" . }} + labels: + {{- include "valheim-server.labels" . | nindent 4 }} +spec: + replicas: {{ .Values.replicaCount }} + selector: + matchLabels: + {{- include "valheim-server.selectorLabels" . | nindent 6 }} + strategy: + type: Recreate + template: + metadata: + labels: + {{- include "valheim-server.selectorLabels" . | nindent 8 }} + spec: + securityContext: + {{- toYaml .Values.podSecurityContext | nindent 8 }} + {{- if .Values.initContainers.enabled }} + initContainers: + - name: init-valheim + image: {{ .Values.initContainers.image }} + {{- if .Values.initContainers.command }} + command: {{ toYaml .Values.initContainers.command | nindent 12 }} + {{- end }} + {{- if .Values.initContainers.args }} + args: {{ toYaml .Values.initContainers.args | nindent 12 }} + {{- end }} + volumeMounts: + - name: saves + mountPath: /home/steam/.config/unity3d/IronGate/Valheim + - name: server + mountPath: /home/steam/valheim + - name: backups + mountPath: /home/steam/backups + {{- end }} + containers: + - name: {{ .Chart.Name }} + securityContext: + {{- toYaml .Values.securityContext | nindent 12 }} + image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + env: + - name: PORT + value: "{{ .Values.server.port }}" + - name: NAME + value: "{{ .Values.server.name }}" + - name: WORLD + value: "{{ .Values.server.world }}" + - name: PASSWORD + valueFrom: + secretKeyRef: + name: {{ .Values.secret.name }} + key: {{ .Values.secret.key }} + - name: TZ + value: "{{ .Values.server.timezone }}" + - name: PUID + value: "{{ .Values.securityContext.runAsUser | default "111" }}" + - name: PGID + value: "{{ .Values.securityContext.runAsGroup | default "1000" }}" + - name: PUBLIC + value: "{{ .Values.server.public }}" + - name: AUTO_UPDATE + value: "{{ .Values.automation.autoUpdate }}" + - name: AUTO_UPDATE_SCHEDULE + value: "{{ .Values.automation.autoUpdateSchedule }}" + - name: UPDATE_ON_STARTUP + value: "{{ .Values.automation.updateOnStartup }}" + - name: AUTO_BACKUP + value: "{{ .Values.automation.autoBackup }}" + - name: AUTO_BACKUP_SCHEDULE + value: "{{ .Values.automation.autoBackupSchedule }}" + - name: AUTO_BACKUP_REMOVE_OLD + value: "{{ .Values.automation.autoBackupRemoveOld }}" + - name: AUTO_BACKUP_DAYS_TO_LIVE + value: "{{ .Values.automation.autoBackupDaysToLive }}" + - name: AUTO_BACKUP_ON_UPDATE + value: "{{ .Values.automation.autoBackupOnUpdate }}" + - name: AUTO_BACKUP_ON_SHUTDOWN + value: "{{ .Values.automation.autoBackupOnShutdown }}" + {{- if .Values.notifications.webhookUrl }} + - name: WEBHOOK_URL + value: "{{ .Values.notifications.webhookUrl }}" + - name: WEBHOOK_INCLUDE_PUBLIC_IP + value: "{{ .Values.notifications.includePublicIp }}" + {{- end }} + {{- if eq (.Values.modding.bepInEx | toString) "1" }} + - name: BEPINEX + value: "1" + {{- end }} + {{- with .Values.extraEnv }} + {{- toYaml . | nindent 12 }} + {{- end }} + ports: + - name: game + containerPort: {{ .Values.server.port }} + protocol: UDP + - name: game-1 + containerPort: {{ add .Values.server.port 1 }} + protocol: UDP + - name: game-2 + containerPort: {{ add .Values.server.port 2 }} + protocol: UDP + lifecycle: + preStop: + exec: + command: [ "/bin/sh", "-c", "kill -SIGINT 1 && sleep 5" ] + volumeMounts: + - name: saves + mountPath: /home/steam/.config/unity3d/IronGate/Valheim + - name: server + mountPath: /home/steam/valheim + - name: backups + mountPath: /home/steam/backups + {{- if eq (.Values.modding.bepInEx | toString) "1" }} + - name: mods + mountPath: {{ .Values.modding.modPath }} + {{- end }} + resources: + {{- toYaml .Values.resources | nindent 12 }} + # Startup probe - wait for server to initialize + {{- if .Values.startupProbe.enabled }} + startupProbe: + exec: + command: + - pgrep + - -f + - valheim_server + initialDelaySeconds: {{ .Values.startupProbe.initialDelaySeconds }} + periodSeconds: {{ .Values.startupProbe.periodSeconds }} + timeoutSeconds: {{ .Values.startupProbe.timeoutSeconds }} + failureThreshold: {{ .Values.startupProbe.failureThreshold }} + {{- end }} + # Readiness probe - verify is server is ready + {{- if .Values.readinessProbe.enabled }} + readinessProbe: + exec: + command: + - pgrep + - -f + - valheim_server + initialDelaySeconds: {{ .Values.readinessProbe.initialDelaySeconds }} + periodSeconds: {{ .Values.readinessProbe.periodSeconds }} + timeoutSeconds: {{ .Values.readinessProbe.timeoutSeconds }} + failureThreshold: {{ .Values.readinessProbe.failureThreshold }} + {{- end }} + # Liveness probe - check if server is running + {{- if .Values.livenessProbe.enabled }} + livenessProbe: + exec: + command: + - pgrep + - -f + - valheim_server + initialDelaySeconds: {{ .Values.livenessProbe.initialDelaySeconds }} + periodSeconds: {{ .Values.livenessProbe.periodSeconds }} + timeoutSeconds: {{ .Values.livenessProbe.timeoutSeconds }} + failureThreshold: {{ .Values.livenessProbe.failureThreshold }} + {{- end }} + volumes: + - name: saves + {{- if and .Values.persistence.enabled .Values.persistence.saves.existingClaim }} + persistentVolumeClaim: + claimName: {{ .Values.persistence.saves.existingClaim }} + {{- else if .Values.persistence.enabled }} + persistentVolumeClaim: + claimName: {{ include "valheim-server.fullname" . }}-saves + {{- else }} + emptyDir: { } + {{- end }} + - name: server + {{- if and .Values.persistence.enabled .Values.persistence.server.existingClaim }} + persistentVolumeClaim: + claimName: {{ .Values.persistence.server.existingClaim }} + {{- else if .Values.persistence.enabled }} + persistentVolumeClaim: + claimName: {{ include "valheim-server.fullname" . }}-server + {{- else }} + emptyDir: { } + {{- end }} + - name: backups + {{- if and .Values.persistence.enabled .Values.persistence.backups.existingClaim }} + persistentVolumeClaim: + claimName: {{ .Values.persistence.backups.existingClaim }} + {{- else if .Values.persistence.enabled }} + persistentVolumeClaim: + claimName: {{ include "valheim-server.fullname" . }}-backups + {{- else }} + emptyDir: { } + {{- end }} + {{- if eq (.Values.modding.bepInEx | toString) "1" }} + - name: mods + emptyDir: { } + {{- end }} + {{- with .Values.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} diff --git a/k8s/charts/valheim-server/templates/pvc.yaml b/k8s/charts/valheim-server/templates/pvc.yaml new file mode 100644 index 0000000..57b1ced --- /dev/null +++ b/k8s/charts/valheim-server/templates/pvc.yaml @@ -0,0 +1,67 @@ +{{- if and .Values.persistence.enabled (not .Values.persistence.saves.existingClaim) }} +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: {{ include "valheim-server.fullname" . }}-saves + labels: + {{- include "valheim-server.labels" . | nindent 4 }} +spec: + accessModes: + - {{ .Values.persistence.saves.accessMode }} + {{- if .Values.persistence.storageClass }} + {{- if (eq "-" .Values.persistence.storageClass) }} + storageClassName: "" + {{- else }} + storageClassName: "{{ .Values.persistence.storageClass }}" + {{- end }} + {{- end }} + resources: + requests: + storage: {{ .Values.persistence.saves.size }} +{{- end }} + +{{- if and .Values.persistence.enabled (not .Values.persistence.server.existingClaim) }} +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: {{ include "valheim-server.fullname" . }}-server + labels: + {{- include "valheim-server.labels" . | nindent 4 }} +spec: + accessModes: + - {{ .Values.persistence.server.accessMode }} + {{- if .Values.persistence.storageClass }} + {{- if (eq "-" .Values.persistence.storageClass) }} + storageClassName: "" + {{- else }} + storageClassName: "{{ .Values.persistence.storageClass }}" + {{- end }} + {{- end }} + resources: + requests: + storage: {{ .Values.persistence.server.size }} +{{- end }} + +{{- if and .Values.persistence.enabled (not .Values.persistence.backups.existingClaim) }} +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: {{ include "valheim-server.fullname" . }}-backups + labels: + {{- include "valheim-server.labels" . | nindent 4 }} +spec: + accessModes: + - {{ .Values.persistence.backups.accessMode }} + {{- if .Values.persistence.storageClass }} + {{- if (eq "-" .Values.persistence.storageClass) }} + storageClassName: "" + {{- else }} + storageClassName: "{{ .Values.persistence.storageClass }}" + {{- end }} + {{- end }} + resources: + requests: + storage: {{ .Values.persistence.backups.size }} +{{- end }} diff --git a/k8s/charts/valheim-server/templates/service.yaml b/k8s/charts/valheim-server/templates/service.yaml new file mode 100644 index 0000000..628c582 --- /dev/null +++ b/k8s/charts/valheim-server/templates/service.yaml @@ -0,0 +1,34 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ include "valheim-server.fullname" . }} + labels: + {{- include "valheim-server.labels" . | nindent 4 }} + {{- with .Values.service.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + type: {{ .Values.service.type }} + {{- if and (eq .Values.service.type "LoadBalancer") .Values.service.loadBalancerIP }} + loadBalancerIP: {{ .Values.service.loadBalancerIP }} + {{- end }} + {{- if and (eq .Values.service.type "LoadBalancer") .Values.service.loadBalancerSourceRanges }} + loadBalancerSourceRanges: + {{- toYaml .Values.service.loadBalancerSourceRanges | nindent 4 }} + {{- end }} + ports: + - port: {{ .Values.server.port }} + targetPort: game + protocol: UDP + name: game + - port: {{ add .Values.server.port 1 }} + targetPort: game-1 + protocol: UDP + name: game-1 + - port: {{ add .Values.server.port 2 }} + targetPort: game-2 + protocol: UDP + name: game-2 + selector: + {{- include "valheim-server.selectorLabels" . | nindent 4 }} diff --git a/k8s/charts/valheim-server/values.yaml b/k8s/charts/valheim-server/values.yaml new file mode 100644 index 0000000..305b436 --- /dev/null +++ b/k8s/charts/valheim-server/values.yaml @@ -0,0 +1,227 @@ +# Specify image settings for the Valheim server container +image: + # -- Docker repository to use + repository: mbround18/valheim + # -- Docker tag to use - use "latest" for most current version + tag: "3.1" + # -- Image pull policy + pullPolicy: Always + +# -- Number of replicas to deploy (should typically stay at 1) +replicaCount: 1 + +# -- Provide a name override for resources +nameOverride: "" + +# -- Provide a full name override for resources +fullnameOverride: "" + +# Server configuration settings +server: + # -- UDP port for game server (will use PORT, PORT+1, and PORT+2) + port: 2456 + # -- Server name as displayed in-game + name: "Valheim Server with Helm" + # -- World name used for save files + world: "Dedicated" + # -- Server access password (minimum 5 characters) + # @default -- you MUST change this value + password: "ChangeMe123!" + # -- Set to 1 to make server visible publicly, 0 for private + public: 0 + # -- Timezone for the server + timezone: "UTC" + +secret: + name: "" + key: "server-password" + +# Automation configuration for the server +automation: + # -- Enable automatic updates (1=enabled, 0=disabled) + autoUpdate: 1 + # -- Cron schedule for automatic updates + autoUpdateSchedule: "0 1 * * *" + # -- Update server when container starts (1=enabled, 0=disabled) + updateOnStartup: 0 + # -- Enable automatic backups (1=enabled, 0=disabled) + autoBackup: 0 + # -- Cron schedule for automatic backups + autoBackupSchedule: "*/15 * * * *" + # -- Remove old backups automatically (1=enabled, 0=disabled) + autoBackupRemoveOld: 1 + # -- Number of days to keep backups + autoBackupDaysToLive: 7 + # -- Create backup before updates (1=enabled, 0=disabled) + autoBackupOnUpdate: 1 + # -- Create backup on server shutdown (1=enabled, 0=disabled) + autoBackupOnShutdown: 0 + +# Notification settings for server events +notifications: + # -- Discord webhook URL for server notifications + webhookUrl: "" + # -- Include the server's public IP in notifications (1=enabled, 0=disabled) + includePublicIp: 0 + +# Kubernetes service configuration +service: + # -- Service type + type: LoadBalancer + # -- Set specific load balancer IP (depends on cloud provider support) + loadBalancerIP: "" + # -- Annotations for the service + annotations: { } + # -- External source IP ranges allowed to access the server + loadBalancerSourceRanges: [ ] + +# Storage configuration for server data +persistence: + # -- Enable persistent storage for server data + enabled: true + # -- Storage class to use (use null for default or "" for no storage class) + # @default -- use default storage class + storageClass: null + + # Data volume configuration for game saves + saves: + # -- Size of PVC for game saves + size: 1Gi + # -- Access mode for the PVC + accessMode: ReadWriteOnce + # -- Existing claim to use (leave empty to create a new one) + existingClaim: "" + + # Data volume configuration for server files + server: + # -- Size of PVC for server files + size: 4Gi + # -- Access mode for the PVC + accessMode: ReadWriteOnce + # -- Existing claim to use (leave empty to create a new one) + existingClaim: "" + + # Data volume configuration for backups. Requires "autoBackup: 1". + backups: + # -- Size of PVC for backups + size: 10Gi + # -- Access mode for the PVC + accessMode: ReadWriteOnce + # -- Existing claim to use (leave empty to create a new one) + existingClaim: "" + +# -- Resource requests and limits +resources: { } + # We usually recommend not to specify default resources and to leave this as a conscious + # choice for the user. This also increases chances charts run on environments with little + # resources, such as Minikube. + # requests: + # # -- Memory request for the server + # memory: 2Gi + # # -- CPU request for the server + # cpu: 1000m + # # -- Resource limits + # limits: + # # -- Memory limit for the server +# memory: 4Gi +# # -- CPU limit for the server +# cpu: 2000m + +# -- Node selector for pod assignment +nodeSelector: { } + +# -- Tolerations for pod assignment +tolerations: [ ] + +# -- Affinity for pod assignment +affinity: { } + +# -- Additional environment variables for the Valheim server +extraEnv: [ ] +# - name: EXAMPLE_VAR +# value: "example value" + +# -- Init container configuration for server preparation +initContainers: + # -- Enable init container + enabled: false + # -- Init container image + image: busybox:latest + # -- Init container command + command: [ ] + # -- Init container arguments + args: [ ] + +# Modding configuration +modding: + # -- Enable BepInEx for mods (1=enabled, 0=disabled) + bepInEx: 0 + # -- Path to mounted mod directory + modPath: "/home/steam/valheim/BepInEx" + # -- Enable mounting a ConfigurationManager config + useConfigurationManager: false + +# Pod security context settings +# @descriptionStart +# Security context settings applied at the pod level. +# The fsGroup setting ensures that mounted volumes have the proper permissions for the Valheim user. +# @descriptionEnd +podSecurityContext: + # -- File system group ID for volume mounts + fsGroup: 1000 + +# Container security context settings +# @descriptionStart +# Security context settings applied at the container level. +# These settings ensure the container runs as a non-root user for better security. +# The user/group IDs must match those used in the container image. +# @descriptionEnd +securityContext: + # -- User ID to run the container processes. Should default to the steam user ID. + runAsUser: 111 + # -- Group ID to run the container processes + runAsGroup: 1000 + # -- Force the container to run as a non-root user + runAsNonRoot: true + +# Kubernetes startup probe configuration +startupProbe: + # -- Enable startup probe + enabled: true + # -- Initial delay seconds + initialDelaySeconds: 30 + # -- Period seconds + periodSeconds: 10 + # -- Timeout seconds + timeoutSeconds: 5 + # -- Failure threshold + # @default -- 30 (allows up to 5 minutes for initial startup) + failureThreshold: 30 + +# Kubernetes readiness probe configuration +readinessProbe: + # -- Enable readiness probe + enabled: true + # -- Initial delay seconds + initialDelaySeconds: 60 + # -- Period seconds + periodSeconds: 15 + # -- Timeout seconds + timeoutSeconds: 5 + # -- Failure threshold + # @default -- 20 (allows up to 5 minutes for readiness) + failureThreshold: 20 + +# Kubernetes liveness probe configuration +livenessProbe: + # -- Enable liveness probe + enabled: false + # -- Initial delay seconds + initialDelaySeconds: 60 + # -- Period seconds + periodSeconds: 20 + # -- Timeout seconds + timeoutSeconds: 5 + # -- Failure threshold + # @default -- 6 (allows up to 2 minutes for recovery) + failureThreshold: 6 diff --git a/k8s/services/valheim/sealedsecrets.yaml b/k8s/services/valheim/sealedsecrets.yaml new file mode 100644 index 0000000..ad59cb1 --- /dev/null +++ b/k8s/services/valheim/sealedsecrets.yaml @@ -0,0 +1,16 @@ +# yamllint disable rule:line-length +--- +apiVersion: bitnami.com/v1alpha1 +kind: SealedSecret +metadata: + creationTimestamp: null + name: valheim-secrets + namespace: apps-fuku +spec: + encryptedData: + server-password: AgBsm7Qg9ej7FtFh5twb4ALyL0I/fzVukURvFg17aweeDX7bM/9p/Yq7S2XG8gbqOYbC1GxknGMHQUnTXqXC9YZ4tZVUAptTCrAsPZHhHiet8bM39KCo2tGa5mCyC7lcmxae26cHuKj8Df6iMQCHL9ZH58A2SU8OIaszkonjwvSnbk6u7/HLCE8UyqP1JjXBMd4wx4BFDrhbauZr10f51tI55ksY+x44QQNrz84QEXmQ/dgwdzGAWqcPQTf57BebSI+ZKtUIvrMpNtz1ioqGnH3vWlb7QnqyqcyAYri3W3j8DB03EpfI2QjYi5Rs1NaJoO8L5HFdHW5p+rmttuwRxiEUPmURftH25o6Mgv/EcWGsB1TpyyFXM8JNU01lWJ+Wty316YF1BV3zHqdQeKu82R/wSv+iVm1dYKTfSOLe3YJr+aFnhYX3hCpBup1cB2KeOe/X9wTo2ETdvKhcIJPz8x7TRcXaCerVmVBw6LagmmdtMsCL4AIXw2gdkBeGONQmOzR1hDyTBAmpTv59WYzAJcCPZRE6gGxCPqH32G36E7WGEI4UOsjvT3GkVDnYx4FUDppzSP0ebnHZOwwAPFtXojHUaHg7ZTjZiuXDQa9Hkqt4mIOKa0i1HI0MyPu8eZJjoRXNS4j1yLfDCP2eSuhGjtVNbbyQthaITolitZ0VeUU8St1iKB7rvAGHqhBoPSw9TOBVSsBcHgIAV64oRqto4kM8 + template: + metadata: + creationTimestamp: null + name: valheim-secrets + namespace: apps-fuku