From 04a19694da25247666e7d89506eea18d90bd0a93 Mon Sep 17 00:00:00 2001 From: Kian Kasad Date: Wed, 24 Jul 2024 22:45:57 -0700 Subject: [PATCH 01/19] Fix wrong usage of undef() --- config.yml.sample | 6 +++--- roles/jellyfin/defaults/main.yml | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/config.yml.sample b/config.yml.sample index 88ef407..5dbccfb 100644 --- a/config.yml.sample +++ b/config.yml.sample @@ -181,7 +181,7 @@ tailscale_routes: - "10.0.0.0/24" # Use Ansible Vault to put your encrypted auth key here -tailscale_auth_key: "{{ undef }}" +tailscale_auth_key: "{{ undef() }}" ################### @@ -206,8 +206,8 @@ minio_routing: ui_subdomain: minio # Use Ansible Vault to put your encrypted credentials here -minio_root_user: "{{ undef }}" -minio_root_password: "{{ undef }}" +minio_root_user: "{{ undef() }}" +minio_root_password: "{{ undef() }}" ##################### diff --git a/roles/jellyfin/defaults/main.yml b/roles/jellyfin/defaults/main.yml index 2308e9e..46484ea 100644 --- a/roles/jellyfin/defaults/main.yml +++ b/roles/jellyfin/defaults/main.yml @@ -22,8 +22,8 @@ jellyfin_server_name: Jellyfin Media Server jellyfin_sso_only: true # OIDC client ID and secret for Jellyfin-Authentik integration. -jellyfin_oidc_client_id: "{{ undef }}" -jellyfin_oidc_client_secret: "{{ undef }}" +jellyfin_oidc_client_id: "{{ undef() }}" +jellyfin_oidc_client_secret: "{{ undef() }}" # Version/tag of the lscr.io/linuxserver/jellyfin image to use jellyfin_tag: "10.9.7" From a3b3410c1c29e563c84942e14652ec3f684d50c7 Mon Sep 17 00:00:00 2001 From: Kian Kasad Date: Wed, 24 Jul 2024 22:46:06 -0700 Subject: [PATCH 02/19] Create CI pipeline --- .github/workflows/ci.yml | 89 ++++++++++++++++++++++++++++++++++++++++ ci/ansible.cfg | 5 +++ ci/config_overrides.yml | 36 ++++++++++++++++ config.yml | 1 + config.yml.sample | 78 +++++++++++++++++++++++++++++++---- 5 files changed, 201 insertions(+), 8 deletions(-) create mode 100644 .github/workflows/ci.yml create mode 100644 ci/ansible.cfg create mode 100644 ci/config_overrides.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..10b4b6a --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,89 @@ +--- +name: CI + +on: + push: {} + pull_request: {} + +concurrency: + group: ${{ github.workflow }} + cancel-in-progress: true + +env: + ANSIBLE_FORCE_COLOR: '1' + ANSIBLE_CONFIG: ci/ansible.cfg + +jobs: + lint: + name: Lint code + runs-on: ubuntu-latest + steps: + - name: Check out sources + uses: actions/checkout@v4 + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: '3.x' + + - name: Install Python dependencies + run: python3 -m pip install -r requirements.txt + + - name: Install Ansible Galaxy dependencies + run: ansible-galaxy install -r requirements.yml + + - name: Run YAML linter + run: yamllint . + + - name: Run Ansible syntax check + run: ansible-playbook main.yml --syntax-check + + - name: Run Ansible linter + run: ansible-lint + + run-playbook: + name: Run playbook + runs-on: ubuntu-latest + steps: + - name: Check out sources + uses: actions/checkout@v4 + + - name: Install Python dependencies + run: python3 -m pip install -r requirements.txt + + - name: Install Ansible Galaxy dependencies + run: ansible-galaxy install -r requirements.yml + + - name: Remove encrypted secrets + run: grep -lZ -e '^\$ANSIBLE_VAULT' group_vars/*/*.yml | xargs -0 rm -f + + - name: Use sample config + run: cp -f config.yml.sample config.yml + + - name: Run playbook (first run) + run: ansible-playbook main.yml --extra-vars '@ci/config_overrides.yml' + + - name: Run playbook (second run) + run: ansible-playbook main.yml --extra-vars '@ci/config_overrides.yml' | tee /tmp/secondrun.log + + - name: Upload second run output as artifact + uses: actions/upload-artifact@v4 + with: + name: second-run-output + path: /tmp/secondrun.log + + idempotence: + name: Check idempotence + runs-on: ubuntu-latest + needs: run-playbook + steps: + - name: Download second run output artifact + uses: actions/download-artifact@v4 + with: + name: second-run-output + + - name: Check idempotence + run: >- + grep -A1 -e 'PLAY RECAP' secondrun.log | grep -q -e 'changed=0.*failed=0' + && (echo 'Idempotence test: pass' && exit 0) + || (echo 'Idempotence test: fail' && exit 1) diff --git a/ci/ansible.cfg b/ci/ansible.cfg new file mode 100644 index 0000000..ce1a0a8 --- /dev/null +++ b/ci/ansible.cfg @@ -0,0 +1,5 @@ +[defaults] +nocows = True +inventory = inventory +stdout_callback = ansible.posix.debug +strategy = free diff --git a/ci/config_overrides.yml b/ci/config_overrides.yml new file mode 100644 index 0000000..c86a79f --- /dev/null +++ b/ci/config_overrides.yml @@ -0,0 +1,36 @@ +--- +storage: + data_dir: /data + nas_dir: /nas + docker_dir: /var/lib/docker + + # Don't create LVM volumes since we don't control the disk setup + vg: pool + volumes: {} + + + +########### +# SECRETS # +########### + +minio_root_user: "minio" +minio_root_password: "minio" + +secret_authentik_pg_pass: authentik +secret_authentik_bootstrap_email: authentik +secret_authentik_bootstrap_password: authentik + +secret_homarr_oidc_client_id: homarrclientid +secret_homarr_oidc_client_secret: homarrclientsecret + +secret_minio_openid_client_id: minioclientid +secret_minio_openid_client_secret: minioclientsecret + +secret_jellyfin_admin_username: jellyfin +secret_jellyfin_admin_password: jellyfin +secret_jellyfin_oidc_client_id: jellyfinclientid +secret_jellyfin_oidc_client_secret: jellyfinclientsecret + +secret_monitoring_grafana_client_id: grafanaclientid +secret_monitoring_grafana_client_secret: grafanaclientsecret diff --git a/config.yml b/config.yml index cd7c814..bf2d662 100644 --- a/config.yml +++ b/config.yml @@ -244,6 +244,7 @@ homarr_env: AUTH_OIDC_CLIENT_NAME: Authentik AUTH_OIDC_CLIENT_ID: "{{ secret_homarr_oidc_client_id }}" AUTH_OIDC_CLIENT_SECRET: "{{ secret_homarr_oidc_client_secret }}" + AUTH_OIDC_SCOPE_OVERWRITE: openid email profile groups AUTH_OIDC_ADMIN_GROUP: Administrators AUTH_OIDC_URI: >- https://{{ authentik_routing.subdomain | default('auth') }}.{{ general.domain }}/application/o/homarr diff --git a/config.yml.sample b/config.yml.sample index 5dbccfb..f0c2c01 100644 --- a/config.yml.sample +++ b/config.yml.sample @@ -62,7 +62,7 @@ storage: # DDNS options # ################ -ddns_enabled: yes +ddns_enabled: no # Cloudflare zone to which the server's domain belongs ddns_cloudflare_zone: example.com @@ -76,12 +76,13 @@ ddns_cloudflare_api_token: # DNS server options # ###################### -dnsmasq_enabled: false +dnsmasq_enabled: yes dnsmasq_custom_hosts: - name: "{{ general.domain }}" ip: "{{ ansible_default_ipv4.address }}" - + - name: ".{{ general.domain }}" + ip: "{{ ansible_default_ipv4.address }}" ################# # Samba options # @@ -128,16 +129,23 @@ minecraft_server_enabled: no ###################### # After Authentik is enabled, go to https://:9443/if/flow/initial-setup/ -authentik_enabled: no +authentik_enabled: yes # Traefik routing options for Authentik authentik_routing: enabled: true subdomain: authentik -# See https://docs.goauthentik.io/docs/installation/configuration for documentation +# See https://docs.goauthentik.io/docs/installation/configuration for documentation. +# Use Ansible Vault to encrypt the secret_* variables. authentik_env: - PG_PASS: "{{ undef }}" # Use Ansible Vault to store an encrypted password here + # PostgreSQL root password + PG_PASS: "{{ secret_authentik_pg_pass }}" + + # Credentials for the Authentik "akadmin" user during initial setup. + # Use Ansible Vault to store an encrypted password here. + AUTHENTIK_BOOTSTRAP_EMAIL: "{{ secret_authentik_bootstrap_email }}" + AUTHENTIK_BOOTSTRAP_PASSWORD: "{{ secret_authentik_bootstrap_password }}" #################### @@ -154,7 +162,7 @@ traefik_ports: # See https://doc.traefik.io/traefik/https/acme/ for information on how to # configure the provider and environment variables. traefik_acme_dns: - enabled: yes + enabled: no provider: cloudflare # Email for Let's Encrypt, used to receive expiry notifications. @@ -193,6 +201,19 @@ homarr_routing: enabled: true homepage: true +# OIDC settings for Authentik +homarr_env: + AUTH_PROVIDER: oidc + AUTH_OIDC_CLIENT_NAME: Authentik + AUTH_OIDC_CLIENT_ID: "{{ secret_homarr_oidc_client_id }}" + AUTH_OIDC_CLIENT_SECRET: "{{ secret_homarr_oidc_client_secret }}" + AUTH_OIDC_SCOPE_OVERWRITE: openid email profile groups + AUTH_OIDC_ADMIN_GROUP: Administrators + AUTH_OIDC_URI: >- + https://{{ authentik_routing.subdomain | default('auth') }}.{{ general.domain }}/application/o/homarr + AUTH_LOGOUT_REDIRECT_URL: >- + https://{{ authentik_routing.subdomain | default('auth') }}.{{ general.domain }}/application/o/homarr/end-session/ + ################## # Minio settings # @@ -209,12 +230,44 @@ minio_routing: minio_root_user: "{{ undef() }}" minio_root_password: "{{ undef() }}" +# Environment variables to configure integration with Authentik using OpenID Connect. +# Currently, this requires manual setup in the Authentik UI. +# Use Ansible Vault to put your encrypted client ID and secret below. +minio_env: + MINIO_IDENTITY_OPENID_CONFIG_URL: "https://{{ authentik_routing.subdomain | default('auth') }}.{{ general.domain }}\ + /application/o/minio/.well-known/openid-configuration" + MINIO_IDENTITY_OPENID_CLIENT_ID: "{{ secret_minio_openid_client_id }}" + MINIO_IDENTITY_OPENID_CLIENT_SECRET: "{{ secret_minio_openid_client_secret }}" + MINIO_IDENTITY_OPENID_CLAIM_NAME: policy + MINIO_IDENTITY_OPENID_DISPLAY_NAME: Log in with Authentik + MINIO_IDENTITY_OPENID_SCOPES: openid,profile,email,minio + MINIO_IDENTITY_OPENID_REDIRECT_URI: >- + {{ minio_routing.ui_subdomain | default('minio') }}.{{ general.domain }}/oauth_callback + MINIO_IDENTITY_OPENID_REDIRECT_URI_DYNAMIC: "on" + MINIO_IDENTITY_OPENID_CLAIM_USERINFO: "on" + MINIO_IDENTITY_OPENID_COMMENT: "Authentik" + + +###################### +# Bitwarden settings # +###################### + +bitwarden_enabled: true + ##################### # Jellyfin settings # ##################### -jellyfin_enabled: false +jellyfin_enabled: yes + +jellyfin_enable_vaapi: false + +jellyfin_admin_username: "{{ secret_jellyfin_admin_username }}" +jellyfin_admin_password: "{{ secret_jellyfin_admin_password }}" + +jellyfin_oidc_client_id: "{{ secret_jellyfin_oidc_client_id }}" +jellyfin_oidc_client_secret: "{{ secret_jellyfin_oidc_client_secret }}" ####################### @@ -222,3 +275,12 @@ jellyfin_enabled: false ####################### monitoring_enabled: yes + +monitoring_prometheus_routing_private: yes +monitoring_grafana_routing_private: no + +# Grafana SSO settings +monitoring_grafana_sso: yes +monitoring_grafana_sso_only: yes +monitoring_grafana_client_id: "{{ secret_monitoring_grafana_client_id }}" +monitoring_grafana_client_secret: "{{ secret_monitoring_grafana_client_secret }}" From 310853ea1c2924d9f93476b948add7efa39eba7a Mon Sep 17 00:00:00 2001 From: Kian Kasad Date: Wed, 24 Jul 2024 22:48:17 -0700 Subject: [PATCH 03/19] Fix yamllint errors --- .github/workflows/ci.yml | 2 +- .yamlignore | 1 + ci/config_overrides.yml | 1 - roles/monitoring/templates/docker-compose.yml | 9 ++++++--- roles/monitoring/templates/loki.yml | 5 +++-- roles/monitoring/templates/promtail.yml | 1 + roles/traefik/templates/dynamic/privateip.yml | 2 +- 7 files changed, 13 insertions(+), 8 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 10b4b6a..ac4e7dc 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,7 +1,7 @@ --- name: CI -on: +'on': push: {} pull_request: {} diff --git a/.yamlignore b/.yamlignore index e945103..0c1d31d 100644 --- a/.yamlignore +++ b/.yamlignore @@ -1 +1,2 @@ group_vars/homeserver/secrets.yml +group_vars/homeserver/prometheus_scrape_configs.yml diff --git a/ci/config_overrides.yml b/ci/config_overrides.yml index c86a79f..ea5d203 100644 --- a/ci/config_overrides.yml +++ b/ci/config_overrides.yml @@ -9,7 +9,6 @@ storage: volumes: {} - ########### # SECRETS # ########### diff --git a/roles/monitoring/templates/docker-compose.yml b/roles/monitoring/templates/docker-compose.yml index 37f4520..95205dc 100644 --- a/roles/monitoring/templates/docker-compose.yml +++ b/roles/monitoring/templates/docker-compose.yml @@ -22,8 +22,10 @@ services: - "{{ monitoring_prometheus_data_dir }}/data:/prometheus" labels: traefik.enable: "{{ monitoring_prometheus_routing_enabled | ternary('true', 'false') }}" - traefik.http.routers.prometheus.rule: Host(`{{ monitoring_prometheus_routing_subdomain }}.{{ general.domain }}`) - traefik.http.routers.prometheus.middlewares: "{{ monitoring_prometheus_routing_private | ternary('privateip@file', '') }}" + traefik.http.routers.prometheus.rule: >- + Host(`{{ monitoring_prometheus_routing_subdomain }}.{{ general.domain }}`) + traefik.http.routers.prometheus.middlewares: >- + {{ monitoring_prometheus_routing_private | ternary('privateip@file', '') }} traefik.http.routers.prometheus.entrypoints: websecure traefik.http.services.prometheus.loadbalancer.server.port: "9090" networks: @@ -47,7 +49,8 @@ services: labels: traefik.enable: "{{ monitoring_grafana_routing_enabled | ternary('true', 'false')}}" traefik.http.routers.grafana.rule: Host(`{{ monitoring_grafana_routing_subdomain }}.{{ general.domain }}`) - traefik.http.routers.grafana.middlewares: "{{ monitoring_grafana_routing_private | ternary('privateip@file', '') }}" + traefik.http.routers.grafana.middlewares: >- + {{ monitoring_grafana_routing_private | ternary('privateip@file', '') }} traefik.http.routers.grafana.entrypoints: websecure traefik.http.services.grafana.loadbalancer.server.port: "3000" networks: diff --git a/roles/monitoring/templates/loki.yml b/roles/monitoring/templates/loki.yml index a1c9beb..50256f9 100644 --- a/roles/monitoring/templates/loki.yml +++ b/roles/monitoring/templates/loki.yml @@ -1,3 +1,4 @@ +--- auth_enabled: false server: @@ -55,5 +56,5 @@ limits_config: # Refer to the buildReport method to see what goes into a report. # # If you would like to disable reporting, uncomment the following lines: -#analytics: -# reporting_enabled: false +# analytics: +# reporting_enabled: false diff --git a/roles/monitoring/templates/promtail.yml b/roles/monitoring/templates/promtail.yml index b429cc7..f6619be 100644 --- a/roles/monitoring/templates/promtail.yml +++ b/roles/monitoring/templates/promtail.yml @@ -1,3 +1,4 @@ +--- server: http_listen_port: 80 grpc_listen_port: 0 diff --git a/roles/traefik/templates/dynamic/privateip.yml b/roles/traefik/templates/dynamic/privateip.yml index 6d96643..aa84b85 100644 --- a/roles/traefik/templates/dynamic/privateip.yml +++ b/roles/traefik/templates/dynamic/privateip.yml @@ -8,4 +8,4 @@ http: - "fe80::/10" - "127.0.0.1/8" - "::1/128" - - "172.16.0.0/12" # Docker containers + - "172.16.0.0/12" # Docker containers From 23c19425f3fc3423602de4030b0e311b1d327fac Mon Sep 17 00:00:00 2001 From: Kian Kasad Date: Wed, 24 Jul 2024 22:55:13 -0700 Subject: [PATCH 04/19] Define custom module library path --- ansible.cfg | 3 +++ ci/ansible.cfg | 1 + 2 files changed, 4 insertions(+) diff --git a/ansible.cfg b/ansible.cfg index d3539ab..85bfaa7 100644 --- a/ansible.cfg +++ b/ansible.cfg @@ -1,5 +1,8 @@ [defaults] +# Look for custom module(s) in library directory +library = ./library + # Set inventory file inventory = inventory diff --git a/ci/ansible.cfg b/ci/ansible.cfg index ce1a0a8..5ba4a6a 100644 --- a/ci/ansible.cfg +++ b/ci/ansible.cfg @@ -1,5 +1,6 @@ [defaults] nocows = True +library = ../library inventory = inventory stdout_callback = ansible.posix.debug strategy = free From 0764893dac98d451f0802cd4f90f123ec0d78ded Mon Sep 17 00:00:00 2001 From: Kian Kasad Date: Wed, 24 Jul 2024 22:56:02 -0700 Subject: [PATCH 05/19] Rename setup-* roles to setup_* This also removes the useless roles/*/meta/main.yml files from roles which had them. --- main.yml | 12 ++++++------ roles/{minecraft-server => minecraft_server}/LICENSE | 2 +- .../defaults/main.yml | 0 .../tasks/main.yml | 0 roles/monitoring/defaults/main.yml | 2 +- roles/setup-disks/meta/main.yml | 2 -- roles/setup-general/meta/main.yml | 0 roles/setup-users/meta/main.yml | 2 -- roles/{setup-disks => setup_disks}/tasks/main.yml | 0 .../{setup-docker => setup_docker}/defaults/main.yml | 0 roles/{setup-docker => setup_docker}/tasks/main.yml | 0 .../defaults/main.yml | 0 .../handlers/main.yml | 0 .../{setup-general => setup_general}/tasks/main.yml | 2 +- .../templates/avahi-daemon.conf | 0 .../templates/unattended-upgrades.conf | 0 roles/{setup-ssh => setup_ssh}/files/sshd_config | 0 roles/{setup-ssh => setup_ssh}/handlers/main.yml | 0 roles/{setup-ssh => setup_ssh}/tasks/main.yml | 0 roles/{setup-users => setup_users}/tasks/main.yml | 0 20 files changed, 9 insertions(+), 13 deletions(-) rename roles/{minecraft-server => minecraft_server}/LICENSE (94%) rename roles/{minecraft-server => minecraft_server}/defaults/main.yml (100%) rename roles/{minecraft-server => minecraft_server}/tasks/main.yml (100%) delete mode 100644 roles/setup-disks/meta/main.yml delete mode 100644 roles/setup-general/meta/main.yml delete mode 100644 roles/setup-users/meta/main.yml rename roles/{setup-disks => setup_disks}/tasks/main.yml (100%) rename roles/{setup-docker => setup_docker}/defaults/main.yml (100%) rename roles/{setup-docker => setup_docker}/tasks/main.yml (100%) rename roles/{setup-general => setup_general}/defaults/main.yml (100%) rename roles/{setup-general => setup_general}/handlers/main.yml (100%) rename roles/{setup-general => setup_general}/tasks/main.yml (96%) rename roles/{setup-general => setup_general}/templates/avahi-daemon.conf (100%) rename roles/{setup-general => setup_general}/templates/unattended-upgrades.conf (100%) rename roles/{setup-ssh => setup_ssh}/files/sshd_config (100%) rename roles/{setup-ssh => setup_ssh}/handlers/main.yml (100%) rename roles/{setup-ssh => setup_ssh}/tasks/main.yml (100%) rename roles/{setup-users => setup_users}/tasks/main.yml (100%) diff --git a/main.yml b/main.yml index 61d641a..6c23379 100644 --- a/main.yml +++ b/main.yml @@ -4,25 +4,25 @@ become: true roles: - - role: setup-general + - role: setup_general tags: - setup - - role: setup-disks + - role: setup_disks tags: - setup - nas - - role: setup-users + - role: setup_users tags: - setup - nas - - role: setup-ssh + - role: setup_ssh tags: - setup - - role: setup-docker + - role: setup_docker tags: - docker @@ -38,7 +38,7 @@ tags: - nas - - role: minecraft-server + - role: minecraft_server tags: - minecraft diff --git a/roles/minecraft-server/LICENSE b/roles/minecraft_server/LICENSE similarity index 94% rename from roles/minecraft-server/LICENSE rename to roles/minecraft_server/LICENSE index b89daa5..2f47cbe 100644 --- a/roles/minecraft-server/LICENSE +++ b/roles/minecraft_server/LICENSE @@ -1,4 +1,4 @@ -This subdirectory, roles/minecraft-server, is subject to the following license. +This subdirectory, roles/minecraft_server, is subject to the following license. MIT License diff --git a/roles/minecraft-server/defaults/main.yml b/roles/minecraft_server/defaults/main.yml similarity index 100% rename from roles/minecraft-server/defaults/main.yml rename to roles/minecraft_server/defaults/main.yml diff --git a/roles/minecraft-server/tasks/main.yml b/roles/minecraft_server/tasks/main.yml similarity index 100% rename from roles/minecraft-server/tasks/main.yml rename to roles/minecraft_server/tasks/main.yml diff --git a/roles/monitoring/defaults/main.yml b/roles/monitoring/defaults/main.yml index 49895dd..23018f6 100644 --- a/roles/monitoring/defaults/main.yml +++ b/roles/monitoring/defaults/main.yml @@ -12,7 +12,7 @@ monitoring_prometheus_tag: v2.53.1 monitoring_grafana_tag: "11.1.0" monitoring_grafana_image_renderer_tag: "3.11.1" monitoring_cadvisor_tag: v0.49.1 -monitoring_loki_tag: "3.1.0" # Be sure to also update the Loki driver in the setup-docker role +monitoring_loki_tag: "3.1.0" # Be sure to also update the Loki driver in the setup_docker role monitoring_promtail_tag: "{{ monitoring_loki_tag }}" monitoring_prometheus_routing_enabled: true diff --git a/roles/setup-disks/meta/main.yml b/roles/setup-disks/meta/main.yml deleted file mode 100644 index 23d65c7..0000000 --- a/roles/setup-disks/meta/main.yml +++ /dev/null @@ -1,2 +0,0 @@ ---- -dependencies: [] diff --git a/roles/setup-general/meta/main.yml b/roles/setup-general/meta/main.yml deleted file mode 100644 index e69de29..0000000 diff --git a/roles/setup-users/meta/main.yml b/roles/setup-users/meta/main.yml deleted file mode 100644 index 23d65c7..0000000 --- a/roles/setup-users/meta/main.yml +++ /dev/null @@ -1,2 +0,0 @@ ---- -dependencies: [] diff --git a/roles/setup-disks/tasks/main.yml b/roles/setup_disks/tasks/main.yml similarity index 100% rename from roles/setup-disks/tasks/main.yml rename to roles/setup_disks/tasks/main.yml diff --git a/roles/setup-docker/defaults/main.yml b/roles/setup_docker/defaults/main.yml similarity index 100% rename from roles/setup-docker/defaults/main.yml rename to roles/setup_docker/defaults/main.yml diff --git a/roles/setup-docker/tasks/main.yml b/roles/setup_docker/tasks/main.yml similarity index 100% rename from roles/setup-docker/tasks/main.yml rename to roles/setup_docker/tasks/main.yml diff --git a/roles/setup-general/defaults/main.yml b/roles/setup_general/defaults/main.yml similarity index 100% rename from roles/setup-general/defaults/main.yml rename to roles/setup_general/defaults/main.yml diff --git a/roles/setup-general/handlers/main.yml b/roles/setup_general/handlers/main.yml similarity index 100% rename from roles/setup-general/handlers/main.yml rename to roles/setup_general/handlers/main.yml diff --git a/roles/setup-general/tasks/main.yml b/roles/setup_general/tasks/main.yml similarity index 96% rename from roles/setup-general/tasks/main.yml rename to roles/setup_general/tasks/main.yml index 4e3ce83..e8c52ce 100644 --- a/roles/setup-general/tasks/main.yml +++ b/roles/setup_general/tasks/main.yml @@ -7,7 +7,7 @@ community.general.timezone: name: "{{ general.timezone }}" -# TODO: Extract Avahi setup to a separate setup-network role +# TODO: Extract Avahi setup to a separate setup_network role - name: Install network discovery service daemons ansible.builtin.package: name: diff --git a/roles/setup-general/templates/avahi-daemon.conf b/roles/setup_general/templates/avahi-daemon.conf similarity index 100% rename from roles/setup-general/templates/avahi-daemon.conf rename to roles/setup_general/templates/avahi-daemon.conf diff --git a/roles/setup-general/templates/unattended-upgrades.conf b/roles/setup_general/templates/unattended-upgrades.conf similarity index 100% rename from roles/setup-general/templates/unattended-upgrades.conf rename to roles/setup_general/templates/unattended-upgrades.conf diff --git a/roles/setup-ssh/files/sshd_config b/roles/setup_ssh/files/sshd_config similarity index 100% rename from roles/setup-ssh/files/sshd_config rename to roles/setup_ssh/files/sshd_config diff --git a/roles/setup-ssh/handlers/main.yml b/roles/setup_ssh/handlers/main.yml similarity index 100% rename from roles/setup-ssh/handlers/main.yml rename to roles/setup_ssh/handlers/main.yml diff --git a/roles/setup-ssh/tasks/main.yml b/roles/setup_ssh/tasks/main.yml similarity index 100% rename from roles/setup-ssh/tasks/main.yml rename to roles/setup_ssh/tasks/main.yml diff --git a/roles/setup-users/tasks/main.yml b/roles/setup_users/tasks/main.yml similarity index 100% rename from roles/setup-users/tasks/main.yml rename to roles/setup_users/tasks/main.yml From 7283451f9af68b61887732c0956bf16ced5d3ef7 Mon Sep 17 00:00:00 2001 From: Kian Kasad Date: Wed, 24 Jul 2024 22:57:50 -0700 Subject: [PATCH 06/19] Fix accidental gitignore rule --- .gitignore | 2 +- ci/inventory | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) create mode 100644 ci/inventory diff --git a/.gitignore b/.gitignore index e92c364..d61edb2 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,6 @@ keys/* !keys/README.md -inventory +/inventory .facts_cache vault_password.txt venv/ diff --git a/ci/inventory b/ci/inventory new file mode 100644 index 0000000..0924397 --- /dev/null +++ b/ci/inventory @@ -0,0 +1,2 @@ +[homeserver] +localhost ansible_connection=local From e5c652e001ac091bf4fb9e55f34ec7f9a0779d5d Mon Sep 17 00:00:00 2001 From: Kian Kasad Date: Wed, 24 Jul 2024 23:04:25 -0700 Subject: [PATCH 07/19] Remove defaults from setup_general --- config.yml | 5 ++++- config.yml.sample | 7 ++++--- roles/setup_general/defaults/main.yml | 9 --------- 3 files changed, 8 insertions(+), 13 deletions(-) delete mode 100644 roles/setup_general/defaults/main.yml diff --git a/config.yml b/config.yml index bf2d662..3da3fba 100644 --- a/config.yml +++ b/config.yml @@ -13,7 +13,10 @@ general: # Set the timezone timezone: America/Los_Angeles - # Only automatically install security updates + # Configure which package updates are installed automatically + # If set to "security", only security updates will be installed + # If set to "all", all updates will be installed + # If set to "none", no updates will be installed auto_update_packages: security users: diff --git a/config.yml.sample b/config.yml.sample index f0c2c01..e701599 100644 --- a/config.yml.sample +++ b/config.yml.sample @@ -14,9 +14,10 @@ general: # Set the timezone timezone: Etc/UTC - # Whether to auto-update packages. - # Can be "all" for all updates, "security" for security updates only, or - # "none" for no updates + # Configure which package updates are installed automatically + # If set to "security", only security updates will be installed + # If set to "all", all updates will be installed + # If set to "none", no updates will be installed auto_update_packages: security users: diff --git a/roles/setup_general/defaults/main.yml b/roles/setup_general/defaults/main.yml deleted file mode 100644 index fb5a8a4..0000000 --- a/roles/setup_general/defaults/main.yml +++ /dev/null @@ -1,9 +0,0 @@ ---- - -general: - - # Configure which package updates are installed automatically - # If set to "security", only security updates will be installed - # If set to "all", all updates will be installed - # If set to "none", no updates will be installed - auto_update_packages: security From 2d927f561f8a77faeb6486f27898adfe102317f9 Mon Sep 17 00:00:00 2001 From: Kian Kasad Date: Wed, 24 Jul 2024 23:16:38 -0700 Subject: [PATCH 08/19] Extract zeroconf setup to separate role --- main.yml | 14 ++++++--- roles/setup_general/handlers/main.yml | 5 ---- roles/setup_general/tasks/main.yml | 29 ------------------- roles/setup_zeroconf/tasks/main.yml | 28 ++++++++++++++++++ .../templates/avahi-daemon.conf | 0 5 files changed, 38 insertions(+), 38 deletions(-) create mode 100644 roles/setup_zeroconf/tasks/main.yml rename roles/{setup_general => setup_zeroconf}/templates/avahi-daemon.conf (100%) diff --git a/main.yml b/main.yml index 6c23379..df28777 100644 --- a/main.yml +++ b/main.yml @@ -26,10 +26,6 @@ tags: - docker - - role: ddns - tags: - - ddns - - role: dnsmasq tags: - dnsmasq @@ -38,6 +34,16 @@ tags: - nas + # This must happen after Samba is installed, because wsdd2.service depends + # on smbd.service. + - role: setup_zeroconf + tags: + - setup + + - role: ddns + tags: + - ddns + - role: minecraft_server tags: - minecraft diff --git a/roles/setup_general/handlers/main.yml b/roles/setup_general/handlers/main.yml index 528044c..b729f3b 100644 --- a/roles/setup_general/handlers/main.yml +++ b/roles/setup_general/handlers/main.yml @@ -1,9 +1,4 @@ --- -- name: Restart Avahi daemon - ansible.builtin.service: - name: avahi-daemon - state: restarted - - name: Restart unattended upgrades service ansible.builtin.service: name: unattended-upgrades diff --git a/roles/setup_general/tasks/main.yml b/roles/setup_general/tasks/main.yml index e8c52ce..05108ce 100644 --- a/roles/setup_general/tasks/main.yml +++ b/roles/setup_general/tasks/main.yml @@ -7,35 +7,6 @@ community.general.timezone: name: "{{ general.timezone }}" -# TODO: Extract Avahi setup to a separate setup_network role -- name: Install network discovery service daemons - ansible.builtin.package: - name: - - avahi-daemon # for mDNS - - wsdd2 # for WSD and LLMNR - state: present - -- name: Enable and start Avahi daemon - ansible.builtin.service: - name: avahi-daemon - enabled: yes - state: started - -- name: Enable and start WSDD - ansible.builtin.service: - name: wsdd2 - enabled: yes - state: started - -- name: Configure Avahi daemon - ansible.builtin.template: - src: templates/avahi-daemon.conf - dest: /etc/avahi/avahi-daemon.conf - owner: root - group: root - mode: '0644' - notify: Restart Avahi daemon - - name: Configure unattended upgrades when: ansible_facts['distribution'] == "Debian" and general.auto_update_packages != "none" block: diff --git a/roles/setup_zeroconf/tasks/main.yml b/roles/setup_zeroconf/tasks/main.yml new file mode 100644 index 0000000..8051d1c --- /dev/null +++ b/roles/setup_zeroconf/tasks/main.yml @@ -0,0 +1,28 @@ +--- +- name: Install network discovery service daemons + ansible.builtin.package: + name: + - avahi-daemon # for mDNS + - wsdd2 # for WSD and LLMNR + state: present + +- name: Configure Avahi daemon + ansible.builtin.template: + src: templates/avahi-daemon.conf + dest: /etc/avahi/avahi-daemon.conf + owner: root + group: root + mode: '0644' + register: avahi_conf + +- name: Enable and start Avahi daemon + ansible.builtin.service: + name: avahi-daemon + enabled: yes + state: "{{ avahi_conf.changed | ternary('restarted', 'started') }}" + +- name: Enable and start WSDD + ansible.builtin.service: + name: wsdd2 + enabled: yes + state: started diff --git a/roles/setup_general/templates/avahi-daemon.conf b/roles/setup_zeroconf/templates/avahi-daemon.conf similarity index 100% rename from roles/setup_general/templates/avahi-daemon.conf rename to roles/setup_zeroconf/templates/avahi-daemon.conf From bc24a5a33cb0723ddb230d25f978cddfd8a8440c Mon Sep 17 00:00:00 2001 From: Kian Kasad Date: Thu, 25 Jul 2024 09:37:34 -0700 Subject: [PATCH 09/19] Run CI on Ubuntu 24.04 --- .github/workflows/ci.yml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ac4e7dc..a6ff416 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -43,11 +43,17 @@ jobs: run-playbook: name: Run playbook - runs-on: ubuntu-latest + runs-on: ubuntu-24.04 steps: - name: Check out sources uses: actions/checkout@v4 + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: '3.x' + cache: pip + - name: Install Python dependencies run: python3 -m pip install -r requirements.txt From c9bd042fb5ec696445758e2b9488f3ab20998bb3 Mon Sep 17 00:00:00 2001 From: Kian Kasad Date: Thu, 25 Jul 2024 10:20:32 -0700 Subject: [PATCH 10/19] Make dnsmasq port configurable --- ci/config_overrides.yml | 2 ++ roles/dnsmasq/defaults/main.yml | 3 +++ roles/dnsmasq/tasks/main.yml | 6 +++--- roles/dnsmasq/templates/dnsmasq.conf | 2 +- 4 files changed, 9 insertions(+), 4 deletions(-) diff --git a/ci/config_overrides.yml b/ci/config_overrides.yml index ea5d203..d71e353 100644 --- a/ci/config_overrides.yml +++ b/ci/config_overrides.yml @@ -8,6 +8,8 @@ storage: vg: pool volumes: {} +dnsmasq_port: 54 + ########### # SECRETS # diff --git a/roles/dnsmasq/defaults/main.yml b/roles/dnsmasq/defaults/main.yml index 297ab9d..1346660 100644 --- a/roles/dnsmasq/defaults/main.yml +++ b/roles/dnsmasq/defaults/main.yml @@ -5,6 +5,9 @@ dnsmasq_enabled: false # Set data directory dnsmasq_data_dir: "{{ storage.data_dir }}/dnsmasq" +# Set the port to listen on +dnsmasq_port: 53 + # Use Cloudflare's DNS servers by default dnsmasq_upstream_dns_servers: - '1.1.1.1' diff --git a/roles/dnsmasq/tasks/main.yml b/roles/dnsmasq/tasks/main.yml index 1cade7f..8c6f915 100644 --- a/roles/dnsmasq/tasks/main.yml +++ b/roles/dnsmasq/tasks/main.yml @@ -28,8 +28,8 @@ state: started restart_policy: unless-stopped ports: - - "53:53/udp" - - "53:53/tcp" + - "{{ dnsmasq_port }}:{{ dnsmasq_port }}/udp" + - "{{ dnsmasq_port }}:{{ dnsmasq_port }}/tcp" volumes: - "{{ dnsmasq_data_dir }}/dnsmasq.conf:/etc/dnsmasq.conf:ro" capabilities: @@ -52,7 +52,7 @@ owner: root group: root mode: '0644' - line: nameserver 127.0.0.1 + line: "nameserver 127.0.0.1:{{ dnsmasq_port }}" regexp: "^nameserver\\s+(127\\.0\\.0\\.1|::1|localhost)" insertafter: '^#' notify: Regenerate resolv.conf diff --git a/roles/dnsmasq/templates/dnsmasq.conf b/roles/dnsmasq/templates/dnsmasq.conf index 96453fe..e83a341 100644 --- a/roles/dnsmasq/templates/dnsmasq.conf +++ b/roles/dnsmasq/templates/dnsmasq.conf @@ -1,7 +1,7 @@ # Listen on this specific port instead of the standard DNS port # (53). Setting this to zero completely disables DNS function, # leaving only DHCP and/or TFTP. -port=53 +port={{ dnsmasq_port }} # Don't provide DHCP services. Empty value means all interfaces. no-dhcp-interface= From 69862160c4613042c826920b418c9b8f4cd8da1b Mon Sep 17 00:00:00 2001 From: Kian Kasad Date: Thu, 25 Jul 2024 11:40:31 -0700 Subject: [PATCH 11/19] Use systemd-resolved instead of resolvconf --- config.yml | 7 +++++ config.yml.sample | 7 +++++ main.yml | 8 ++++++ roles/dnsmasq/defaults/main.yml | 6 +---- roles/dnsmasq/handlers/main.yml | 12 --------- roles/dnsmasq/tasks/main.yml | 27 ++----------------- roles/setup_dns/defaults/main.yml | 2 ++ roles/setup_dns/tasks/main.yml | 35 +++++++++++++++++++++++++ roles/setup_dns/templates/resolved.conf | 13 +++++++++ 9 files changed, 75 insertions(+), 42 deletions(-) delete mode 100644 roles/dnsmasq/handlers/main.yml create mode 100644 roles/setup_dns/defaults/main.yml create mode 100644 roles/setup_dns/tasks/main.yml create mode 100644 roles/setup_dns/templates/resolved.conf diff --git a/config.yml b/config.yml index 3da3fba..bee6aea 100644 --- a/config.yml +++ b/config.yml @@ -19,6 +19,13 @@ general: # If set to "none", no updates will be installed auto_update_packages: security + # DNS servers to use for non-local lookups + upstream_dns_servers: + - '1.1.1.1' + - '1.0.0.1' + - '2606:4700:4700::1111' + - '2606:4700:4700::1001' + users: worker: worker nas: nas diff --git a/config.yml.sample b/config.yml.sample index e701599..8bfbc92 100644 --- a/config.yml.sample +++ b/config.yml.sample @@ -20,6 +20,13 @@ general: # If set to "none", no updates will be installed auto_update_packages: security + # DNS servers to use for non-local lookups + upstream_dns_servers: + - '1.1.1.1' + - '1.0.0.1' + - '2606:4700:4700::1111' + - '2606:4700:4700::1001' + users: worker: worker nas: nas diff --git a/main.yml b/main.yml index df28777..71a8e18 100644 --- a/main.yml +++ b/main.yml @@ -18,6 +18,11 @@ - setup - nas + - role: setup_dns + tags: + - setup + - dns + - role: setup_ssh tags: - setup @@ -29,6 +34,7 @@ - role: dnsmasq tags: - dnsmasq + - dns - role: vladgh.samba.server tags: @@ -39,10 +45,12 @@ - role: setup_zeroconf tags: - setup + - dns - role: ddns tags: - ddns + - dns - role: minecraft_server tags: diff --git a/roles/dnsmasq/defaults/main.yml b/roles/dnsmasq/defaults/main.yml index 1346660..9ef290d 100644 --- a/roles/dnsmasq/defaults/main.yml +++ b/roles/dnsmasq/defaults/main.yml @@ -9,11 +9,7 @@ dnsmasq_data_dir: "{{ storage.data_dir }}/dnsmasq" dnsmasq_port: 53 # Use Cloudflare's DNS servers by default -dnsmasq_upstream_dns_servers: - - '1.1.1.1' - - '1.0.0.1' - - '2606:4700:4700::1111' - - '2606:4700:4700::1001' +dnsmasq_upstream_dns_servers: "{{ general.upstream_dns_servers | mandatory }}" # Domains to treat as LAN-local dnsmasq_local_domain_suffix: local diff --git a/roles/dnsmasq/handlers/main.yml b/roles/dnsmasq/handlers/main.yml deleted file mode 100644 index 134f755..0000000 --- a/roles/dnsmasq/handlers/main.yml +++ /dev/null @@ -1,12 +0,0 @@ ---- -- name: Restart dnsmasq container - community.docker.docker_container: - name: dnsmasq - state: started - restart: true - -- name: Regenerate resolv.conf - ansible.builtin.command: - cmd: resolvconf -u - changed_when: true - become: true diff --git a/roles/dnsmasq/tasks/main.yml b/roles/dnsmasq/tasks/main.yml index 8c6f915..e8a17ea 100644 --- a/roles/dnsmasq/tasks/main.yml +++ b/roles/dnsmasq/tasks/main.yml @@ -17,7 +17,7 @@ owner: "{{ users.worker }}" group: "{{ users.worker }}" mode: '0640' - notify: Restart dnsmasq container + register: dnsmasq_config - name: Start dnsmasq community.docker.docker_container: @@ -26,6 +26,7 @@ pull: always image_name_mismatch: recreate state: started + restart: "{{ dnsmasq_config.changed }}" restart_policy: unless-stopped ports: - "{{ dnsmasq_port }}:{{ dnsmasq_port }}/udp" @@ -38,30 +39,6 @@ networks: - name: subway - - name: Use dnsmasq for our own DNS lookups - block: - - name: Ensure resolvconf is installed - ansible.builtin.package: - name: resolvconf - state: present - - - name: Set /etc/resolv.conf head contents - ansible.builtin.lineinfile: - path: /etc/resolvconf/resolv.conf.d/head - create: true - owner: root - group: root - mode: '0644' - line: "nameserver 127.0.0.1:{{ dnsmasq_port }}" - regexp: "^nameserver\\s+(127\\.0\\.0\\.1|::1|localhost)" - insertafter: '^#' - notify: Regenerate resolv.conf - - - name: Ensure resolvconf is running - ansible.builtin.service: - name: resolvconf - state: started - - name: Disable dnsmasq when: dnsmasq_enabled is false block: diff --git a/roles/setup_dns/defaults/main.yml b/roles/setup_dns/defaults/main.yml new file mode 100644 index 0000000..12c1852 --- /dev/null +++ b/roles/setup_dns/defaults/main.yml @@ -0,0 +1,2 @@ +--- +setup_dns_upstream_dns_servers: "{{ general.upstream_dns_servers | mandatory }}" diff --git a/roles/setup_dns/tasks/main.yml b/roles/setup_dns/tasks/main.yml new file mode 100644 index 0000000..47286c1 --- /dev/null +++ b/roles/setup_dns/tasks/main.yml @@ -0,0 +1,35 @@ +--- +- name: Install systemd-resolved + ansible.builtin.package: + name: systemd-resolved + state: present + +- name: Ensure resolvconf is uninstalled + ansible.builtin.package: + name: resolvconf + state: absent + +- name: Template systemd-resolved configuration + ansible.builtin.template: + src: resolved.conf + dest: /etc/systemd/resolved.conf + owner: root + group: root + mode: '0644' + register: resolved_conf + +- name: Get service facts + ansible.builtin.service_facts: {} + +- name: Ensure resolvconf is not running + when: "'resolvconf.service' in ansible_facts['services']" + ansible.builtin.service: + name: resolvconf + state: stopped + enabled: no + +- name: Start & enable systemd-resolved + ansible.builtin.service: + name: systemd-resolved + state: "{{ resolved_conf.changed | ternary('restarted', 'started') }}" + enabled: yes diff --git a/roles/setup_dns/templates/resolved.conf b/roles/setup_dns/templates/resolved.conf new file mode 100644 index 0000000..a67c57f --- /dev/null +++ b/roles/setup_dns/templates/resolved.conf @@ -0,0 +1,13 @@ +# See resolved.conf(5) for documentation + +[Resolve] +DNS={{ dnsmasq_enabled | default(false) | ternary('[::1]:' ~ (dnsmasq_port | default(53)) ~ ' 127.0.0.1:' ~ (dnsmasq_port | default(53)), '') }} {{ setup_dns_upstream_dns_servers | join(' ') }} +FallbackDNS={{ setup_dns_upstream_dns_servers | join(' ') }} +Domains=~. +DNSStubListener=no +LLMNR=resolve +MulticastDNS=no # Avahi does this +DNSSEC=no +DNSOverTLS=no +Cache=yes +CacheFromLocalhost=no # dnsmasq will cache for us From 72280c66177f3f23021c4c00ecc0e373531985e8 Mon Sep 17 00:00:00 2001 From: Kian Kasad Date: Thu, 25 Jul 2024 11:53:30 -0700 Subject: [PATCH 12/19] Fix disabling of nonexistent services --- roles/ddns/tasks/main.yml | 4 ++++ roles/setup_general/tasks/main.yml | 9 +++++---- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/roles/ddns/tasks/main.yml b/roles/ddns/tasks/main.yml index 279cc1a..98f1ca2 100644 --- a/roles/ddns/tasks/main.yml +++ b/roles/ddns/tasks/main.yml @@ -25,7 +25,11 @@ - name: Disable ddclient when: ddns_enabled is false block: + - name: Get service facts + ansible.builtin.service_facts: {} + - name: Stop & disable ddclient service + when: "'ddclient.service' in services" ansible.builtin.service: name: ddclient state: stopped diff --git a/roles/setup_general/tasks/main.yml b/roles/setup_general/tasks/main.yml index 05108ce..a0af0cb 100644 --- a/roles/setup_general/tasks/main.yml +++ b/roles/setup_general/tasks/main.yml @@ -7,13 +7,14 @@ community.general.timezone: name: "{{ general.timezone }}" +- name: Install unattended upgrades package + ansible.builtin.package: + name: unattended-upgrades + state: present + - name: Configure unattended upgrades when: ansible_facts['distribution'] == "Debian" and general.auto_update_packages != "none" block: - - name: Install unattended upgrades package - ansible.builtin.package: - name: unattended-upgrades - state: present - name: Copy unattended upgrades configuration file ansible.builtin.template: From 854823dde13497993ad7b545babc73058728e08f Mon Sep 17 00:00:00 2001 From: Kian Kasad Date: Thu, 25 Jul 2024 12:09:18 -0700 Subject: [PATCH 13/19] Re-order Jellyfin setup tasks --- roles/jellyfin/tasks/main.yml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/roles/jellyfin/tasks/main.yml b/roles/jellyfin/tasks/main.yml index 41cf3cb..0b8b65c 100644 --- a/roles/jellyfin/tasks/main.yml +++ b/roles/jellyfin/tasks/main.yml @@ -94,14 +94,6 @@ networks: - name: subway - - name: Enable metrics for Jellyfin # noqa no-handler - ansible.builtin.lineinfile: - state: present - path: "{{ jellyfin_data_dir }}/config/system.xml" - line: " true" - regex: "^\\s*[^<]+\\s*$" - notify: Restart Jellyfin container - - name: Perform initial Jellyfin setup when: not config_dir.stat.exists jellyfin_setup: @@ -114,6 +106,14 @@ authentik_domain: "{{ authentik_routing.subdomain | default('authentik') }}.{{ general.domain }}" login_sso_only: "{{ jellyfin_sso_only }}" + - name: Enable metrics for Jellyfin + ansible.builtin.lineinfile: + state: present + path: "{{ jellyfin_data_dir }}/config/system.xml" + line: " true" + regex: "^\\s*[^<]+\\s*$" + notify: Restart Jellyfin container + - name: Disable Jellyfin when: jellyfin_enabled is false block: From 00db77cf3f76238b81c2d38d27f0aa446787a3ba Mon Sep 17 00:00:00 2001 From: Kian Kasad Date: Thu, 25 Jul 2024 14:21:52 -0700 Subject: [PATCH 14/19] Skip Jellyfin setup in CI --- ci/config_overrides.yml | 4 ++++ roles/jellyfin/defaults/main.yml | 4 ++++ roles/jellyfin/tasks/main.yml | 6 +++++- 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/ci/config_overrides.yml b/ci/config_overrides.yml index d71e353..50e0c79 100644 --- a/ci/config_overrides.yml +++ b/ci/config_overrides.yml @@ -10,6 +10,10 @@ storage: dnsmasq_port: 54 +# Jellyfin takes too long to start on the GitHub Actions runner. +# TODO: Figure out why this is the case. +jellyfin_skip_setup: yes + ########### # SECRETS # diff --git a/roles/jellyfin/defaults/main.yml b/roles/jellyfin/defaults/main.yml index 46484ea..769b1ee 100644 --- a/roles/jellyfin/defaults/main.yml +++ b/roles/jellyfin/defaults/main.yml @@ -12,6 +12,10 @@ jellyfin_routing: enabled: true subdomain: jellyfin +# Whether to skip the initial Jellyfin setup. If set, you must manually set up +# Jellyfin using the web UI. +jellyfin_skip_setup: no + # Set the server name jellyfin_server_name: Jellyfin Media Server diff --git a/roles/jellyfin/tasks/main.yml b/roles/jellyfin/tasks/main.yml index 0b8b65c..4846230 100644 --- a/roles/jellyfin/tasks/main.yml +++ b/roles/jellyfin/tasks/main.yml @@ -95,7 +95,7 @@ - name: subway - name: Perform initial Jellyfin setup - when: not config_dir.stat.exists + when: (not config_dir.stat.exists) and (not jellyfin_skip_setup) jellyfin_setup: server_name: "{{ jellyfin_server_name }}" admin_username: "{{ jellyfin_admin_username }}" @@ -113,6 +113,10 @@ line: " true" regex: "^\\s*[^<]+\\s*$" notify: Restart Jellyfin container + register: enable_metrics + until: enable_metrics is success + retries: 24 + delay: 5 - name: Disable Jellyfin when: jellyfin_enabled is false From 8323012964cbc1442d8c7b1d2d2cfbf965576d2e Mon Sep 17 00:00:00 2001 From: Kian Kasad Date: Sat, 27 Jul 2024 17:30:58 -0700 Subject: [PATCH 15/19] Include task timestamps in CI --- ansible.cfg | 7 +++++++ ci/ansible.cfg | 4 ++++ 2 files changed, 11 insertions(+) diff --git a/ansible.cfg b/ansible.cfg index 85bfaa7..4dee559 100644 --- a/ansible.cfg +++ b/ansible.cfg @@ -19,3 +19,10 @@ vault_password_file = ./vault_password.txt # Print output/errors in human-readable format stdout_callback = ansible.posix.debug + +# Print timestamp for each task +;callbacks_enabled = ansible.posix.profile_tasks + +[callback_profile_tasks] +# Don't show summary of longest-running tasks +;task_output_limit = 0 diff --git a/ci/ansible.cfg b/ci/ansible.cfg index 5ba4a6a..0f64d19 100644 --- a/ci/ansible.cfg +++ b/ci/ansible.cfg @@ -4,3 +4,7 @@ library = ../library inventory = inventory stdout_callback = ansible.posix.debug strategy = free +callbacks_enabled = ansible.posix.profile_tasks + +[callback_profile_tasks] +task_output_limit = 0 From 48ff764ecc30fbf781494a3dd6f43adfd176f57c Mon Sep 17 00:00:00 2001 From: Kian Kasad Date: Sat, 27 Jul 2024 17:34:00 -0700 Subject: [PATCH 16/19] Don't cancel CI on other branches --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a6ff416..6867287 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -6,7 +6,7 @@ name: CI pull_request: {} concurrency: - group: ${{ github.workflow }} + group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true env: From 5376c414be44647727da644960d1fb0109be0128 Mon Sep 17 00:00:00 2001 From: Kian Kasad Date: Sat, 27 Jul 2024 17:11:55 -0700 Subject: [PATCH 17/19] Enable Minecraft server in CI It only takes ~6 seconds to start the Minecraft server in CI, which isn't bad at all. --- config.yml.sample | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/config.yml.sample b/config.yml.sample index 8bfbc92..285be9a 100644 --- a/config.yml.sample +++ b/config.yml.sample @@ -129,8 +129,27 @@ samba_shares: # Minecraft server options # ############################ -minecraft_server_enabled: no - +minecraft_server_enabled: yes +minecraft_server_env: + # Server properties + SERVER_PORT: "25565" + ENFORCE_SECURE_PROFILE: "false" + ONLINE_MODE: "true" + ENABLE_COMMAND_BLOCK: "true" + ENABLE_QUERY: "true" + + # Enable automatically pausing when nobody is online + EXEC_DIRECTLY: "false" + ENABLE_AUTOPAUSE: "true" + MAX_TICK_TIME: "-1" # See https://docker-minecraft-server.readthedocs.io/en/latest/misc/autopause-autostop/autopause/ + AUTOPAUSE_TIMEOUT_EST: "600" # Pause 10 minutes after last player disconnects + AUTOPAUSE_TIMEOUT_INIT: "60" # Pause 1 minute after startup if inactive + + # Server settings + TYPE: fabric + VERSION: "1.20.4" + INIT_MEMORY: "512M" + MAX_MEMORY: "1G" ###################### # Authentik settings # @@ -292,3 +311,5 @@ monitoring_grafana_sso: yes monitoring_grafana_sso_only: yes monitoring_grafana_client_id: "{{ secret_monitoring_grafana_client_id }}" monitoring_grafana_client_secret: "{{ secret_monitoring_grafana_client_secret }}" + +# vim: ft=yaml From cbae42cc6c4106682105943b097977bbd022d2b6 Mon Sep 17 00:00:00 2001 From: Kian Kasad Date: Sat, 27 Jul 2024 20:39:31 -0700 Subject: [PATCH 18/19] Fix linting errors --- .yamlignore | 1 + roles/monitoring/templates/docker-compose.yml | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/.yamlignore b/.yamlignore index 0c1d31d..4337604 100644 --- a/.yamlignore +++ b/.yamlignore @@ -1,2 +1,3 @@ group_vars/homeserver/secrets.yml group_vars/homeserver/prometheus_scrape_configs.yml +roles/monitoring/templates/prometheus.yml diff --git a/roles/monitoring/templates/docker-compose.yml b/roles/monitoring/templates/docker-compose.yml index 95205dc..2b08b70 100644 --- a/roles/monitoring/templates/docker-compose.yml +++ b/roles/monitoring/templates/docker-compose.yml @@ -129,7 +129,6 @@ services: - "/var/log:/var/log:ro,rslave" - "/run/log/journal:/run/log/journal:ro,rslave" # For systemd-journal scraper - "/etc/machine-id:/etc/machine-id:ro" # For systemd-journal scraper - # - "{{ storage.docker_dir | default('/var/lib/docker' ) }}/containers:/var/lib/docker/containers:ro" # For Docker log files - "/var/run/docker.sock:/var/run/docker.sock:ro" # For Docker container metadata # Don't include the subway network, because only Loki needs access to # this service From e7fc2780902c6def2fe6a38963e22de2d4194f9a Mon Sep 17 00:00:00 2001 From: Kian Kasad Date: Sat, 27 Jul 2024 20:51:29 -0700 Subject: [PATCH 19/19] Add CI badge to README.md --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 4294139..2b4f3e6 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,7 @@ # Home server playbook +[![CI](https://github.com/kdkasad/home-server/actions/workflows/ci.yml/badge.svg)](https://github.com/kdkasad/home-server/actions/workflows/ci.yml) + An Ansible playbook to manage my home server, a mini-PC running Debian.