Official Helm chart for deploying a Stardew Valley multiplayer dedicated server on Kubernetes.
helm repo add cabrera-evil https://cabrera-evil.github.io/charts/
helm install my-stardew cabrera-evil/stardew-valley-server \
--set gameServer.steamCredentials.username=YOUR_STEAM_USER \
--set gameServer.steamCredentials.password=YOUR_STEAM_PASS \
--set gameServer.vncPassword=YOUR_VNC_PASS
This chart deploys a Stardew Valley dedicated game server using the SDVD server image.
helm install my-stardew cabrera-evil/stardew-valley-server \
--set gameServer.steamCredentials.username=mysteamuser \
--set gameServer.steamCredentials.password=mysteampass \
--set gameServer.vncPassword=myvncpass
Create my-values.yaml:
gameServer:
steamCredentials:
username: "mysteamuser"
password: "mysteampass"
guardCode: "AB123" # If 2FA enabled
vncPassword: "secure-password"
service:
type: LoadBalancer
persistence:
gameData:
size: 20Gi # Increase if using mods
Install:
helm install my-stardew cabrera-evil/stardew-valley-server -f my-values.yaml
| Parameter | Description | Example |
|---|---|---|
gameServer.steamCredentials.username |
Steam account username | mysteamuser |
gameServer.steamCredentials.password |
Steam account password | mypassword |
| Parameter | Description | Default |
|---|---|---|
gameServer.steamCredentials.guardCode |
Steam Guard 2FA code | "" |
gameServer.vncPassword |
VNC access password | "" |
gameServer.disableRendering |
Disable graphics rendering | "true" |
gameServer.gamePort |
Game server port | 24642 |
| Parameter | Description | Default |
|---|---|---|
image.repository |
Container image repository | sdvd/server |
image.pullPolicy |
Image pull policy | IfNotPresent |
image.tag |
Image tag | "" (uses appVersion) |
| Parameter | Description | Default |
|---|---|---|
service.type |
Kubernetes service type | LoadBalancer |
service.gamePort |
Service port | 24642 |
service.protocol |
Service protocol | UDP |
service.nodePort |
NodePort if service type is NodePort | "" (auto) |
service.externalTrafficPolicy |
External traffic policy | Local |
service.annotations |
Service annotations | {} |
| Parameter | Description | Default |
|---|---|---|
persistence.gameData.enabled |
Enable game data persistence | true |
persistence.gameData.size |
Size of game data PVC | 10Gi |
persistence.gameData.storageClass |
Storage class | "" (default) |
persistence.gameData.accessMode |
Access mode | ReadWriteOnce |
persistence.gameData.annotations |
PVC annotations | {} |
persistence.serverConfig.enabled |
Enable config persistence | true |
persistence.serverConfig.size |
Size of config PVC | 1Gi |
persistence.serverConfig.storageClass |
Storage class | "" (default) |
persistence.serverConfig.accessMode |
Access mode | ReadWriteOnce |
persistence.serverConfig.annotations |
PVC annotations | {} |
| Parameter | Description | Default |
|---|---|---|
resources.requests.memory |
Memory request | 2Gi |
resources.requests.cpu |
CPU request | 1000m |
resources.limits.memory |
Memory limit | 4Gi |
resources.limits.cpu |
CPU limit | 2000m |
| Parameter | Description | Default |
|---|---|---|
livenessProbe.enabled |
Enable liveness probe | true |
livenessProbe.initialDelaySeconds |
Initial delay | 60 |
livenessProbe.periodSeconds |
Check period | 30 |
readinessProbe.enabled |
Enable readiness probe | true |
readinessProbe.initialDelaySeconds |
Initial delay | 30 |
startupProbe.enabled |
Enable startup probe | true |
startupProbe.failureThreshold |
Startup failures allowed | 30 |
| Parameter | Description | Default |
|---|---|---|
podSecurityContext.fsGroup |
Pod filesystem group | 1000 |
securityContext.runAsUser |
Container user ID | 1000 |
securityContext.runAsGroup |
Container group ID | 1000 |
securityContext.runAsNonRoot |
Run as non-root | true |
securityContext.readOnlyRootFilesystem |
Read-only root filesystem | false |
service:
type: LoadBalancer
annotations:
# AWS
service.beta.kubernetes.io/aws-load-balancer-type: "nlb"
# Azure
service.beta.kubernetes.io/azure-load-balancer-protocol: "UDP"
# GCP automatically supports UDP
persistence:
gameData:
storageClass: "gp3" # AWS gp3, or fast-ssd for GCP
size: 20Gi
serverConfig:
storageClass: "gp3"
service:
type: NodePort
nodePort: 30642 # Fixed port for firewall rules
persistence:
gameData:
storageClass: "local-path" # or your local storage class
size: 20Gi
resources:
requests:
memory: "4Gi"
cpu: "2000m"
limits:
memory: "8Gi"
cpu: "4000m"
persistence:
gameData:
storageClass: "fast-ssd"
size: 50Gi
nodeSelector:
disktype: ssd
Deploy multiple independent servers:
helm install stardew-farm1 cabrera-evil/stardew-valley-server -f farm1-values.yaml
helm install stardew-farm2 cabrera-evil/stardew-valley-server -f farm2-values.yaml
Each server gets its own PVCs and service endpoint.
helm repo update
helm upgrade my-stardew cabrera-evil/stardew-valley-server -f my-values.yaml
helm upgrade my-stardew cabrera-evil/stardew-valley-server \
--set image.tag=new-version \
--reuse-values
# Get pod name
POD_NAME=$(kubectl get pod -n default -l app.kubernetes.io/name=stardew-valley-server -o jsonpath='{.items[0].metadata.name}')
# Backup game data
kubectl cp default/$POD_NAME:/data/Stardew ./backup-$(date +%Y%m%d)
# Backup server config
kubectl cp default/$POD_NAME:/config/xdg/config/StardewValley ./backup-config-$(date +%Y%m%d)
# Copy backup to pod
kubectl cp ./backup-20240101 default/$POD_NAME:/data/Stardew
# Restart server
kubectl rollout restart deployment/my-stardew
Tag PVCs for automatic backup:
persistence:
gameData:
annotations:
backup.velero.io/backup-volumes: game-data
serverConfig:
annotations:
backup.velero.io/backup-volumes: server-config
kubectl logs deployment/my-stardew | grep -i steam
Verify Steam Guard code (expires after ~30 seconds)
Ensure Steam account owns Stardew Valley
kubectl describe pod -l app.kubernetes.io/name=stardew-valley-server
kubectl get svc my-stardew
Check firewall allows UDP port 24642
Verify client game version matches server
nc -uz <SERVER_IP> 24642
resources:
limits:
memory: "8Gi"
cpu: "4000m"
gameServer:
disableRendering: "true"
kubectl top nodes
kubectl top pods
kubectl get pvc
kubectl get storageclass
kubectl describe pvc my-stardew-game-data
helm uninstall my-stardew
WARNING: This does NOT delete PVCs by default. To completely remove all data:
# Delete PVCs
kubectl delete pvc -l app.kubernetes.io/instance=my-stardew
# Or delete specific PVCs
kubectl delete pvc my-stardew-game-data my-stardew-server-config
With External Secrets Operator:
# Don't set credentials in values
gameServer:
steamCredentials:
username: "" # Will be injected by ExternalSecret
password: ""
# Create ExternalSecret separately
Add init containers for mod installation or world setup (modify deployment manually or use Helm post-renderer).
For more advanced scenarios, consider converting to StatefulSet (requires manual customization).
This chart is licensed under the MIT License.
Contributions are welcome! Please open an issue or pull request at the GitHub repository.