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
- MetalLB, Longhorn, and Ingress-NGINX completed
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:
- Ensure your device is connected to Tailscale
- Open Factorio → Multiplayer → Connect to server
- Enter:
<EXTERNAL-IP>:34197
Next Steps
With Factorio running via Tailscale, deploy more game servers.
For optional Factorio enhancements:
- Add playit.gg for public access
- Import an existing save
- Enable security hardening
- Server management commands
Resources
Footnotes
SQLJames, "Factorio Server Charts," github.com. Accessed: Dec. 22, 2025. [Online]. Available: https://github.com/SQLJames/factorio-server-charts ↩
factoriotools, "Factorio Docker Image," github.com. Accessed: Dec. 22, 2025. [Online]. Available: https://github.com/factoriotools/factorio-docker ↩
Wube Software, "Factorio Download," factorio.com. Accessed: Dec. 22, 2025. [Online]. Available: https://factorio.com/download ↩
factoriotools, "Docker Image Tags," hub.docker.com. Accessed: Dec. 22, 2025. [Online]. Available: https://hub.docker.com/r/factoriotools/factorio/tags ↩