Skip to content

Commit

Permalink
Major rework to deploy services as podman quadlets
Browse files Browse the repository at this point in the history
* All services are provisioned as quadlets now
* Removed pruning unknown services for now
* Added support to running the role rootless
* Reworked envvar config for minecraft
* Removed explicit custom services, you can specify them as name:
  'path/to/service_tasks.yml'
* Added ARR stack 🏴‍☠️
* Reworked all storage into podman volumes instead of mounted dirs,
  this will allow greater flexibility when deploying volumes, provided
  your Podman instance is configured for it
* Removed portainer
* Added a workaround for containers/ansible-podman-collections#739
  • Loading branch information
Thulium-Drake committed Dec 16, 2024
1 parent 0b1a258 commit b690581
Show file tree
Hide file tree
Showing 21 changed files with 383 additions and 203 deletions.
29 changes: 18 additions & 11 deletions .ansible-sign/sha256sum.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,29 @@ ddb6d4a8fc425176bc64489d5735c67466df263d6b0006991a58925b02399d99 .gitignore
1500b5452cb8564ec9902295aaee4583633224ccfeeee7fc283b40a9ff3b246f .pre-commit-config.yaml
3972dc9744f6499f0f9b2dbf76696f2ae7ad8af9b23dde66d6af86c9dfb36986 LICENSE
06ec80d1bfd1d94e946835cfdf8999901dd9732b6c4df14efdd32e1b3e95ab6c MANIFEST.in
75c6aee54403a7871721b2057a1a03b926451825a16957591cabc4910ce4df17 README.md
af826550112f80403c1a1b8f7dc7e94e5946d0b46ee1f856d796f6d407917901 README.md
437fe21765ab0f8764e7474e5fcbea7eeb2c57fea4bd807a22a90366aab6b7b1 defaults/main/arr.yml
3c40772ea079c6223887e3ac8f1bc4492e50cc3bdddfae94976824d0370d0400 defaults/main/factorio.yml
44726eb5c12e8826b488316a9209c9df63a35348caed73c5db400dea07fc1958 defaults/main/main.yml
ad55f1e185fadd3b796b2f556ef4f79b50f5d37fa2135d6ca70848500719895b defaults/main/minecraft.yml
27e7e3ebb99c889b117a1e4147368b41fbacc068042327f75da29d1f5829ca40 defaults/main/main.yml
87e4b484968f2224e624997f6e7d8db88fc2ea9526dc127040fe48a3f47f3c38 defaults/main/minecraft.yml
016a8c730556dd9d5bd341b739689f40d98050dd673dfadd3dd8940cf4bbf917 defaults/main/portainer.yml
b58931c5c242891d5d7b9f189efe82bfb1a9d681d99c6abc7f96297f8869accb defaults/main/vaultwarden.yml
eaaccbd421b12cc9b4ebfce8092262017a659cbc7b883441cb1d7c2d36bda8e8 defaults/main/vaultwarden.yml
76fc17ef985f57044ec59fabd80423a58ff4a30a6c13273d79b59e40e3edc46d handlers/main.yml
230c6e7230a6fd181134a921da38785bfbad450d1242c13bdbc5351a8c88b66a meta/main.yml
e469827a621deca25edffd1a36cc5d2aaef07ba2b70b9d7736e5e8e3361ba2c2 molecule/default/INSTALL.rst
b3a2f7bb742970b2a52b96d4ab4de0563dfd3a028f56264d1475771e20bcc13b molecule/default/converge.yml
578ab76570c95c6b5f7c1cfc8492903d2b7df0747e1a047e562338b1c7a8896b molecule/default/molecule.yml
113f8f168f0d41bb78e1ed960bb2986720f757191ddb229ff3d694eaee370662 molecule/default/prepare.yml
2edd783d28b9e420ad49fcfa5ebcfb4cbbd7c15ba48d0dbc0dc8a7445c00fb5d molecule/default/verify.yml
ab2d3fed945f89f346bd9b35ee9ce8ff46dcb694cf1c4ab9004a210bfe0b1e0f tasks/main.yml
fdb105777772a6c968c61634d467bb75016fae55e815f8f6b5095cc1446c80da tasks/services/factorio.yml
fc21258fa7f27a9207e642d9c19ccd8550625aaca532bcd49404294eab83aeb2 tasks/services/hello_world.yml
7ae142d3f39bb7a5a44b92e5562a75942f2c805d5aecfb01a7bd8873e406f810 tasks/services/minecraft.yml
32cafd9b87eb70a346d9c40133e42c0f492fad17233cc6b8d61eb2d7c2f867e4 tasks/services/portainer.yml
63975d6aa7d5df689072ef189d83fdf9403e38f5695a7cf37354f2ba30288a14 tasks/services/vaultwarden.yml
909f6b4f91ee05a2c63d73433518b824798195a1e7a4e769e438a91ab323cbfc vars/main.yml
9fec3d23bbd6246c5d37c6fc9516fbc43b681cd7fecdab8005c4ed70ceb2109e tasks/changed_service.yml
34c3bef783429c472861cfe9caef94b0abf0b9c9e32b89e82c82745c6ec0bc45 tasks/main.yml
97b2cfe31f834c47513f67c682ee5915ec4db10261b6b739de82c4eb5aa58559 tasks/network.yml
2532739f47122bc6245aeec5539d74bb7fa0728b43223f37b07820e0adb945a4 tasks/restart_container.yml
8c7b59aab16d6a48dde66bd42fef0c5770938db97c18858e60b313e7257274e0 tasks/services/arr.yml
61ed7d0cb20e5ad415d7b3634d01416cd2229c4a668e225fa72188a2fee676bb tasks/services/factorio.yml
42f1d648848d8a029b5072cf6d9ee0ebe99d4e2423e22b6815c265d8c839953b tasks/services/hello_world.yml
a41c76d986966b569f480fa4e591e34ff32cc1d43f55f224c3b8b58f01abb685 tasks/services/minecraft.yml
65c5018c35bd581f3d5bef078397312d14fabdae76c133aa4da5363b4b30b1e3 tasks/services/vaultwarden.yml
bdacd2fbb481dc028734f9b3c9a69260db9509fc39b7e1c2e81b0eb824f339a0 tasks/volume.yml
476b04fe1cb04eba215960f2f5f80a51b05c9cd64a4aaffe72eafbac8f7cccd7 tasks/workaround_remove.yml
1d7f88fba9c5ecc9d37c6140b881cb93eb82153983637f92332381dc4607b5b6 vars/main.yml
8 changes: 4 additions & 4 deletions .ansible-sign/sha256sum.txt.sig
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
-----BEGIN PGP SIGNATURE-----

