- name: Initialize homeserver hosts: "{{ chosen_host | default('staging1.test') }}" remote_user: "{{ chosen_user | default('senpai') }}" vars_files: - vars/local_facts.yml # REQUIRED - vars/email_settings.yml - vars/podpose_settings.yml # REQUIRED - vars/source_code.yml # REQUIRED - vars/iptables_settings@homeserver.yml - vars/caddy_settings.yml - vars/certbot_settings@homeserver.yml # REQUIRED - vars/mysql_settings.yml - vars/redis_settings.yml - vars/nextcloud_settings.yml - vars/forgejo_settings.yml - vars/opengist_settings.yml - vars/nodebb_settings.yml - vars/syncplay_settings.yml - vars/vpn_settings.yml - vars/headscale_settings.yml - vars/tailscale_settings.yml - vars/glance_settings.yml - vars/surge_settings.yml - vars/aria_settings.yml - vars/soulseek_settings.yml - vars/flexget_settings.yml # REQUIRED - vars/actual_settings.yml - vars/kavita_settings.yml - vars/stash_settings.yml - vars/git_aliases.yml # REQUIRED - vars/vim_settings.yml # REQUIRED - vars/tor_settings.yml # REQUIRED - vars/openpgp_settings.yml # REQUIRED - vars/config@{{ inventory_hostname | default('homeserver') }}.yml tasks: - name: Acquiring home of current user when: ansible_facts["system"] == "Linux" ansible.builtin.shell: cmd: "echo ~{{ ansible_user }}" register: ansible_user_home - name: Acquiring current user when: ansible_facts["system"] == "Linux" ansible.builtin.shell: cmd: "echo {{ ansible_user }}" register: current_user - name: Reorganizing userspace package groups into single list ansible.builtin.set_fact: all_userspace_pkgs: "{{ pkgs | dict2items(key_name='pkg_group', value_name='pkgs') | map(attribute='pkgs') | list | map(attribute='userspace', default='no_userspace') | list | flatten | reject('search', 'no_userspace') | map(attribute='name') | list }}" - name: Reorganizing core package groups into single list ansible.builtin.set_fact: all_core_pkgs: "{{ pkgs | dict2items(key_name='pkg_group', value_name='pkgs') | map(attribute='pkgs') | list | map(attribute='core', default='no_core') | list | flatten | reject('search', 'no_core') | map(attribute='name') | list }}" - name: Saving HTTP/(S)FTP credentials ansible.builtin.include_role: name: init-server tasks_from: netrc.yml handlers_from: userspace - name: Transferring OpenPGP / GPG keyring to managed node block: - name: Finding GPG keyrings for user delegate_facts: true delegate_to: localhost become: true become_user: "{{ local_facts['user_id'] }}" ansible.builtin.find: paths: "{{ local_facts['user_dir'] }}/.gnupg" patterns: ["^pubring\\.kbx$"] file_type: file use_regex: true register: gpg_keys - name: Creating user directory for OpenPGP / GPG keyring ansible.builtin.file: path: "{{ ansible_user_home.stdout }}/.gnupg" recurse: true owner: "{{ ansible_user }}" group: "{{ ansible_user }}" state: directory mode: "700" - name: Emitting file content as file in managed node become: true become_user: "{{ current_user.stdout }}" ansible.builtin.copy: content: "{{ lookup('file', item.path) }}" dest: "{{ ansible_user_home.stdout }}/.gnupg/{{ (((fqdn | default(inventory_hostname)) | split('.'))[:-1] | join('.')) + (idx | string) }}.kbx" owner: "{{ ansible_user }}" group: "{{ ansible_user }}" mode: "664" force: true backup: true loop: "{{ gpg_keys.files }}" loop_control: index_var: idx - name: Creating an OpenPGP / GPG batch file for OpenPGP / GPG key pair creation become: true ansible.builtin.blockinfile: path: "/tmp/gpg-key{{ idx | string }}" block: | Key-Type: {{ item.encryption_method }} Key-Length: {{ item.length | string }} Subkey-Type: {{ item.primary_subkey.encryption_method }} Subkey-Length: {{ item.primary_subkey.length | string }} Name-Real: {{ item.name }} Name-Comment: {{ item.alias }} Name-Email: {{ item.email }} Expire-Date: {{ item.expiration }} Passphrase: {{ item.password }} %pubring pubring.kbx %secring trustdb.gpg %commit %echo GPG key pair created owner: "{{ ansible_user }}" group: "{{ ansible_user }}" mode: "600" create: true backup: true loop: "{{ gpg.keypairs }}" loop_control: index_var: idx register: gpg_key_requests - name: Creating OpenPGP / GPG key pair ansible.builtin.command: argv: - gpg - "--batch" - "--gen-key" - "/tmp/gpg-key{{ idx | string }}" loop: "{{ gpg.keypairs }}" loop_control: index_var: idx - name: Saving OpenPGP / GPG key pair passphrases become: true ansible.builtin.copy: content: "{{ item.password }}" dest: "/tmp/gpg-key-pass{{ idx | string }}" owner: "{{ ansible_user }}" group: "{{ ansible_user }}" mode: "600" force: true backup: true loop: "{{ gpg.keypairs }}" loop_control: index_var: idx # @TODO add "show" (debug task module) option task, as counterpart to below fetch module task - name: Acquiring the OpenPGP / GPG key pair passphrases when: true ansible.builtin.fetch: src: "/tmp/gpg-key-pass{{ idx | string }}" dest: "./.tmp/{{ inventory_hostname }}-openpgp/openpgp.pass{{ idx | string }}" flat: true loop: "{{ gpg.keypairs }}" loop_control: index_var: idx - name: Installing requisite packages ansible.builtin.include_role: name: init-server tasks_from: userspace@install-pkgs handlers_from: userspace - name: Configuring aliases for using git when: "'git' in all_core_pkgs or 'git' in all_userspace_pkgs" community.general.git_config: name: "alias.{{ item[0] }}" scope: global value: "{{ item[1] }}" loop: "{{ git_aliases }}" - name: Checking presence of dependency for SoulSeek CLI when: "('nvm' in all_core_pkgs or 'nvm' in all_userspace_pkgs) and not soulseek.containerized" block: - name: Installing SoulSeek CLI community.general.npm: name: "soulseek-cli" global: true state: present - name: Checking presence of dependency for GoCryptFS # when: "'gocryptfs' in all_core_pkgs or 'gocryptfs' in all_userspace_pkgs" when: false block: - name: Allowing users ability to allow others for FUSE mount become: true ansible.builtin.lineinfile: path: /etc/fuse.conf regexp: "^#user_allow_other" insertafter: EOF line: "user_allow_other" - name: Creating prerequisite directories for GoCryptFS cipher configuration files ansible.builtin.file: path: "{{ ansible_user_home.stdout }}/.config/gocryptfs" recurse: true owner: "{{ ansible_user }}" group: "{{ ansible_user }}" mode: "755" state: directory register: cipher_configs - name: Creating prerequisite directories for GoCryptFS XXX cipher ansible.builtin.file: path: "{{ ansible_user_home.stdout }}/.ciphers/.xxx" recurse: true owner: "{{ ansible_user }}" group: "{{ ansible_user }}" mode: "755" state: directory register: xxx_cipher - name: Creating password for GoCryptFS XXX cipher become: true ansible.builtin.copy: content: "{{ lookup('password', './.tmp/' + inventory_hostname + '-xxx@gocryptfs.pass', chars=['ascii_lowercase', 'digits'], length=32) }}" dest: /xxx-pass owner: "{{ ansible_user }}" group: "{{ ansible_user }}" mode: "600" force: true backup: true - name: Creating GoCryptFS XXX cipher ansible.builtin.command: argv: - gocryptfs - "--init" - "--sharedstorage" - "--passfile" - /xxx-pass - "{{ xxx_cipher.path }}" register: xxx_master_key - name: Creating file containing XXX master key become: true ansible.builtin.copy: content: "{{ xxx_master_key.stdout }}" dest: /tmp/xxx-master-key owner: "{{ ansible_user }}" group: "{{ ansible_user }}" mode: "600" force: true backup: true - name: Copying GoCryptFS XXX cipher configuration file over to corresponding directory ansible.builtin.copy: src: "{{ ansible_user_home.stdout }}/.ciphers/.xxx/gocryptfs.conf" remote_src: true dest: "{{ ansible_user_home.stdout }}/.config/gocryptfs/xxx.conf" owner: "{{ ansible_user }}" group: "{{ ansible_user }}" mode: "600" force: true backup: true - name: Removing GoCryptFS XXX cipher configuration file ansible.builtin.file: path: "{{ ansible_user_home.stdout }}/.ciphers/.xxx/gocryptfs.conf" state: absent - name: Creating prerequisite directories for XXX downloads cipher ansible.builtin.file: path: "{{ ansible_user_home.stdout }}/.ciphers/downloads/.xxx" recurse: true owner: "{{ ansible_user }}" group: "{{ ansible_user }}" mode: "755" state: directory register: xxx_downloads_cipher - name: Creating password for XXX downloads cipher become: true ansible.builtin.copy: content: "{{ lookup('password', './.tmp/' + inventory_hostname + '-downloads_xxx@gocryptfs.pass', chars=['ascii_lowercase', 'digits'], length=32) }}" dest: /xxx-downloads-pass owner: "{{ ansible_user }}" group: "{{ ansible_user }}" mode: "600" force: true backup: true - name: Creating GoCryptFS XXX downloads cipher ansible.builtin.command: argv: - gocryptfs - "--init" - "--sharedstorage" - "--passfile" - /xxx-downloads-pass - "{{ xxx_downloads_cipher.path }}" register: xxx_downloads_master_key - name: Creating file containing XXX downloads master key become: true ansible.builtin.copy: content: "{{ xxx_downloads_master_key.stdout }}" dest: /tmp/xxx-downloads-master-key owner: "{{ ansible_user }}" group: "{{ ansible_user }}" mode: "600" force: true backup: true - name: Copying GoCryptFS XXX downloads cipher configuration file over to corresponding directory ansible.builtin.copy: src: "{{ ansible_user_home.stdout }}/.ciphers/downloads/.xxx/gocryptfs.conf" remote_src: true dest: "{{ ansible_user_home.stdout }}/.config/gocryptfs/downloads-xxx.conf" owner: "{{ ansible_user }}" group: "{{ ansible_user }}" mode: "600" force: true backup: true - name: Removing GoCryptFS XXX downloads cipher configuration file ansible.builtin.file: path: "{{ ansible_user_home.stdout }}/.ciphers/downloads/.xxx/gocryptfs.conf" state: absent - name: Pausing to inquire about how to proceed ansible.builtin.pause: prompt: "Type \"fetch\" to get the cipher master keys, or \"show\" to see contents for manual copying instead" echo: true register: data_method - name: Providing XXX cipher master key to control node machine when: data_method.user_input == "fetch" ansible.builtin.fetch: src: /tmp/xxx-master-key dest: "./.tmp/{{ inventory_hostname }}-xxx@gocryptfs.key" flat: true - name: Providing XXX downloads cipher master key to control node machine when: data_method.user_input == "fetch" ansible.builtin.fetch: src: /tmp/xxx-downloads-master-key dest: "./.tmp/{{ inventory_hostname }}-downloads_xxx@gocryptfs.key" flat: true - name: Presenting XXX cipher master key to control node machine when: data_method.user_input == "show" ansible.builtin.debug: msg: "{{ xxx_master_key.stdout }}" - name: Presenting XXX downloads cipher master key to control node machine when: data_method.user_input == "show" ansible.builtin.debug: msg: "{{ xxx_downloads_master_key.stdout }}" - name: Giving opportunity to manually copy contents of GoCryptFS cipher master keys when: data_method.user_input == "show" ansible.builtin.pause: - name: Creating requisite hidden XXX directory for NSFW video torrent links file ansible.builtin.file: path: "{{ ansible_user_home.stdout }}/.xxx" recurse: true owner: "{{ ansible_user }}" group: "{{ ansible_user }}" state: directory mode: "755" # - name: Mounting GoCryptFS XXX cipher # ansible.builtin.command: # argv: # - gocryptfs # - "--rw" # - "--allow_other" # - "--config" # - "{{ ansible_user_home.stdout }}/.config/gocryptfs/xxx.conf" # - "--passfile" # - /xxx-pass # - "{{ xxx_cipher.path }}" # - "{{ ansible_user_home.stdout }}/.xxx" - name: Mounting GoCryptFS XXX cipher ansible.posix.mount: path: "{{ ansible_user_home.stdout }}/.xxx" src: "{{ xxx_cipher.path }}" fstype: fuse./usr/bin/gocryptfs opts: "rw,allow_other,quiet,config={{ ansible_user_home.stdout }}/.config/gocryptfs/xxx.conf,passfile=/xxx-pass" dump: "0" passno: "0" state: mounted - name: Creating requisite hidden file for NSFW video torrent links ansible.builtin.file: path: "{{ ansible_user_home.stdout }}/.xxx/.vids.csv" owner: "{{ ansible_user }}" group: "{{ ansible_user }}" state: touch mode: "644" - name: Creating requisite hidden XXX download paths ansible.builtin.file: path: "{{ ansible_user_home.stdout }}/downloads/.xxx" recurse: true owner: "{{ ansible_user }}" group: "{{ ansible_user }}" state: directory mode: "755" # - name: Mounting GoCryptFS XXX downloads cipher # ansible.builtin.command: # argv: # - gocryptfs # - "--rw" # - "--allow_other" # - "--config" # - "{{ ansible_user_home.stdout }}/.config/gocryptfs/downloads-xxx.conf" # - "--passfile" # - /xxx-downloads-pass # - "{{ xxx_downloads_cipher.path }}" # - "{{ ansible_user_home.stdout }}/downloads/.xxx" - name: Mounting GoCryptFS XXX downloads cipher ansible.posix.mount: path: "{{ ansible_user_home.stdout }}/downloads/.xxx" src: "{{ xxx_downloads_cipher.path }}" fstype: fuse./usr/bin/gocryptfs opts: "rw,allow_other,quiet,config={{ ansible_user_home.stdout }}/.config/gocryptfs/downloads-xxx.conf,passfile=/xxx-downloads-pass" dump: "0" passno: "0" state: mounted - name: Creating requisite hidden download paths ansible.builtin.file: path: "{{ ansible_user_home.stdout }}/downloads/.xxx/flexget/vids/torrents" recurse: true owner: "{{ ansible_user }}" group: "{{ ansible_user }}" state: directory mode: "755" - name: Creating requisite hidden download paths ansible.builtin.file: path: "{{ ansible_user_home.stdout }}/downloads/.xxx/media/vids" recurse: true owner: "{{ ansible_user }}" group: "{{ ansible_user }}" state: directory mode: "755" - name: Checking presence of dependency for flexget when: "('uv' in all_core_pkgs or 'uv' in all_userspace_pkgs) and flexget.enabled and not flexget.containerized" block: - name: Installing flexget become: true become_user: "{{ current_user.stdout }}" ansible.builtin.command: argv: - uv - tool - install - "flexget[locked,ftp,sftp]" - "--with" - pysocks - name: Creating requisite download paths ansible.builtin.file: path: "{{ ansible_user_home.stdout }}/media/vids/{{ item }}" recurse: true owner: "{{ ansible_user }}" group: "{{ ansible_user }}" state: directory mode: "755" loop: - series - features - name: Creating requisite download paths ansible.builtin.file: path: "{{ ansible_user_home.stdout }}/downloads/flexget/vids/series/torrents" recurse: true owner: "{{ ansible_user }}" group: "{{ ansible_user }}" state: directory mode: "755" - name: Creating requisite download paths ansible.builtin.file: path: "{{ ansible_user_home.stdout }}/downloads/flexget/vids/torrents" recurse: true owner: "{{ ansible_user }}" group: "{{ ansible_user }}" state: directory mode: "755" - name: Creating requisite hidden download paths ansible.builtin.file: path: "{{ ansible_user_home.stdout }}/downloads/media/vids/{{ item }}" recurse: true owner: "{{ ansible_user }}" group: "{{ ansible_user }}" state: directory mode: "755" loop: - series - features - name: Creating requisite hidden file for film torrent links ansible.builtin.file: path: "{{ ansible_user_home.stdout }}/downloads/media/vids/features/.films.csv" owner: "{{ ansible_user }}" group: "{{ ansible_user }}" state: touch mode: "644" - name: Creating requisite directory for NSFW video torrent links file ansible.builtin.file: path: "{{ ansible_user_home.stdout }}/.xxx" recurse: true owner: "{{ ansible_user }}" group: "{{ ansible_user }}" state: directory mode: "755" - name: Creating requisite directory for flexget ansible.builtin.file: path: "{{ ansible_user_home.stdout }}/.flexget" recurse: true owner: "{{ ansible_user }}" group: "{{ ansible_user }}" state: directory mode: "755" - name: Configuring flexget become: true become_user: "{{ current_user.stdout }}" ansible.builtin.template: src: roles/init-server/templates/user/flexget/config.yml.j2 variable_start_string: "<<" variable_end_string: ">>" dest: "{{ ansible_user_home.stdout }}/.flexget/config.yml" owner: "{{ ansible_user }}" group: "{{ ansible_user }}" force: true backup: true # validate: "flexget check" - name: Creating a CRON job for flexget ansible.builtin.cron: name: Run flexget minute: "*/60" hour: "4-15" weekday: "1-5" job: "{{ ansible_user_home.stdout }}/.local/bin/flexget --cron execute" - name: Configure installed packages ansible.builtin.meta: flush_handlers - name: Disabling root user shell login become: true ansible.builtin.user: name: root shell: /sbin/nologin tags: - disable_root_shell - name: Disable login for root user altogether become: true ansible.builtin.user: name: root password: "'*'" tags: - disable_root_login