diff --git a/README.md b/README.md index 225dd44..cff32e2 100644 --- a/README.md +++ b/README.md @@ -1,25 +1,97 @@ -Role Name -========= +# laurivan.navidrome -A brief description of the role goes here. +Install navidrome and optionally bonob in docker. -Requirements ------------- +## Requirements -Any pre-requisites that may not be covered by Ansible itself or the role should be mentioned here. For instance, if the role uses the EC2 module, it may be a good idea to mention in this section that the boto package is required. +You need a machine with Docker installed. -Role Variables --------------- +## Role Variables -A description of the settable variables for this role should go here, including any variables that are in defaults/main.yml, vars/main.yml, and any variables that can/should be set via parameters to the role. Any variables that are read from other roles and/or the global scope (ie. hostvars, group vars, etc.) should be mentioned here as well. +All variables are listed below (see also `defaults/main.yml`). -Dependencies ------------- +### Navidrome + +You can (and should) specify the version of the navidrome image: + +```yaml +navidrome_image_version: 'latest' +``` + +Navidrome needs a place to store its configuration and another to pick up music from: + +```yaml +navidrome_config_volume: '/mnt/config-local/navidrome' +navidrome_music_volume: '/mnt/music' +``` +If you have multiple folders with music, you should create a parent and build symbolic links to them. + +The web interface is available at the following port: + +```yaml +navidrome_host_port: 48533 +``` + +### Bonob + +If you have e.g. a Sonos system in the house, you may install also Bonob by setting `bonob_enabled` to `true`. the default is: + +```yml +bonob_enabled: false +``` +You can also specify the bonob image version and the port at which is available: + +```yml +bonob_image_version: 'latest' +bonob_host_port: 48534 +``` + +You can change the colors of the bonob icon displayed: + +```yml +bonob_icon_color: "beige" +bonob_icon_background: "red" +``` +#### Sonos + +The sonos-related variables are: + +```yml +bonob_sonos_auto_register: 'true' +bonob_sonos_device_discovery: 'true' +bonob_sonos_seed_host: +bonob_sonos_service_id: "246" +``` + +If you try sonos autodiscovery and it doesn't work, please: + +1. Find the IP of one of the Sonos devices +2. Set `bonob_sonos_seed_host` to that IP +3. Replay the role + +You can also add custom clients for streaming: + +```yaml +bonob_subsonic_custom_clients: 'audio/flac' +``` + +For more details, please see the [Bonob documentation](https://github.com/simojenki/bonob). + +### Generic + +You will need to specify a timezone: + +```yml +timezone: 'Europe/Brussels' +``` + +Otherwise, Bonob will point to *Australia/Melbourne*, which may not be the same as Navidrome. + +## Dependencies A list of other roles hosted on Galaxy should go here, plus any details in regards to parameters that may need to be set for other roles, or variables that are used from other roles. -Example Playbook ----------------- +## Example Playbook Including an example of how to use your role (for instance, with variables passed in as parameters) is always nice for users too: @@ -27,12 +99,10 @@ Including an example of how to use your role (for instance, with variables passe roles: - { role: username.rolename, x: 42 } -License -------- +## License -BSD +MIT -Author Information ------------------- +## Author Information -An optional section for the role authors to include contact information, or a website (HTML is not allowed). +This role was created in 2022 by [Laur Ivan](https://www.laurivan.com). diff --git a/defaults/main.yml b/defaults/main.yml index 0b44b93..8dd1777 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -1,2 +1,27 @@ --- -# defaults file for navidrome \ No newline at end of file +# defaults file for navidrome + +navidrome_image_version: 'latest' + +navidrome_config_volume: '/mnt/config-local/navidrome' +navidrome_music_volume: '/mnt/music' + +navidrome_host_port: 48533 + +timezone: 'Europe/Brussels' + +# Bonob +bonob_enabled: false +bonob_image_version: 'latest' +bonob_host_port: 48534 +bonob_icon_color: "beige" +bonob_icon_background: "red" + +## Bonob sonos settings +bonob_sonos_auto_register: 'true' +bonob_sonos_device_discovery: 'true' +bonob_sonos_seed_host: +bonob_sonos_service_id: "246" + +## Subsonic +bonob_subsonic_custom_clients: 'audio/flac' diff --git a/meta/main.yml b/meta/main.yml index 0a2471f..cb94983 100644 --- a/meta/main.yml +++ b/meta/main.yml @@ -1,54 +1,35 @@ galaxy_info: - author: your name + author: Laur Ivan namespace: laurivan - description: your role description - company: your company (optional) + role_name: navidrome + description: Navidrome and Bonob installation via docker + license: MIT - # If the issue tracker for your role is not on github, uncomment the - # next line and provide a value - # issue_tracker_url: http://example.com/issue/tracker + min_ansible_version: "2.4" + min_ansible_container_version: "2.4" - # Choose a valid license ID from https://spdx.org - some suggested licenses: - # - BSD-3-Clause (default) - # - MIT - # - GPL-2.0-or-later - # - GPL-3.0-only - # - Apache-2.0 - # - CC-BY-4.0 - license: license (GPL-2.0-or-later, MIT, etc) + platforms: + - name: Debian + versions: + - buster + - bullseye + - name: Ubuntu + versions: + - bionic + - focal + - jammy + - name: Alpine + version: + - all + - name: ArchLinux + versions: + - all - min_ansible_version: 2.9 - - # If this a Container Enabled role, provide the minimum Ansible Container version. - # min_ansible_container_version: - - # - # Provide a list of supported platforms, and for each platform a list of versions. - # If you don't wish to enumerate all versions for a particular platform, use 'all'. - # To view available platforms and versions (or releases), visit: - # https://galaxy.ansible.com/api/v1/platforms/ - # - # platforms: - # - name: Fedora - # versions: - # - all - # - 25 - # - name: SomePlatform - # versions: - # - all - # - 1.0 - # - 7 - # - 99.99 - - galaxy_tags: [] - # List tags for your role here, one per line. A tag is a keyword that describes - # and categorizes the role. Users find roles by searching for tags. Be sure to - # remove the '[]' above, if you add tags to this list. - # - # NOTE: A tag is limited to a single word comprised of alphanumeric characters. - # Maximum 20 tags per role. + galaxy_tags: + - music + - sound + - navidrome + - bonob + - docker dependencies: [] - # List your role dependencies here, one per line. Be sure to remove the '[]' above, - # if you add dependencies to this list. - \ No newline at end of file diff --git a/molecule/default/cleanup.yml b/molecule/default/cleanup.yml new file mode 100644 index 0000000..67a9e68 --- /dev/null +++ b/molecule/default/cleanup.yml @@ -0,0 +1,23 @@ +--- +- name: Clean up + hosts: all + gather_facts: true + tasks: + - name: Check if the docker-compose file exists. + ansible.builtin.stat: + path: "~/plausible/docker-compose.yml" + register: docker_compose_file + + - name: Remove docker-compose. + community.docker.docker_compose: + project_src: ~/navidrome/ + build: false + state: absent + when: docker_compose_file.stat.exists + become: false + + - name: Remove the docker-compose file + ansible.builtin.file: + path: "~/navidrome/docker-compose.yml" + state: absent + when: docker_compose_file.stat.exists diff --git a/molecule/default/converge.yml b/molecule/default/converge.yml index 9c6ec2d..a629784 100644 --- a/molecule/default/converge.yml +++ b/molecule/default/converge.yml @@ -1,8 +1,12 @@ --- - name: Converge hosts: all - gather_facts: false - tasks: - - name: "Include laurivan.navidrome" - ansible.builtin.include_role: - name: "laurivan.navidrome" + # gather_facts: false + pre_tasks: + - name: "Include necessary variables" + ansible.builtin.include_vars: + file: "../../.env.yml" + + roles: + - role: laurivan.navidrome + diff --git a/molecule/default/create.yml b/molecule/default/create.yml deleted file mode 100644 index 09489e3..0000000 --- a/molecule/default/create.yml +++ /dev/null @@ -1,35 +0,0 @@ ---- -- name: Create - hosts: localhost - connection: local - gather_facts: false - no_log: "{{ molecule_no_log }}" - tasks: - - # TODO: Developer must implement and populate 'server' variable - - - when: server.changed | default(false) | bool - block: - - name: Populate instance config dict - ansible.builtin.set_fact: - instance_conf_dict: { - 'instance': "{{ }}", - 'address': "{{ }}", - 'user': "{{ }}", - 'port': "{{ }}", - 'identity_file': "{{ }}", } - with_items: "{{ server.results }}" - register: instance_config_dict - - - name: Convert instance config dict to a list - ansible.builtin.set_fact: - instance_conf: "{{ instance_config_dict.results | map(attribute='ansible_facts.instance_conf_dict') | list }}" - - - name: Dump instance config - ansible.builtin.copy: - content: | - # Molecule managed - - {{ instance_conf | to_json | from_json | to_yaml }} - dest: "{{ molecule_instance_config }}" - mode: 0600 diff --git a/molecule/default/destroy.yml b/molecule/default/destroy.yml index dd6e220..27a067c 100644 --- a/molecule/default/destroy.yml +++ b/molecule/default/destroy.yml @@ -6,6 +6,10 @@ no_log: "{{ molecule_no_log }}" tasks: # Developer must implement. + - name: Remove the docker image + community.docker.docker_container: + name: instance-navidrome + state: absent # Mandatory configuration for Molecule to function. diff --git a/molecule/default/molecule.yml b/molecule/default/molecule.yml index 74c8557..8729d6e 100644 --- a/molecule/default/molecule.yml +++ b/molecule/default/molecule.yml @@ -1,11 +1,30 @@ --- +role_name_check: 1 dependency: name: galaxy + options: + ignore-certs: true + ignore-errors: true + role-file: molecule/requirements.yml + requirements-file: molecule/requirements.yml driver: - name: delegated + name: docker platforms: - - name: instance + - name: instance-navidrome + image: "geerlingguy/docker-${MOLECULE_DISTRO:-centos8}-ansible:latest" + command: ${MOLECULE_DOCKER_COMMAND:-""} + volumes: + - /sys/fs/cgroup:/sys/fs/cgroup:ro + - /var/run/docker.sock:/tmp/docker_mounted.sock + privileged: true + pre_build_image: true provisioner: name: ansible + playbooks: + converge: ${MOLECULE_PLAYBOOK:-converge.yml} verifier: name: ansible +lint: | + set -e + yamllint . + ansible-lint . \ No newline at end of file diff --git a/molecule/default/prepare.yml b/molecule/default/prepare.yml new file mode 100644 index 0000000..1ab9afd --- /dev/null +++ b/molecule/default/prepare.yml @@ -0,0 +1,35 @@ +--- +- name: Setup the test machine + hosts: instance-navidrome + tasks: + - name: Check if /var/run/docker.sock already exists + ansible.builtin.stat: + path: "/var/run/docker.sock" + register: docker_sock_stat + + - name: Create docker.sock + raw: touch /var/run/docker.sock + become: true + changed_when: false + when: not docker_sock_stat.stat.exists + + - name: Move docker.sock from tmp + raw: mount --move /tmp/docker_mounted.sock /var/run/docker.sock + become: true + changed_when: false + when: not docker_sock_stat.stat.exists + + - name: Update apt cache. + apt: update_cache=yes cache_valid_time=600 + when: ansible_os_family == 'Debian' + - name: Install python requests + pip: + name: + - requests + - docker + - docker-compose + - name: Install docker + vars: + docker_service_manage: false + include_role: + name: geerlingguy.docker diff --git a/molecule/requirements.yml b/molecule/requirements.yml new file mode 100644 index 0000000..a6284de --- /dev/null +++ b/molecule/requirements.yml @@ -0,0 +1,4 @@ +--- +roles: + - geerlingguy.docker +collections: [] diff --git a/tasks/main.yml b/tasks/main.yml index 01a8752..a52a158 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -1,2 +1,34 @@ --- -# tasks file for navidrome \ No newline at end of file +# tasks file for navidrome + +- name: Set up directories + ansible.builtin.file: + state: directory + path: "{{ item }}" + owner: "{{ ansible_effective_user_id }}" + group: "{{ ansible_effective_group_id }}" + mode: "0750" + with_items: + - "{{ navidrome_config_volume }}" + - "~/navidrome" + tags: + - configuration + become: true + +- name: Write configuration files + ansible.builtin.template: + src: "{{ item }}.j2" + dest: "~/navidrome/{{ item }}" + mode: '0640' + loop: + - "docker-compose.yml" + - "env.navidrome.conf" + - "env.bonob.conf" + tags: + - configuration + +- name: Ensure navirdome is running. + community.docker.docker_compose: + project_src: ~/navidrome/ + build: false + become: false \ No newline at end of file diff --git a/templates/docker-compose.yml.j2 b/templates/docker-compose.yml.j2 new file mode 100644 index 0000000..b489063 --- /dev/null +++ b/templates/docker-compose.yml.j2 @@ -0,0 +1,31 @@ +version: "3.3" +services: + navidrome: + image: "deluan/navidrome:{{ navidrome_image_version }}" + restart: always + env_file: + - ~/navidrome/env.navidrome.conf + volumes: + - {{ navidrome_config_volume }}:/data + - {{ navidrome_music_volume }}:/music + ports: + - {{ navidrome_host_port }}:4533 + networks: + - navidrome +{% if bonob_enabled %} + bonob: + image: simojenki/bonob:{{ bonob_image_version }} + restart: always + depends_on: + - navidrome + env_file: + - ~/navidrome/env.bonob.conf + ports: + - "{{ bonob_host_port }}:3000" + networks: + - navidrome + - default +{% endif %} + +networks: + navidrome: {} \ No newline at end of file diff --git a/templates/env.bonob.conf.j2 b/templates/env.bonob.conf.j2 new file mode 100644 index 0000000..3c1603d --- /dev/null +++ b/templates/env.bonob.conf.j2 @@ -0,0 +1,15 @@ +{% if bonob_enabled %} +BNB_SONOS_AUTO_REGISTER={{ bonob_sonos_auto_register }} +BNB_SONOS_DEVICE_DISCOVERY={{ bonob_sonos_device_discovery }} +BNB_PORT=3000 +{% if bonob_sonos_seed_host %} +BNB_SONOS_SEED_HOST={{ bonob_sonos_seed_host }} +{% endif %} +BNB_SUBSONIC_URL=http://navidrome:4533 +BNB_SONOS_SERVICE_ID={{ bonob_sonos_service_id }} +BNB_URL=http://{{ hostvars[inventory_hostname]['ansible_default_ipv4']['address'] }}:{{ bonob_host_port }} +BNB_SUBSONIC_CUSTOM_CLIENTS="audio/flac" +BNB_ICON_FOREGROUND_COLOR={{ bonob_icon_color }} +BNB_ICON_BACKGROUND_COLOR={{ bonob_icon_background }} +TZ={{ timezone }} +{% endif %} diff --git a/templates/env.navidrome.conf.j2 b/templates/env.navidrome.conf.j2 new file mode 100644 index 0000000..8c92d95 --- /dev/null +++ b/templates/env.navidrome.conf.j2 @@ -0,0 +1 @@ +TZ={{timezone}} \ No newline at end of file