add: valheim

This commit is contained in:
2025-12-18 01:01:43 -08:00
parent 03aa9e69aa
commit 4e19949075
4 changed files with 342 additions and 17 deletions

View File

@@ -27,12 +27,12 @@
"state": { "state": {
"type": "markdown", "type": "markdown",
"state": { "state": {
"file": "README.md", "file": "valheim.md",
"mode": "source", "mode": "source",
"source": false "source": false
}, },
"icon": "lucide-file", "icon": "lucide-file",
"title": "README" "title": "valheim"
} }
} }
], ],
@@ -109,7 +109,7 @@
"state": { "state": {
"type": "backlink", "type": "backlink",
"state": { "state": {
"file": "README.md", "file": "valheim.md",
"collapseAll": false, "collapseAll": false,
"extraContext": false, "extraContext": false,
"sortOrder": "alphabetical", "sortOrder": "alphabetical",
@@ -119,7 +119,7 @@
"unlinkedCollapsed": true "unlinkedCollapsed": true
}, },
"icon": "links-coming-in", "icon": "links-coming-in",
"title": "Backlinks for README" "title": "Backlinks for valheim"
} }
}, },
{ {
@@ -128,12 +128,12 @@
"state": { "state": {
"type": "outgoing-link", "type": "outgoing-link",
"state": { "state": {
"file": "README.md", "file": "valheim.md",
"linksCollapsed": false, "linksCollapsed": false,
"unlinkedCollapsed": true "unlinkedCollapsed": true
}, },
"icon": "links-going-out", "icon": "links-going-out",
"title": "Outgoing links from README" "title": "Outgoing links from valheim"
} }
}, },
{ {
@@ -171,13 +171,13 @@
"state": { "state": {
"type": "outline", "type": "outline",
"state": { "state": {
"file": "README.md", "file": "valheim.md",
"followCursor": false, "followCursor": false,
"showSearch": false, "showSearch": false,
"searchQuery": "" "searchQuery": ""
}, },
"icon": "lucide-list", "icon": "lucide-list",
"title": "Outline of README" "title": "Outline of valheim"
} }
} }
] ]
@@ -201,8 +201,9 @@
"active": "1dd11189df0fe00f", "active": "1dd11189df0fe00f",
"lastOpenFiles": [ "lastOpenFiles": [
"infra.md", "infra.md",
"README.md", "valheim.md",
"rikidown.md", "rikidown.md",
"README.md",
"thoughts.md" "thoughts.md"
] ]
} }

View File

@@ -1,8 +1,6 @@
# Hello world! # Hello world!
It appears this does not support normal markdown, so this may be dropped awfully quick. Much sadness. This is powered by rikidown (see below); some previous text alluded a different software I was considering that ultimately got dropped because it was not using propert Markdown format. This seems to be working much better.
It seems to be simple and fast though, so I'm conflicted.
[infra.md](infra.md) [infra.md](infra.md)

View File

@@ -1,9 +1,23 @@
All of this is running on a Raspberry Pi 5 sitting in a closet. The Pi runs k3s, a lightweight Kubernetes implementation, and Tailscale to allow me to access resources when I'm away from home. I acquired a used server for a very reasonable cost; it has 80x3.0ghz ARM cores, 128 GiB of RAM, and uses 70w of power. Power where I live is super expensive, so I'm very excited to have this beast available for minimal power cost.
## FluxCD If you are interested in hosting anything, please reach out :). If I you don't know how to reach out, you probably aren't invited to reach out.
The cluster is managed by FluxCD. I describe my apps in kustomizations and plain YAML. I also have 5pi5, a Raspberry Pi 5 (16 GiB) that I use to host smaller applications.
## SSL ## Configuration
SSL certs are issues through letsencrypt. I've pointed my name cheap domain name to Google Clouds DNS servers, then setup cert-manager in the Kubernetes cluster to acquire SSL certificates using the DNS challenge method. This allows me to have valid SSL certs with no client side configuration, and without actually exposing my service to the Internet (which would be required for the standard HTML challenge). The very strong ARM machine (aka, machop) runs k3s. This allows me to store my configurations in FluxCD, kept in a Git repo. Very helpful in terms of my ability to work on one project a time, when tipsy.
As a bonus, those silly AI tools are *very* helpful when you are tipsy. You can just ask it to:
> add a new app to prod which uses the Docker image docker.tipsy.codes/rikidown:20251217.
> the app should include and ingress for wiki.tipsy.codes, and it should add the arguments '--git-repo https://git.tipsy.codes/charles/wiki.tipsy.codes.git'.
> the pod will expose port 8080, which should be wrapped in a service and used in the ingress
and it will do the thing. It did pretty good, overall.
The Git repo for my FluxCD configuration is not public because I'm not confident that I've correctly removed all private keys from it (notably, the keys to access the kubernetes dashboard). In principle it should still be fine because access to the k3s control plane is restricted to my local network, but all the same... I don't trust you.
# Projects
[Valheim](valheim.md)

