From fa06c71f84709ada0de70407ec9be74cf9d1dd29 Mon Sep 17 00:00:00 2001 From: burny Date: Wed, 22 Nov 2023 15:14:04 +0100 Subject: [PATCH] Add ansible factorio setup scripts --- ansible/100_simple_ping/ping.yml | 9 ++ ansible/hosts | 6 + ansible/service_factorio/factorio_setup.yml | 106 ++++++++++++++++++ ansible/service_factorio/factorio_stop.yml | 37 ++++++ ansible/service_factorio/factorio_update.yml | 38 +++++++ .../service_factorio/files/factorio.service | 26 +++++ ansible/service_factorio/files/mod-list.json | 36 ++++++ .../files/server-adminlist.json | 3 + .../files/server-settings.json | 72 ++++++++++++ 9 files changed, 333 insertions(+) create mode 100644 ansible/100_simple_ping/ping.yml create mode 100644 ansible/hosts create mode 100644 ansible/service_factorio/factorio_setup.yml create mode 100644 ansible/service_factorio/factorio_stop.yml create mode 100644 ansible/service_factorio/factorio_update.yml create mode 100644 ansible/service_factorio/files/factorio.service create mode 100644 ansible/service_factorio/files/mod-list.json create mode 100644 ansible/service_factorio/files/server-adminlist.json create mode 100644 ansible/service_factorio/files/server-settings.json diff --git a/ansible/100_simple_ping/ping.yml b/ansible/100_simple_ping/ping.yml new file mode 100644 index 00000000..24d91900 --- /dev/null +++ b/ansible/100_simple_ping/ping.yml @@ -0,0 +1,9 @@ +# Execute with +# ansible-playbook ping.yml -i ../hosts +- name: Ping all + hosts: all + gather_facts: false + + tasks: + - name: ping + ping: diff --git a/ansible/hosts b/ansible/hosts new file mode 100644 index 00000000..110cb873 --- /dev/null +++ b/ansible/hosts @@ -0,0 +1,6 @@ +ungrouped: + hosts: + c: + host: 38.242.226.148 + remote_user: root + private_key_file: /home/burny/syncthing/secrets/.ssh/contabo diff --git a/ansible/service_factorio/factorio_setup.yml b/ansible/service_factorio/factorio_setup.yml new file mode 100644 index 00000000..81d1d380 --- /dev/null +++ b/ansible/service_factorio/factorio_setup.yml @@ -0,0 +1,106 @@ +# Execute with +# ansible-playbook factorio_setup.yml -i ../hosts -i /home/burny/syncthing/secrets/.ansible_secrets +- name: Create and start factorio service + hosts: all + vars: + USERNAME: factorio + tasks: + - name: Create group 'factorio' + ansible.builtin.group: + name: '{{ USERNAME }}' + state: present + + - name: Create 'factorio' user + ansible.builtin.user: + name: '{{ USERNAME }}' + groups: + - '{{ USERNAME }}' + - docker + shell: '{{ secrets.DEFAULT_SHELL }}' + + - name: Get user id + ansible.builtin.shell: + cmd: id {{ USERNAME }} -u + register: USER_ID + + - name: Get group id + ansible.builtin.shell: + cmd: id {{ USERNAME }} -g + register: GROUP_ID + + - name: Print user id + ansible.builtin.debug: + var: USER_ID.stdout + verbosity: 0 + + - name: Print group id + ansible.builtin.debug: + var: GROUP_ID.stdout + verbosity: 0 + + - name: Create systemd file + template: + src: files/factorio.service + dest: /etc/systemd/system/{{ USERNAME }}.service + owner: '{{ USER_ID.stdout }}' + group: '{{ GROUP_ID.stdout }}' + + - name: Create directories + file: + path: '{{ item }}' + recurse: true + state: directory + owner: '{{ USER_ID.stdout }}' + group: '{{ GROUP_ID.stdout }}' + loop: + - /home/{{ USERNAME }}/data/config + - /home/{{ USERNAME }}/data/mods + + - name: Copy admin list file + template: + src: files/server-adminlist.json + dest: /home/{{ USERNAME }}/data/config/server-adminlist.json + owner: '{{ USER_ID.stdout }}' + group: '{{ GROUP_ID.stdout }}' + - name: Copy server settings file + template: + src: files/server-settings.json + dest: /home/{{ USERNAME }}/data/config/server-settings.json + owner: '{{ USER_ID.stdout }}' + group: '{{ GROUP_ID.stdout }}' + + - name: Copy mod list settings + template: + src: files/mod-list.json + dest: /home/{{ USERNAME }}/data/mods/mod-list.json + owner: '{{ USER_ID.stdout }}' + group: '{{ GROUP_ID.stdout }}' + + - name: Stop factorio server + ansible.builtin.systemd_service: + name: factorio + state: stopped + enabled: false + + - name: Stop factorio container + community.docker.docker_container: + name: factorio + state: stopped + image: factoriotools/factorio + + - name: Remove factorio container + community.docker.docker_container: + name: factorio + state: absent + image: factoriotools/factorio + + - name: Start factorio server again + ansible.builtin.systemd_service: + name: factorio + state: started + daemon_reload: true + enabled: true + + - name: Print reminder + ansible.builtin.debug: + msg: Remember to upload an existing savegame manually, aswell as putting mods as .zip files in the '/home/{{ USERNAME }}/data/mods' folder diff --git a/ansible/service_factorio/factorio_stop.yml b/ansible/service_factorio/factorio_stop.yml new file mode 100644 index 00000000..f225241c --- /dev/null +++ b/ansible/service_factorio/factorio_stop.yml @@ -0,0 +1,37 @@ +# Stop factorio service, remove container, remove image +# Execute with +# ansible-playbook factorio_stop.yml -i ../hosts +- name: Stop factorio + hosts: all + vars: + USERNAME: factorio + tasks: + - name: Stop factorio server + ansible.builtin.systemd_service: + name: '{{ USERNAME }}' + state: stopped + enabled: false + + - name: Stop factorio container + community.docker.docker_container: + name: '{{ USERNAME }}' + state: stopped + image: factoriotools/factorio + + - name: Remove factorio container + community.docker.docker_container: + name: '{{ USERNAME }}' + state: absent + image: factoriotools/factorio + + - name: Remove factorio image + community.docker.docker_image: + name: factoriotools/factorio + tag: latest + state: absent + + # - name: Remove the user 'factorio' + # ansible.builtin.user: + # name: {{ USERNAME }} + # state: absent + # remove: true diff --git a/ansible/service_factorio/factorio_update.yml b/ansible/service_factorio/factorio_update.yml new file mode 100644 index 00000000..aa99c05d --- /dev/null +++ b/ansible/service_factorio/factorio_update.yml @@ -0,0 +1,38 @@ +# Stop factorio service, remove container, remove image, start service +# Execute with +# ansible-playbook factorio_update.yml -i ../hosts +- name: Update factorio + hosts: all + vars: + USERNAME: factorio + tasks: + - name: Stop factorio server + ansible.builtin.systemd_service: + name: '{{ USERNAME }}' + state: stopped + enabled: false + + - name: Stop factorio container + community.docker.docker_container: + name: '{{ USERNAME }}' + state: stopped + image: factoriotools/factorio + + - name: Remove factorio container + community.docker.docker_container: + name: '{{ USERNAME }}' + state: absent + image: factoriotools/factorio + + - name: Remove factorio image + community.docker.docker_image: + name: factoriotools/factorio + tag: latest + state: absent + + - name: Start factorio server again + ansible.builtin.systemd_service: + name: '{{ USERNAME }}' + state: started + enabled: true + diff --git a/ansible/service_factorio/files/factorio.service b/ansible/service_factorio/files/factorio.service new file mode 100644 index 00000000..96108e56 --- /dev/null +++ b/ansible/service_factorio/files/factorio.service @@ -0,0 +1,26 @@ +# /etc/systemd/system/{{ USERNAME }}.service +[Service] +ExecStart=/usr/bin/docker run \ + --rm \ + --name factorio \ + -e PUID={{ USER_ID.stdout }} \ + -e PGID={{ GROUP_ID.stdout }} \ + -p 34197:34197/udp \ + -p 27015:27015/tcp \ + -v ./data:/factorio \ + -e GENERATE_NEW_SAVE=true \ + -e SAVE_NAME={{ secrets.FACTORIO.SAVE_NAME }} \ + -e UPDATE_MODS_ON_START=true \ + -l traefik.enable=true \ + -l traefik.http.routers.{{ USERNAME }}.rule=Host(`{{ USERNAME }}.{{ secrets.MY_DOMAIN }}`) \ + -l traefik.http.services.{{ USERNAME }}.loadbalancer.server.port=27015 \ + -l traefik.http.routers.{{ USERNAME }}.tls=true \ + -l traefik.http.routers.{{ USERNAME }}.tls.certresolver=production \ + --network {{ secrets.TRAFIK_NETWORK }} \ + factoriotools/factorio +Restart=always +RestartSec=20 +SyslogIdentifier={{ USERNAME }} +User={{ USERNAME }} +Group={{ USERNAME }} +WorkingDirectory=/home/{{ USERNAME }} diff --git a/ansible/service_factorio/files/mod-list.json b/ansible/service_factorio/files/mod-list.json new file mode 100644 index 00000000..dc90f6c4 --- /dev/null +++ b/ansible/service_factorio/files/mod-list.json @@ -0,0 +1,36 @@ +{ + "mods": + [ + + { + "name": "base", + "enabled": true + }, + + { + "name": "auto-research", + "enabled": true + }, + + { + "name": "AutoDeconstruct", + "enabled": true + }, + + { + "name": "Bottleneck", + "enabled": true + }, + + { + "name": "far-reach", + "enabled": true + }, + + { + "name": "Squeak Through", + "enabled": true + } + ] + } + \ No newline at end of file diff --git a/ansible/service_factorio/files/server-adminlist.json b/ansible/service_factorio/files/server-adminlist.json new file mode 100644 index 00000000..9fa07f87 --- /dev/null +++ b/ansible/service_factorio/files/server-adminlist.json @@ -0,0 +1,3 @@ +[ +"{{ secrets.FACTORIO.NICKNAME }}" +] diff --git a/ansible/service_factorio/files/server-settings.json b/ansible/service_factorio/files/server-settings.json new file mode 100644 index 00000000..167c7774 --- /dev/null +++ b/ansible/service_factorio/files/server-settings.json @@ -0,0 +1,72 @@ +{ + "name": "Name of the game as it will appear in the game listing", + "description": "Description of the game that will appear in the listing", + "tags": ["game", "tags"], + + "_comment_max_players": "Maximum number of players allowed, admins can join even a full server. 0 means unlimited.", + "max_players": 0, + + "_comment_visibility": ["public: Game will be published on the official Factorio matching server", + "lan: Game will be broadcast on LAN"], + "visibility": + { + "public": true, + "lan": true + }, + + "_comment_credentials": "Your factorio.com login credentials. Required for games with visibility public", + "username": "{{ secrets.FACTORIO.NICKNAME }}", + "password": "", + + "_comment_token": "Authentication token. May be used instead of 'password' above.", + "token": "{{ secrets.FACTORIO.TOKEN }}", + + "game_password": "{{ secrets.FACTORIO.GAME_PASSWORD }}", + + "_comment_require_user_verification": "When set to true, the server will only allow clients that have a valid Factorio.com account", + "require_user_verification": true, + + "_comment_max_upload_in_kilobytes_per_second" : "optional, default value is 0. 0 means unlimited.", + "max_upload_in_kilobytes_per_second": 0, + + "_comment_max_upload_slots" : "optional, default value is 5. 0 means unlimited.", + "max_upload_slots": 5, + + "_comment_minimum_latency_in_ticks": "optional one tick is 16ms in default speed, default value is 0. 0 means no minimum.", + "minimum_latency_in_ticks": 0, + + "_comment_max_heartbeats_per_second": "Network tick rate. Maximum rate game updates packets are sent at before bundling them together. Minimum value is 6, maximum value is 240.", + "max_heartbeats_per_second": 60, + + "_comment_ignore_player_limit_for_returning_players": "Players that played on this map already can join even when the max player limit was reached.", + "ignore_player_limit_for_returning_players": false, + + "_comment_allow_commands": "possible values are, true, false and admins-only", + "allow_commands": "admins-only", + + "_comment_autosave_interval": "Autosave interval in minutes", + "autosave_interval": 10, + + "_comment_autosave_slots": "server autosave slots, it is cycled through when the server autosaves.", + "autosave_slots": 20, + + "_comment_afk_autokick_interval": "How many minutes until someone is kicked when doing nothing, 0 for never.", + "afk_autokick_interval": 0, + + "_comment_auto_pause": "Whether should the server be paused when no players are present.", + "auto_pause": true, + + "only_admins_can_pause_the_game": true, + + "_comment_autosave_only_on_server": "Whether autosaves should be saved only on server or also on all connected clients. Default is true.", + "autosave_only_on_server": true, + + "_comment_non_blocking_saving": "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, + + "_comment_segment_sizes": "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 +}