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!