iHUEABYKAB0WIQQsyXWq0wHVhSS9uIw57/aqH1sRoAUCZwexkwAKCRA57/aqH1sR
oIpLAP0U9hBQWHG1K2Bpf/Z5xdxMHC9uBcNysPFKqxxU1KeXxwD/Qzd9czrCB48W
PU12B4bdFCHxs5yLtjilanVDnp3fmg0=
=08Yj
iHUEABYKAB0WIQQsyXWq0wHVhSS9uIw57/aqH1sRoAUCZ2AFewAKCRA57/aqH1sR
oNtWAQDNaxUqsd7i7w9nbfqi7lJVW+0gWM3kMONBj7mVv6UApAD/emTVj82bAu3S
ywMX2/fIBz+r+pZiF3mMhoWHEoUwoAw=
=Y8yZ
-----END PGP SIGNATURE-----
16 changes: 15 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
# Podman services catalogue
This role contains a collection of services that run on a Podman node. All persistent storage is bind-mounted into the container, this allows for placing that data on shared storage, such as NFS or GlusterFS.
This role contains a collection of services that run on a Podman node. All persistent storage is configured to use Podman Volumes. If desired, you can change the driver used by the volumes, by default it uses 'local'.

The catalogus currently contains:

* arr: A full arr stack with tranmission
* hello_world: a simple container that will return 'hello world' via a REST API
* vaultwarden: A free alternative server for the Bitwarden Password Manager
* factorio: The Factorio server
* minecraft: The Minecraft Server

