𝔩𝔢𝔩𝕠𝔭𝔢𝔷
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