𝔩𝔢𝔩𝕠𝔭𝔢𝔷
Theme

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