# Deployment
In order to use the services from this catalogue, do the following:
Expand All @@ -20,3 +23,14 @@ In order to use the services from this catalogue, do the following:
roles:
- 'podman_services'
```

## ARR stack notes
Configuring the ARR stack should mostly still be done by hand, all containers are reachable for each other by their container name (which is arr-$APP, e.g. arr-sonarr) on their default ports.

NOTE: Keep in mind that reaching the apps from your pc uses the hostname of the podman host! The apps themselves are configured to connect to each other using a Podman network and uses an alternative DNS source!

Configuring the integrations between the different apps works as follows:

* Go to the source app -> Settings -> General and retrieve the API key
* Go to the target app and paste the API key
* The server address inside the app will be http://arr-$APP:$PORT (e.g. http://arr-prowlarr:9696 and http://arr-radarr:7878)
15 changes: 15 additions & 0 deletions defaults/main/arr.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
---
# Set this to the folder that _contains_ your downloads/movies/tv etc.
arr_data_folder: '/media'

arr_data_container_uid: '0'
arr_data_container_gid: '0'

bazarr_port: 6767
prowlarr_port: 9696
radarr_port: 7878
readarr_port: 8787
sonarr_port: 8989
transmission_port: 9091

arr_timezone: 'Etc/UTC'
34 changes: 14 additions & 20 deletions defaults/main/main.yml
Original file line number Diff line number Diff line change
@@ -1,24 +1,18 @@
---
# Services to deploy contained in this role
# Services to deploy contained in this role, for service configuration, please see the appropriate file
# in the defaults
# NOTE: When disabling services, DATA VOLUMES WILL BE REMOVED!
podman_services: []
# - name: 'hello_world'
# state: 'present'

# Services to deploy from the custom_services_path
podman_custom_services: []
podman_custom_services_path: 'files/podman_services'
# Which driver to use for volume storage, this role does not set up the driver!
podman_volume_driver: 'local'

# Default container registry to use when no fully qualified image name is provided
# NOTE: This role does not configure registries.
podman_default_registry: 'docker.io'

# Directory to store all container data
podman_data_dir: '/opt'

# Systemd config for all podman services
podman_services_systemd_config:
path: '/etc/systemd/system'
restart_policy: 'always'
time: 120
names: true
new: true
container_prefix: 'podman_service'
separator: '_'
# Default options for all generated container quadlets
# Enable automatic updates and ensure that it is started by default
podman_quadlet_options:
- 'AutoUpdate=registry'
- |
[Install]
WantedBy=default.target
25 changes: 11 additions & 14 deletions defaults/main/minecraft.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,17 @@
# Images etc.
minecraft_image_uri: 'docker.io/itzg/minecraft-server'
minecraft_image_version: 'latest'
minecraft_rcon_image_uri: 'docker.io/itzg/rcon'
minecraft_rcon_version: 'latest'

minecraft_curseforge_api_key: 'my_awesome_api_key'

# Minecraft server settings
minecraft_listen_port: 25565
minecraft_initial_memory: '1G'
minecraft_max_memory: '1G'
minecraft_game_version: 'LATEST'

# Mods
# The server is setup to use either the contents of 'mods_list.txt' in the data directory
# and auto-download the mods with the configured mod platform.
#
# Or, disable mods_list support and set a modpack URL which contains everything you need
minecraft_mods_list_enabled: true # when false, uses the modpack defined
minecraft_mod_platform: 'FORGE'
minecraft_modpack_url: 'http://example.com/mods/modpack.zip'
minecraft_envvars:
EULA: "TRUE"
VERSION: 'LATEST'
TYPE: 'AUTO_CURSEFORGE'
CF_API_KEY: "{{ minecraft_curseforge_api_key | quote }}"
CF_SLUG: 'better-mc-forge-bmc4'
CF_EXCLUDE_MODS: 'yungs-menu-tweaks,xaeroplus'
INIT_MEMORY: '1G'
MAX_MEMORY: '1G'
2 changes: 2 additions & 0 deletions defaults/main/vaultwarden.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
---
vaultwarden_version: 'alpine'
vaultwarden_image_uri: 'docker.io/vaultwarden/server'

# Set this token to enable the admin portal
vaultwarden_admin_token: ''
vaultwarden_domain: 'vault.example.nl'
Expand Down
6 changes: 6 additions & 0 deletions handlers/main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
- name: 'Restart changed services'
ansible.builtin.include_tasks: '../tasks/restart_container.yml'
loop: "{{ podman_services_changed }}"
loop_control:
loop_var: 'service'
12 changes: 12 additions & 0 deletions tasks/changed_service.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
---
- name: 'Add service to changelist' # noqa no-handler
ansible.builtin.set_fact:
podman_services_changed: "{{ podman_services_changed + [service['name']] }}"
when:
- service_config['changed']
- service['state'] | default('present') == 'present'

- name: 'Reload systemd'
ansible.builtin.systemd:
daemon_reload: true
scope: "{{ (ansible_facts['effective_user_id'] > 0) | ternary('user', 'system', 'system') }}"
46 changes: 6 additions & 40 deletions tasks/main.yml
Original file line number Diff line number Diff line change
@@ -1,47 +1,13 @@
---
- name: 'Deploy services'
ansible.builtin.include_tasks: "services/{{ container }}.yml"
ansible.builtin.include_tasks: "services/{{ service['name'] }}.yml"
loop: "{{ podman_services }}"
loop_control:
loop_var: 'container'

- name: 'Deploy custom services'
ansible.builtin.include_tasks: "{{ podman_custom_services_path }}/{{ container }}.yml"
loop: "{{ podman_custom_services }}"
loop_control:
loop_var: 'container'

- name: 'Gathering services'
ansible.builtin.service_facts:

- name: 'Make list of podman services'
ansible.builtin.set_fact:
podman_services_detected: "{{ podman_services_detected + [item['key'].split('.')[0].split('_')[2:] | join('_')] }}"
loop: "{{ ansible_facts['services'] | dict2items | selectattr('key', 'contains', 'podman_service_') }}"

- name: 'Stop unknown Podman services'
ansible.builtin.service:
name: "podman_service_{{ item }}"
state: 'stopped'
enabled: false
failed_when: false
loop: "{{ podman_services_detected | difference(podman_services + podman_custom_services) }}"

- name: 'Remove unknown Podman services'
ansible.builtin.file:
path: "/etc/systemd/system/podman_service_{{ item }}.service"
state: 'absent'
loop: "{{ podman_services_detected | difference(podman_services + podman_custom_services) }}"

- name: 'Reload systemd to process changed units'
ansible.builtin.systemd:
daemon_reload: true
loop_var: 'service'

- name: 'Restart changed services' # noqa no-handler
ansible.builtin.service:
name: "podman_service_{{ service }}"
state: 'restarted'
enabled: true
loop: "{{ podman_services_changed }}"
- name: 'Workaround - remove services'
ansible.builtin.include_tasks: 'workaround_remove.yml'
when: service['state'] | default('present') == 'absent'
loop: "{{ podman_services }}"
loop_control:
loop_var: 'service'
9 changes: 9 additions & 0 deletions tasks/network.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
- name: "Ensure networks - {{ service['name'] }}"
containers.podman.podman_network:
name: "{{ network }}"
state: "{{ (service['state'] | default('present') == 'present') | ternary('quadlet', 'absent') }}"
notify: 'Restart changed services'
loop: "{{ podman_networks[service['name']] }}"
loop_control:
loop_var: 'network'
9 changes: 9 additions & 0 deletions tasks/restart_container.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
- name: 'Restart changed containers'
ansible.builtin.systemd:
name: "{{ container }}"
state: 'restarted'
scope: "{{ (ansible_facts['effective_user_id'] > 0) | ternary('user', 'system', 'system') }}"
loop: "{{ podman_containers[service] }}"
loop_control:
loop_var: 'container'
Loading

0 comments on commit b690581

Please sign in to comment.