𝔩𝔢𝔩𝕠𝔭𝔢𝔷
Theme
Connect With Me on LinkedIn Buy Me a Coffee

Homelab

Factorio Kubernetes Server

Running a Factorio Dedicated Server on Kubernetes with Tailscale

Overview

This article deploys a Factorio dedicated server on Kubernetes with persistent world saves and private access via Tailscale. Friends on your tailnet can join directly using the LoadBalancer IP, providing a LAN-like multiplayer experience without exposing the server to the public internet.

Tip:Having trouble? See v0.11.0 for what your setup should look like after completing this article.

Before You Begin

Prerequisites

Create Factorio Manifests

Using the SQLJames factorio-server-charts Helm chart1 with the factoriotools Docker image2. The image tag must match your Factorio client version3 - check available tags4 on Docker Hub.

Init Workspace

cd ~/homelab
export KUBECONFIG=$(pwd)/talos/clusterconfig/kubeconfig
mkdir -p k8s/apps/factorio
git checkout -b dev

Namespace

k8s/apps/factorio/namespace.yaml:

---
apiVersion: v1
kind: Namespace
metadata:
  name: factorio

PersistentVolumeClaim

Persistent storage for world saves and mods.

k8s/apps/factorio/pvc.yaml:

---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: factorio-data
  namespace: factorio
spec:
  accessModes:
    - ReadWriteOnce
  storageClassName: longhorn
  resources:
    requests:
      storage: 10Gi

HelmRelease

k8s/apps/factorio/helmrelease.yaml:

---
apiVersion: source.toolkit.fluxcd.io/v1
kind: HelmRepository
metadata:
  name: factorio
  namespace: factorio
spec:
  interval: 24h
  url: https://sqljames.github.io/factorio-server-charts
---
apiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
metadata:
  name: factorio
  namespace: factorio
spec:
  interval: 30m
  chart:
    spec:
      chart: factorio-server-charts
      sourceRef:
        kind: HelmRepository
        name: factorio
  install:
    remediation:
      retries: 3
  upgrade:
    remediation:
      retries: 3
  values:
    # Image version - MUST match client version
    # Check your Factorio client version: Main Menu → About
    # Available tags: https://hub.docker.com/r/factoriotools/factorio/tags
    image:
      tag: '2.0.72'
      pullPolicy: IfNotPresent

    # Disable hostNetwork - using LoadBalancer instead
    # Required for PodSecurity "baseline" compliance
    hostNetworkEnabled: false

    # Service - MetalLB assigns IP for Tailscale access
    service:
      type: LoadBalancer
      port: 34197

    # Persistence - use our PVC for larger storage
    persistence:
      enabled: true
      dataDir:
        existingClaim: factorio-data

    # Save configuration
    # - save_name: which save file to create/load
    # - generate_new_save: create if doesn't exist
    # - load_latest_save: false = always load save_name (not most recent)
    factorioServer:
      save_name: <your-world-name>
      generate_new_save: true
      load_latest_save: false

    # Server settings
    server_settings:
      name: 'Openlandmark'
      description: 'Experience is merely the name men gave to their mistakes.'
      visibility:
        public: false
        lan: true
      max_players: 0 # 0 = unlimited
      auto_pause: true
      only_admins_can_pause_the_game: true

    # Map seed for reproducible maps
    map_gen_settings:
      seed: 1853500214

    # Admin players (your Factorio username)
    admin_list:
      - <your-username>

    # Resource limits (Factorio is CPU-bound, needs decent RAM)
    resources:
      requests:
        memory: 2Gi
        cpu: 1000m
      limits:
        memory: 4Gi
        cpu: 2000m

Kustomization

k8s/apps/factorio/kustomization.yaml:

---
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
  - namespace.yaml
  - pvc.yaml
  - helmrelease.yaml

Apps Kustomization

Add factorio to k8s/apps/kustomization.yaml:

---
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
  - plex
  - factorio

Deploy Factorio

Commit Changes

cd ~/homelab

git add k8s/apps/factorio/ k8s/apps/kustomization.yaml
git commit -m "feat(factorio): add Factorio server"

git checkout main
git merge --ff-only dev
git push

Reconcile Flux

flux reconcile source git flux-system && flux reconcile kustomization sync

Verify Factorio

Deployment Status

# Check HelmRelease status
flux get helmreleases -n factorio

# Check pod is running
kubectl get pods -n factorio

# Check service has LoadBalancer IP
kubectl get svc -n factorio

# View logs
kubectl logs -n factorio -l app=factorio-factorio-server-charts -f

Wait for the pod to be Running and the service to have an EXTERNAL-IP.

Tailscale Access

Get the LoadBalancer IP:

kubectl get svc -n factorio -o jsonpath='{.items[0].status.loadBalancer.ingress[0].ip}'

Connect:

  1. Ensure your device is connected to Tailscale
  2. Open Factorio → Multiplayer → Connect to server
  3. Enter: <EXTERNAL-IP>:34197

Next Steps

With Factorio running via Tailscale, deploy more game servers.

See: Minecraft Paper Server

For optional Factorio enhancements:

Resources

Footnotes

  1. SQLJames, "Factorio Server Charts," github.com. Accessed: Dec. 22, 2025. [Online]. Available: https://github.com/SQLJames/factorio-server-charts

  2. factoriotools, "Factorio Docker Image," github.com. Accessed: Dec. 22, 2025. [Online]. Available: https://github.com/factoriotools/factorio-docker

  3. Wube Software, "Factorio Download," factorio.com. Accessed: Dec. 22, 2025. [Online]. Available: https://factorio.com/download

  4. factoriotools, "Docker Image Tags," hub.docker.com. Accessed: Dec. 22, 2025. [Online]. Available: https://hub.docker.com/r/factoriotools/factorio/tags

Previous
Plex Intel GPU Transcoding