312
valheim.md Normal file
View File

@@ -0,0 +1,312 @@
It turns out that you can run x86 applications on ARM machines, which is super cool. But it requires a bit of nonsense. Here is how I got the Valheim server to work.
## Dockerfile
I created a docker file like:
```
# Use Ubuntu 22.04 as base
FROM weilbyte/box:debian-11
RUN apt update && apt upgrade -y
RUN apt install -y curl libpulse-dev libatomic1 libc6
# Create user steam
RUN useradd -m steam
# Change user to steam
USER steam
# Go to /home/steam/Steam
WORKDIR /home/steam/Steam
# Download and extract SteamCMD
RUN curl -sqL "https://steamcdn-a.akamaihd.net/client/installer/steamcmd_linux.tar.gz" | tar zxvf -
RUN /usr/local/bin/box64 /home/steam/Steam/steamcmd.sh +force_install_dir /home/steam/Valheim +login anonymous +app_update 896660 validate +exit
WORKDIR /home/steam/Valheim
COPY start_server.sh /home/steam/Valheim
ENTRYPOINT ["/usr/local/bin/box64", "/home/steam/Valheim/start_server.sh"]
```
I built and pushed this image with:
```
docker build -t docker.tipsy.codes/valheim:20251214 .
```
## k3s config
To deploy this, I made added some files to my Flux repo. Here is a tree:
```
tree apps/prod/valheim
apps/prod/valheim
├── deployment.yaml
├── ingress.yaml
├── kustomization.yaml
├── namespace.yaml
├── pvc.yaml
├── pv.yaml
└── service.yaml
1 directory, 7 files
```
The most interesting files are:
```
find apps/prod/valheim/* -exec echo '# {}' \; -exec cat {} \;
# apps/prod/valheim/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
 name: valheim
 namespace: valheim
spec:
 replicas: 1
 selector:
   matchLabels:
     app: valheim
 template:
   metadata:
     labels:
       app: valheim
   spec:
     containers:
       - name: valheim
         image: docker.tipsy.codes/valheim:20251214
         ports:
           - containerPort: 2456
             protocol: UDP
           - containerPort: 2457
             protocol: UDP
           - containerPort: 9001
             protocol: TCP
           - containerPort: 80
             protocol: TCP
         volumeMounts:
           - name: valheim-data
             mountPath: /opt/valheim
           - name: valheim-config
             mountPath: /config
     volumes:
       - name: valheim-data
         persistentVolumeClaim:
           claimName: valheim-pvc
       - name: valheim-config
         persistentVolumeClaim:
           claimName: valheim-config-pvc
# apps/prod/valheim/ingress.yaml
apiVersion: traefik.io/v1alpha1
kind: IngressRouteUDP
metadata:
 name: valheim-udp1
spec:
 # By default, IngressRouteUDP listens to all UDP entry points if 'entryPoints' is not specified.
 entryPoints:
   - valheim-udp1
 routes:
   - services:
       - name: valheim
         port: 2456 # Replace with your service port
---
apiVersion: traefik.io/v1alpha1
kind: IngressRouteUDP
metadata:
 name: valheim-udp2
spec:
 # By default, IngressRouteUDP listens to all UDP entry points if 'entryPoints' is not specified.
 entryPoints:
   - valheim-udp2
 routes:
   - services:
       - name: valheim
         port: 2457 # Replace with your service port
---
apiVersion: traefik.io/v1alpha1
kind: IngressRouteTCP
metadata:
 name: valheim-tcp1
spec:
 # By default, IngressRouteUDP listens to all UDP entry points if 'entryPoints' is not specified.
 entryPoints:
   - valheim-tcp1
 routes:
   - match: HostSNI(`*`)
     services:
       - name: valheim
         port: 2456 # Replace with your service port
---
apiVersion: traefik.io/v1alpha1
kind: IngressRouteTCP
metadata:
 name: valheim-tcp2
spec:
 # By default, IngressRouteUDP listens to all UDP entry points if 'entryPoints' is not specified.
 entryPoints:
   - valheim-tcp2
 routes:
   - match: HostSNI(`*`)
     services:
       - name: valheim
         port: 2457 # Replace with your service port
# apps/prod/valheim/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
 - ./namespace.yaml
 - ./pvc.yaml
 - ./deployment.yaml
 - ./service.yaml
 - ./ingress.yaml
 - ./pv.yaml
patches:
 - patch: |
     - op: replace
       path: /metadata/namespace
       value: valheim
   target:
     name: ".*"
# apps/prod/valheim/namespace.yaml
apiVersion: v1
kind: Namespace
metadata:
 name: valheim
# apps/prod/valheim/pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
 name: valheim-pvc
 namespace: valheim
spec:
 storageClassName: local-path
 accessModes:
   - ReadWriteOnce
 resources:
   requests:
     storage: 100Gi
 volumeName: valheim-pv
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
 name: valheim-config-pvc
 namespace: valheim
spec:
 storageClassName: local-path
 accessModes:
   - ReadWriteOnce
 resources:
   requests:
     storage: 100Gi
 volumeName: valheim-config-pv
# apps/prod/valheim/pv.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
 name: valheim-pv
spec:
 capacity:
   storage: 100Gi
 volumeMode: Filesystem
 accessModes:
   - ReadWriteOnce
 persistentVolumeReclaimPolicy: Retain
 storageClassName: local-path
 claimRef:
   namespace: valheim
   name: valheim-pvc
 local:
   path: /var/lib/rancher/k3s/storage/valheim-pvc
 nodeAffinity:
   required:
     nodeSelectorTerms:
       - matchExpressions:
           - key: kubernetes.io/hostname
             operator: In
             values:
               - machop
---
apiVersion: v1
kind: PersistentVolume
metadata:
 name: valheim-config-pv
spec:
 capacity:
   storage: 100Gi
 volumeMode: Filesystem
 accessModes:
   - ReadWriteOnce
 persistentVolumeReclaimPolicy: Retain
 storageClassName: local-path
 claimRef:
   namespace: valheim
   name: valheim-config-pvc
 local:
   path: /var/lib/rancher/k3s/storage/valheim-config-pvc
 nodeAffinity:
   required:
     nodeSelectorTerms:
       - matchExpressions:
           - key: kubernetes.io/hostname
             operator: In
             values:
               - machop
# apps/prod/valheim/service.yaml
apiVersion: v1
kind: Service
metadata:
 name: valheim
 namespace: valheim
spec:
 selector:
   app: valheim
 ports:
   - name: udp-2456
     protocol: UDP
     port: 2456
     targetPort: 2456
   - name: udp-2457
     protocol: UDP
     port: 2457
     targetPort: 2457
   - name: tcp-2456
     protocol: TCP
     port: 2456
     targetPort: 2456
   - name: tcp-2457
     protocol: TCP
     port: 2457
     targetPort: 2457
```
I did have to make some changes to k3s configuration to open the correct ports:
```
charles@machop:~/p3/palworld-arm64$ sudo cat /var/lib/rancher/k3s/server/manifests/traefik-config.yaml
apiVersion: helm.cattle.io/v1
kind: HelmChartConfig
metadata:
 name: traefik
 namespace: kube-system
spec:
 valuesContent: |-
   ports:
     websecure:
       transport:
         respondingTimeouts:
           readTimeout: 180m
     valheim-udp1:
       port: 2456
       hostPort: 2456
       protocol: UDP
     valheim-udp2:
       port: 2457
       hostPort: 2457
       protocol: UDP
     valheim-tcp1:
       port: 2456
       hostPort: 2456
       protocol: TCP
     valheim-tcp2:
       port: 2457
       hostPort: 2457
       protocol: TCP
```
## Does it work?
Yeah, it seems to work. I had some trouble with crossplay, but I have no interest in playing with console peasants anyway.
Happy hunting!