diff --git a/factorio/kustomization.yaml b/factorio/kustomization.yaml new file mode 100644 index 0000000..4db2860 --- /dev/null +++ b/factorio/kustomization.yaml @@ -0,0 +1,7 @@ +--- +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization + +resources: + - main.yaml + - svc.yaml \ No newline at end of file diff --git a/factorio/main.yaml b/factorio/main.yaml new file mode 100644 index 0000000..ea93d84 --- /dev/null +++ b/factorio/main.yaml @@ -0,0 +1,371 @@ +apiVersion: v1 +data: + map-gen-settings.json: | + { + "autoplace_controls": { + "coal": { + "frequency": 1, + "richness": 1, + "size": 1 + }, + "copper-ore": { + "frequency": 1, + "richness": 1, + "size": 1 + }, + "crude-oil": { + "frequency": 1, + "richness": 1, + "size": 1 + }, + "enemy-base": { + "frequency": 1, + "richness": 1, + "size": 1 + }, + "iron-ore": { + "frequency": 1, + "richness": 1, + "size": 1 + }, + "stone": { + "frequency": 1, + "richness": 1, + "size": 1 + }, + "trees": { + "frequency": 1, + "richness": 1, + "size": 1 + }, + "uranium-ore": { + "frequency": 1, + "richness": 1, + "size": 1 + } + }, + "cliff_settings": { + "cliff_elevation_0": 10, + "cliff_elevation_interval": 40, + "name": "cliff", + "richness": 1 + }, + "height": 0, + "peaceful_mode": false, + "property_expression_names": { + "control-setting:aux:bias": "0", + "control-setting:aux:frequency:multiplier": "1", + "control-setting:moisture:bias": "0", + "control-setting:moisture:frequency:multiplier": "1" + }, + "starting_area": 1, + "starting_points": [ + { + "x": 0, + "y": 0 + } + ], + "terrain_segmentation": 1, + "water": 1, + "width": 0 + } + map-settings.json: | + { + "difficulty_settings": { + "recipe_difficulty": 0, + "research_queue_setting": "after-victory", + "technology_difficulty": 0, + "technology_price_multiplier": 1 + }, + "enemy_evolution": { + "destroy_factor": 0.002, + "enabled": true, + "pollution_factor": 9e-7, + "time_factor": 0.000004 + }, + "enemy_expansion": { + "building_coefficient": 0.1, + "enabled": true, + "enemy_building_influence_radius": 2, + "friendly_base_influence_radius": 2, + "max_colliding_tiles_coefficient": 0.9, + "max_expansion_cooldown": 216000, + "max_expansion_distance": 7, + "min_base_spacing": 3, + "min_expansion_cooldown": 14400, + "neighbouring_base_chunk_coefficient": 0.4, + "neighbouring_chunk_coefficient": 0.5, + "other_base_coefficient": 2, + "settler_group_max_size": 20, + "settler_group_min_size": 5 + }, + "max_failed_behavior_count": 3, + "path_finder": { + "cache_accept_path_end_distance_ratio": 0.15, + "cache_accept_path_start_distance_ratio": 0.2, + "cache_max_connect_to_cache_steps_multiplier": 100, + "cache_path_end_distance_rating_multiplier": 20, + "cache_path_start_distance_rating_multiplier": 10, + "direct_distance_to_consider_short_request": 100, + "enemy_with_different_destination_collision_penalty": 30, + "extended_collision_penalty": 3, + "fwd2bwd_ratio": 5, + "general_entity_collision_penalty": 10, + "general_entity_subsequent_collision_penalty": 3, + "goal_pressure_ratio": 2, + "ignore_moving_enemy_collision_distance": 5, + "long_cache_min_cacheable_distance": 30, + "long_cache_size": 25, + "max_clients_to_accept_any_new_request": 10, + "max_clients_to_accept_short_new_request": 100, + "max_steps_worked_per_tick": 100, + "max_work_done_per_tick": 8000, + "min_steps_to_check_path_find_termination": 2000, + "negative_cache_accept_path_end_distance_ratio": 0.3, + "negative_cache_accept_path_start_distance_ratio": 0.3, + "negative_path_cache_delay_interval": 20, + "overload_levels": [ + 0, + 100, + 500 + ], + "overload_multipliers": [ + 2, + 3, + 4 + ], + "short_cache_min_algo_steps_to_cache": 50, + "short_cache_min_cacheable_distance": 10, + "short_cache_size": 5, + "short_request_max_steps": 1000, + "short_request_ratio": 0.5, + "stale_enemy_with_same_destination_collision_penalty": 30, + "start_to_goal_cost_multiplier_to_terminate_path_find": 500, + "use_path_cache": true + }, + "pollution": { + "ageing": 1, + "diffusion_ratio": 0.02, + "enabled": true, + "enemy_attack_pollution_consumption_modifier": 1, + "expected_max_per_chunk": 150, + "max_pollution_to_restore_trees": 20, + "min_pollution_to_damage_trees": 60, + "min_to_diffuse": 15, + "min_to_show_per_chunk": 50, + "pollution_per_tree_damage": 50, + "pollution_restored_per_tree_damage": 10, + "pollution_with_max_forest_damage": 150 + }, + "steering": { + "default": { + "force_unit_fuzzy_goto_behavior": false, + "radius": 1.2, + "separation_factor": 1.2, + "separation_force": 0.005 + }, + "moving": { + "force_unit_fuzzy_goto_behavior": false, + "radius": 3, + "separation_factor": 3, + "separation_force": 0.01 + } + }, + "unit_group": { + "max_gathering_unit_groups": 30, + "max_group_gathering_time": 36000, + "max_group_member_fallback_factor": 3, + "max_group_radius": 30, + "max_group_slowdown_factor": 0.3, + "max_member_slowdown_when_ahead": 0.6, + "max_member_speedup_when_behind": 1.4, + "max_unit_group_size": 200, + "max_wait_time_for_late_members": 7200, + "member_disown_distance": 10, + "min_group_gathering_time": 3600, + "min_group_radius": 5, + "tick_tolerance_when_member_arrives": 60 + } + } + rconpw: | + replaceme + server-adminlist.json: | + [ + "Urrrk", + "Wendy" + ] + server-settings.json: | + { + "afk_autokick_interval": 0, + "allow_commands": "admins-only", + "auto_pause": true, + "auto_pause_when_players_connect": false, + "autosave_interval": 10, + "autosave_only_on_server": true, + "autosave_slots": 5, + "description": "Factorio running on Kubernetes", + "game_password": "", + "ignore_player_limit_for_returning_players": false, + "max_heartbeats_per_second": 60, + "max_players": 0, + "max_upload_in_kilobytes_per_second": 0, + "max_upload_slots": 5, + "maximum_segment_size": 100, + "maximum_segment_size_peer_count": 10, + "minimum_latency_in_ticks": 0, + "minimum_segment_size": 25, + "minimum_segment_size_peer_count": 20, + "name": "Factorio", + "non_blocking_saving": false, + "only_admins_can_pause_the_game": true, + "password": "", + "require_user_verification": false, + "tags": [ + "game", + "tags" + ], + "token": "", + "username": "", + "visibility": { + "lan": true, + "public": false + } + } +kind: ConfigMap +metadata: + labels: + app.kubernetes.io/instance: factorio + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: factorio + app.kubernetes.io/version: stable + helm.sh/chart: factorio-1.2.2 + name: factorio-settings +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + labels: + app.kubernetes.io/instance: factorio + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: factorio + app.kubernetes.io/version: stable + helm.sh/chart: factorio-1.2.2 + name: factorio-config +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 1Gi + storageClassName: openebs-3-replicas +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + app.kubernetes.io/instance: factorio + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: factorio + app.kubernetes.io/version: stable + helm.sh/chart: factorio-1.2.2 + name: factorio +spec: + replicas: 1 + revisionHistoryLimit: 3 + selector: + matchLabels: + app.kubernetes.io/instance: factorio + app.kubernetes.io/name: factorio + strategy: + type: Recreate + template: + metadata: + labels: + app.kubernetes.io/instance: factorio + app.kubernetes.io/name: factorio + spec: + automountServiceAccountToken: true + containers: + - env: + - name: GENERATE_NEW_SAVE + value: "false" + - name: LOAD_LATEST_SAVE + value: "true" + - name: PORT + value: "34197" + - name: RCON_PORT + value: "27015" + - name: SAVE_NAME + value: _autosave1 + - name: TOKEN + value: "" + - name: TZ + value: UTC + - name: UPDATE_MODS_ON_START + value: "false" + - name: USERNAME + value: "" + image: factoriotools/factorio:2.0.43 + imagePullPolicy: IfNotPresent + livenessProbe: + failureThreshold: 3 + initialDelaySeconds: 0 + periodSeconds: 10 + tcpSocket: + port: 27015 + timeoutSeconds: 1 + name: factorio + ports: + - containerPort: 27015 + name: rcon + protocol: TCP + - containerPort: 34197 + name: server + protocol: UDP + readinessProbe: + failureThreshold: 3 + initialDelaySeconds: 0 + periodSeconds: 10 + tcpSocket: + port: 27015 + timeoutSeconds: 1 + startupProbe: + failureThreshold: 30 + initialDelaySeconds: 0 + periodSeconds: 5 + tcpSocket: + port: 27015 + timeoutSeconds: 1 + volumeMounts: + - mountPath: /factorio + name: config + - mountPath: /helmconfig/map_settings.json + name: factorio-config + subPath: map_settings.json + dnsPolicy: ClusterFirst + enableServiceLinks: true + initContainers: + - command: + - sh + - -c + - | + mkdir -p /factorio/config + cp -vL /helmconfig/* /factorio/config/ + image: busybox + imagePullPolicy: IfNotPresent + name: copy-configmap + securityContext: + runAsUser: 0 + volumeMounts: + - mountPath: /helmconfig/ + name: factorio-config + - mountPath: /factorio/ + name: config + serviceAccountName: default + volumes: + - name: config + persistentVolumeClaim: + claimName: factorio-config + - configMap: + name: factorio-settings + name: factorio-config diff --git a/factorio/src/kustomization.yaml b/factorio/src/kustomization.yaml new file mode 100644 index 0000000..3c4766f --- /dev/null +++ b/factorio/src/kustomization.yaml @@ -0,0 +1,12 @@ +--- +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization + +helmCharts: + - name: factorio + repo: https://k8s-at-home.com/charts/ + version: 1.2.2 + releaseName: factorio + includeCRDs: true + namespace: factorio + valuesFile: values.yaml diff --git a/factorio/src/values.yaml b/factorio/src/values.yaml new file mode 100644 index 0000000..44c8394 --- /dev/null +++ b/factorio/src/values.yaml @@ -0,0 +1,378 @@ +# +# IMPORTANT NOTE +# +# This chart inherits from our common library chart. You can check the default values/options here: +# https://github.com/k8s-at-home/library-charts/tree/main/charts/stable/common/values.yaml +# + +image: + # -- image repository + repository: factoriotools/factorio + # -- image tag + # @default -- chart.appVersion + tag: 2.0.43 + # -- image pull policy + pullPolicy: IfNotPresent + +initContainers: + # -- Configures an initContainer that copies the configmap to the factorio conf directory + # @default -- See values.yaml + copy-configmap: + image: busybox + imagePullPolicy: IfNotPresent + command: + - "sh" + - "-c" + - | + mkdir -p /factorio/config + cp -vL /helmconfig/* /factorio/config/ + volumeMounts: + - name: factorio-config + mountPath: /helmconfig/ + - name: config + mountPath: /factorio/ + securityContext: + runAsUser: 0 + +# -- environment variables. See more environment variables in the [factorio documentation](https://factorio.org/docs). +# @default -- See below +env: + # -- Set the container timezone + TZ: UTC + # -- Generate a new save if one does not exist before starting the server + GENERATE_NEW_SAVE: "{{ .Values.config.factorioServer.generate_new_save }}" + # -- Load latest when true. Otherwise load SAVE_NAME + LOAD_LATEST_SAVE: "{{ .Values.config.factorioServer.load_latest_save }}" + # -- UDP port the server listens on + PORT: "{{ .Values.service.main.ports.server.port }}" + # -- TCP port the rcon server listens on + RCON_PORT: "{{ .Values.service.main.ports.rcon.port }}" + # -- Name to use for the save file + SAVE_NAME: "{{ .Values.config.factorioServer.save_name }}" + # -- factorio.com token + TOKEN: "{{ .Values.config.factorioServer.token }}" + # -- If mods should be updated befoqre starting the server + UPDATE_MODS_ON_START: "{{ .Values.config.factorioServer.update_mods_on_start }}" + # -- factorio.com username + USERNAME: "{{ .Values.config.factorioServer.username }}" + +# -- Configures service settings for the chart. +# @default -- See values.yaml +service: + main: + ports: + http: + enabled: false + primary: false + server: + enabled: true + port: 34197 + protocol: UDP + rcon: + enabled: true + primary: true + port: 27015 + protocol: TCP + +ingress: + # -- Enable and configure ingress settings for the chart under this key. + # @default -- See values.yaml + main: + enabled: false + +# -- Configure persistence settings for the chart under this key. +# @default -- See values.yaml +persistence: + config: + enabled: true + mountPath: /factorio + accessMode: ReadWriteOnce + storageClass: openebs-3-replicas + size: 1Gi + +# -- Configure server settings. Can be disabled if you wish to configure in the container in the json config files. +# -- See values.yaml for descriptions for many config options, ore refer to https://wiki.factorio.com/Multiplayer. +# @default -- See values.yaml +config: + factorioServer: + # -- name to be used for save + save_name: "_autosave1" + # -- Generate a New Save + generate_new_save: false + # -- Update mods on start + update_mods_on_start: false + # -- lets the game know if you want to load the latest save + load_latest_save: true + # -- factorio.com token + token: + # -- factorio.com password + username: + + server_settings: + # -- Your Instance Name + name: Factorio + # -- Your Instance Description + description: "Factorio running on Kubernetes" + tags: + - game + - tags + # -- Maximum number of players allowed, admins can join even a full server. 0 means unlimited. + max_players: 0 + # -- Game visibility + visibility: + # -- Game will be published on the official Factorio matching server + public: false + # -- Game will be broadcast on LAN + lan: true + # -- Your factorio.com login credentials. Required for games with visibility public + username: "" + password: "" + # -- Authentication token. May be used instead of password above. + token: "" + # -- password required to log into the factorio server + game_password: "" + # -- When set to true, the server will only allow clients that have a valid Factorio.com account + require_user_verification: false + # -- optional, default value is 0. 0 means unlimited. + max_upload_in_kilobytes_per_second: 0 + # -- optional, default value is 5. 0 means unlimited. + max_upload_slots: 5 + # -- optional one tick is 16ms in default speed, default value is 0. 0 means no minimum. + minimum_latency_in_ticks: 0 + max_heartbeats_per_second: 60 + # -- Players that played on this map already can join even when the max player limit was reached. + ignore_player_limit_for_returning_players: false + # -- possible values are, true, false and admins-only + allow_commands: admins-only + # -- Autosave interval in minutes + autosave_interval: 10 + # -- server autosave slots, it is cycled through when the server autosaves. + autosave_slots: 5 + # -- How many minutes until someone is kicked when doing nothing, 0 for never. + afk_autokick_interval: 0 + # -- Whether should the server be paused when no players are present. + auto_pause: true + auto_pause_when_players_connect: false + # -- specifies if anyone can pause or only admins + only_admins_can_pause_the_game: true + # -- Whether autosaves should be saved only on server or also on all connected clients. Default is true. + autosave_only_on_server: true + # -- Highly experimental feature, enable only at your own + # -- risk of losing your saves. On UNIX systems, server will fork itself to create an + # -- autosave. Autosaving on connected Windows clients will be disabled regardless of + # -- autosave_only_on_server option. + non_blocking_saving: false + # -- Long network messages are split into segments that are sent + # -- over multiple ticks. Their size depends on the number of peers currently connected. + # -- Increasing the segment size will increase upload bandwidth requirement for the server + # -- and download bandwidth requirement for clients. This setting only affects server + # -- outbound messages. Changing these settings can have a negative impact on connection + # -- stability for some clients. + minimum_segment_size: 25 + minimum_segment_size_peer_count: 20 + maximum_segment_size: 100 + maximum_segment_size_peer_count: 10 + + # -- Password and port for the rcon service + rcon: + external: true + type: LoadBalancer + password: "replaceme" + port: 30100 + + map_gen_settings: + # --The inverse of water scale in the map generator GUI. + terrain_segmentation: 1 + # -- The equivalent to water coverage in the map generator GUI. Higher coverage means + # -- more water in larger oceans. + # -- Water level = 10 * log2(this value) + water: 1 + # -- Width and height of map, in tiles; 0 means infinite + width: 0 + # -- Width and height of map, in tiles; 0 means infinite + height: 0 + # -- Multiplier for biter free zone radius + starting_area: 1 + peaceful_mode: false + autoplace_controls: + coal: + frequency: 1 + size: 1 + richness: 1 + stone: + frequency: 1 + size: 1 + richness: 1 + copper-ore: + frequency: 1 + size: 1 + richness: 1 + iron-ore: + frequency: 1 + size: 1 + richness: 1 + uranium-ore: + frequency: 1 + size: 1 + richness: 1 + crude-oil: + frequency: 1 + size: 1 + richness: 1 + trees: + frequency: 1 + size: 1 + richness: 1 + enemy-base: + frequency: 1 + size: 1 + richness: 1 + cliff_settings: + # -- Name of the cliff prototype + name: cliff + # -- Elevation of first row of cliffs + cliff_elevation_0: 10 + # -- Elevation difference between successive rows of cliffs. + # -- This is inversely proportional to frequency in the map generation GUI. Specifically, when set from the GUI the value is 40 / frequency. + cliff_elevation_interval: 40 + # -- Called cliff continuity in the map generator GUI. 0 will result in no cliffs, 10 will make all cliff rows completely solid + richness: 1 + # -- Overrides for property value generators (map type) + # -- Leave elevation blank to get normal terrain. + # -- Use ''elevation'': ''0_16-elevation'' to reproduce terrain from 0.16. + # -- Use ''elevation'': ''0_17-island'' to get an island. + # -- Moisture and terrain type are also controlled via this. + # -- "control-setting:moisture:frequency:multiplier is the inverse of the moisture scale in the map generator GUI." + # -- "control-setting:moisture:bias is the moisture bias in the map generator GUI." + # -- "control-setting:aux:frequency:multiplier is the inverse of the terrain type scale in the map generator GUI." + # -- "control-setting:aux:bias is the teraain type bias in the map generator GUI." + property_expression_names: + control-setting:moisture:frequency:multiplier: "1" + control-setting:moisture:bias: "0" + control-setting:aux:frequency:multiplier: "1" + control-setting:aux:bias: "0" + starting_points: + - "x": 0 + "y": 0 + # -- Use null for a random seed, number for a specific seed. + seed: null + + map_settings: + difficulty_settings: + recipe_difficulty: 0 + technology_difficulty: 0 + technology_price_multiplier: 1 + research_queue_setting: after-victory + pollution: + enabled: true + # -- these are values for 60 ticks (1 simulated second) + # -- amount that is diffused to neighboring chunk + diffusion_ratio: 0.02 + min_to_diffuse: 15 + ageing: 1 + expected_max_per_chunk: 150 + min_to_show_per_chunk: 50 + min_pollution_to_damage_trees: 60 + pollution_with_max_forest_damage: 150 + pollution_per_tree_damage: 50 + pollution_restored_per_tree_damage: 10 + max_pollution_to_restore_trees: 20 + enemy_attack_pollution_consumption_modifier: 1 + enemy_evolution: + enabled: true + time_factor: 0.000004 + destroy_factor: 0.002 + pollution_factor: 0.0000009 + enemy_expansion: + enabled: true + min_base_spacing: 3 + max_expansion_distance: 7 + friendly_base_influence_radius: 2 + enemy_building_influence_radius: 2 + building_coefficient: 0.1 + other_base_coefficient: 2 + neighbouring_chunk_coefficient: 0.5 + neighbouring_base_chunk_coefficient: 0.4 + max_colliding_tiles_coefficient: 0.9 + settler_group_min_size: 5 + settler_group_max_size: 20 + min_expansion_cooldown: 14400 + max_expansion_cooldown: 216000 + unit_group: + min_group_gathering_time: 3600 + max_group_gathering_time: 36000 + max_wait_time_for_late_members: 7200 + max_group_radius: 30 + min_group_radius: 5 + max_member_speedup_when_behind: 1.4 + max_member_slowdown_when_ahead: 0.6 + max_group_slowdown_factor: 0.3 + max_group_member_fallback_factor: 3 + member_disown_distance: 10 + tick_tolerance_when_member_arrives: 60 + max_gathering_unit_groups: 30 + max_unit_group_size: 200 + steering: + default: + radius: 1.2 + separation_force: 0.005 + separation_factor: 1.2 + force_unit_fuzzy_goto_behavior: false + moving: + radius: 3 + separation_force: 0.01 + separation_factor: 3 + force_unit_fuzzy_goto_behavior: false + path_finder: + fwd2bwd_ratio: 5 + goal_pressure_ratio: 2 + max_steps_worked_per_tick: 100 + max_work_done_per_tick: 8000 + use_path_cache: true + short_cache_size: 5 + long_cache_size: 25 + short_cache_min_cacheable_distance: 10 + short_cache_min_algo_steps_to_cache: 50 + long_cache_min_cacheable_distance: 30 + cache_max_connect_to_cache_steps_multiplier: 100 + cache_accept_path_start_distance_ratio: 0.2 + cache_accept_path_end_distance_ratio: 0.15 + negative_cache_accept_path_start_distance_ratio: 0.3 + negative_cache_accept_path_end_distance_ratio: 0.3 + cache_path_start_distance_rating_multiplier: 10 + cache_path_end_distance_rating_multiplier: 20 + stale_enemy_with_same_destination_collision_penalty: 30 + ignore_moving_enemy_collision_distance: 5 + enemy_with_different_destination_collision_penalty: 30 + general_entity_collision_penalty: 10 + general_entity_subsequent_collision_penalty: 3 + extended_collision_penalty: 3 + max_clients_to_accept_any_new_request: 10 + max_clients_to_accept_short_new_request: 100 + direct_distance_to_consider_short_request: 100 + short_request_max_steps: 1000 + short_request_ratio: 0.5 + min_steps_to_check_path_find_termination: 2000 + start_to_goal_cost_multiplier_to_terminate_path_find: 500 + overload_levels: + - 0 + - 100 + - 500 + overload_multipliers: + - 2 + - 3 + - 4 + negative_path_cache_delay_interval: 20 + max_failed_behavior_count: 3 + + admin_list: + - Urrrk + - Wendy + + white_list: + # - "john_doe" + # - "jane_doe" + + ban_list: + # - "john_doe" + # - "jane_doe" diff --git a/factorio/svc.yaml b/factorio/svc.yaml new file mode 100644 index 0000000..b81ae80 --- /dev/null +++ b/factorio/svc.yaml @@ -0,0 +1,27 @@ +--- +apiVersion: v1 +kind: Service +metadata: + labels: + app.kubernetes.io/instance: factorio + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: factorio + app.kubernetes.io/version: stable + helm.sh/chart: factorio-1.2.2 + name: factorio + annotations: + io.cilium/lb-ipam-ips: 192.168.0.183 +spec: + ports: + - name: rcon + port: 27015 + protocol: TCP + targetPort: rcon + - name: server + port: 34197 + protocol: UDP + targetPort: server + selector: + app.kubernetes.io/instance: factorio + app.kubernetes.io/name: factorio + type: LoadBalancer \ No newline at end of file