diff --git a/.gitignore b/.gitignore index f6a6c47..8d6d61c 100644 --- a/.gitignore +++ b/.gitignore @@ -4,17 +4,9 @@ /hosts.yml /hosts.yaml /hosts.json -*.bak -/group_vars/armitage.yml -/group_vars/sukaato.yml -/group_vars/armitage.yml -/group_vars/sukaato.yml -/vars/aria_api.yml -/vars/vpn_server.yml -/vars/tail_net.yml -/vars/local_facts.yml # Ansible runtime and backups +*.bak *.original *.tmp /.tmp/ @@ -27,12 +19,14 @@ /.devcontainer/ .lock /.cache/ +/roles/**/files/user/wg/containerized/*.conf # Try tyo avoid any plain-text passwords *pwd* *pass* *password* *secret* +*.key roles/**/vars/* roles/**/vars/** diff --git a/administrate@homeserver.yml b/administrate@homeserver.yml index 7adc511..d09951e 100644 --- a/administrate@homeserver.yml +++ b/administrate@homeserver.yml @@ -1,13 +1,34 @@ - name: Initialize homeserver - hosts: "{{ chosen_host | default('armitage') }}" + hosts: "{{ chosen_host | default('staging1.test') }}" remote_user: "{{ chosen_user | default('senpai') }}" vars_files: + - vars/email_settings.yml + - vars/podpose_settings.yml # REQUIRED + - vars/source_code.yml # REQUIRED + - vars/caddy_settings.yml + - vars/certbot_settings@homeserver.yml # REQUIRED + - vars/mysql_settings.yml + - vars/redis_settings.yml + - vars/nextcloud_settings.yml + - vars/gitea_settings.yml + - vars/opengist_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/flexget_settings.yml # REQUIRED - vars/git_aliases.yml # REQUIRED - - vars/sox_prox.yml # REQUIRED - - vars/flexget_dls.yml # REQUIRED - - vars/aria_api.yml # REQUIRED + - vars/vim_settings.yml # REQUIRED + - vars/tor_settings.yml # REQUIRED - vars/config@{{ inventory_hostname | default('homeserver') }}.yml tasks: + - name: Saving HTTP/(S)FTP credentials + ansible.builtin.include_role: + name: init-server + tasks_from: netrc.yml + handlers_from: userspace - name: Installing requisite packages ansible.builtin.include_role: name: init-server @@ -39,19 +60,19 @@ - disable_root_login - 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') | list | flatten }}" + 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') | 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') | list | flatten }}" + 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') | list }}" - name: Configuring aliases for using git - when: "'git' in all_core_pkgs" + 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 flexget - when: "'uv' in all_core_pkgs" + when: "'uv' in all_core_pkgs and flexget.enabled" block: - name: Installing flexget become: true @@ -139,6 +160,7 @@ group: "{{ ansible_user }}" force: true backup: true + # validate: "flexget check" - name: Creating a CRON job for flexget ansible.builtin.cron: name: Run flexget @@ -146,3 +168,39 @@ hour: "4-15" weekday: "1-5" job: "{{ ansible_user_home.stdout }}/.local/bin/flexget --cron execute" + - name: Opening port 51820 + become: true + ansible.builtin.iptables: + chain: INPUT + protocol: "{{ item }}" + destination_port: 51820 + jump: ACCEPT + comment: Open up port 51820 + loop: + - udp + - tcp + - name: Opening port 443 + become: true + ansible.builtin.iptables: + chain: INPUT + protocol: "{{ item }}" + destination_port: 443 + jump: ACCEPT + comment: Open up port 443 + loop: + - udp + - tcp + - name: Opening ports + become: true + ansible.builtin.iptables: + chain: INPUT + protocol: tcp + destination_port: "{{ item }}" + jump: ACCEPT + comment: "Open up port {{ (item | string) }}" + loop: + - 80 + - 465 + - 587 + - 995 + - 993 \ No newline at end of file diff --git a/administrate@vps.yml b/administrate@vps.yml index 3f78f65..4fabb76 100644 --- a/administrate@vps.yml +++ b/administrate@vps.yml @@ -1,9 +1,12 @@ - name: Initialize VPS - hosts: "{{ chosen_host | default('sukaato') }}" + hosts: "{{ chosen_host | default('staging0.test') }}" remote_user: "{{ chosen_user | default('senpai') }}" vars_files: + - vars/surge_settings.yml - vars/git_aliases.yml # REQUIRED - vars/vim_settings.yml # REQUIRED + - vars/podpose_settings.yml # REQUIRED + - vars/certbot_settings.yml # REQUIRED - vars/config@{{ inventory_hostname | default('vps') }}.yml tasks: - name: Installing requisite packages @@ -42,4 +45,40 @@ name: "alias.{{ item[0] }}" scope: global value: "{{ item[1] }}" - loop: "{{ git_aliases }}" + loop: "{{ git_aliases }}" + - name: Opening port 51820 + become: true + ansible.builtin.iptables: + chain: INPUT + protocol: "{{ item }}" + destination_port: 51820 + jump: ACCEPT + comment: Open up port 51820 + loop: + - udp + - tcp + - name: Opening port 443 + become: true + ansible.builtin.iptables: + chain: INPUT + protocol: "{{ item }}" + destination_port: 443 + jump: ACCEPT + comment: Open up port 443 + loop: + - udp + - tcp + - name: Opening ports + become: true + ansible.builtin.iptables: + chain: INPUT + protocol: tcp + destination_port: "{{ item }}" + jump: ACCEPT + comment: "Open up port {{ (item | string) }}" + loop: + - 80 + - 465 + - 587 + - 995 + - 993 diff --git a/group_vars/homeserver.yml b/group_vars/homeserver.yml deleted file mode 100644 index 30f1b0d..0000000 --- a/group_vars/homeserver.yml +++ /dev/null @@ -1,690 +0,0 @@ -# @TODO create inventory group variables akin to structure of sukaato group's for homeserver -# > representing password for Linux root user account of VPS -password: "" -# representing hostname for LAN server; same as host or group variable name -instance: armitage -# > representing Linux distro or OS image to be used for VPS -# operating_system: "tftp://hikiki.local:69/debian.iso" -operating_system: "" -# ]> of control node or local SSH key basenames -ssh_keys: [] -# > list of administrative users (in Linux, users that can use "sudo") -admins: - - username: senpai # arbitrary valid user name - services: "" # ]> if linux system user, assocated servce - # ]> list of control node or local SSH key basenames for this user - ssh_keys: [] - # > hashed (and maybe salted) password - password: "" -# :]> package groups -pkgs: - # :]> representing package groups installed by package manager via repositories - mngr: - # ]> representing system-level or essential packages - core: - - name: xz-utils - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - - name: wireguard - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - - name: wireguard-tools - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - - name: sudo - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - - name: kitty-terminfo - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - - name: whois - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - - name: smartmontools - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - - name: vim - uri: ~ - sources: ~ - sigkey: ~ - types: ~ - suites: ~ - comps: ~ - handler: vim - - name: vim-vimwiki - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - - name: vim-doc - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - # - name: flatpak - # uri: ~ - # sources: ~ - # sigkey: ~ - # types: ~ - # suites: ~ - # comps: ~ - # handler: ~ - - name: snapd - uri: ~ - sources: ~ - sigkey: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - - name: git - uri: ~ - sources: ~ - sigkey: ~ - types: ~ - suites: ~ - comps: ~ - handler: git - - name: git-delta - uri: ~ - sources: ~ - sigkey: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - - name: git-doc - uri: ~ - sources: ~ - sigkey: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - - name: git-man - uri: ~ - sources: ~ - sigkey: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - - name: fail2ban - uri: ~ - sources: ~ - sigkey: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - - name: crowdsec - uri: ~ - sources: ~ - sigkey: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - - name: glow - uri: ~ - sigkey: "https://repo.charm.sh/apt/gpg.key" - sources: "https://repo.charm.sh/apt/" - types: deb - suites: "*" - comps: "*" - handler: ~ - - name: pandoc - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - - name: curl - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - - name: build-essential - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - - name: fastfetch - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - - name: gcc - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - - name: dpkg-dev - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - - name: ufw - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - - name: avahi-daemon - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - - name: avahi-utils - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - - name: libpam-google-authenticator - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - - name: cron - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - - name: cron-daemon-common - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - - name: tor - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: tor - - name: libpam-u2f - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - - name: pamu2fcfg - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - - name: pcscd - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - - name: tftpd-hpa - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - - name: gocryptfs - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - - name: cryfs - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - - name: tmux - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - - name: cpu-checker - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - - name: libpam-doc - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - - name: burp - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - - name: rsync - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - - name: gnupg - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - - name: gnupg-agent - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - userspace: - - name: neovim - uri: ~ - sources: ~ - sigkey: ~ - types: ~ - suites: ~ - comps: ~ - handler: neovim - - name: sqlite3 - uri: ~ - sources: ~ - sigkey: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - - name: podman - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - - name: podman-compose - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - - name: distrobox - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - - name: proftpd-core - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - - name: proftpd-doc - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - - name: proftpd-mod-crypto - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - - name: proftpd-mod-ldap - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - - name: proftpd-mod-sqlite - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - - name: erlang - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - - name: erlang-doc - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - - name: erlang-hex - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - - name: elixir - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - - name: python3.13 - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - - name: python3-venv - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - - name: python3-pip - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - - name: python3-doc - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - - name: golang - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - - name: golang-doc - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - - name: hugo - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - - name: yt-dlp - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - - name: syncthing-discosrv - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - - name: syncthing-relaysrv - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - - name: syncthing-relaysrv - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - - name: rclone - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - - name: aria2 - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - - name: mopidy - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - - name: mopidy-mpd - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - - name: minidlna - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - # :]> representing package groups installed by shell scripts - script: - # ]> representing user-level or supplemental shell script installations - userspace: - - name: radicle - src: "https://radicle.dev/install" - pre: ~ - post: ~ - handler: radicle - - name: rustup - src: "https://sh.rustup.rs" - pre: ~ - post: ~ - handler: rustup - - name: julia - src: "https://install.julialang.org" - pre: ~ - post: ~ - handler: julia - - name: uv - src: "https://astral.sh/uv/install.sh" - pre: ~ - post: ~ - handler: uv - # :]> representing package groups installed from source archives - archive: - # ]> representing user-level or supplemental source archives - userspace: - # - name: surge - # src: "https://github.com/SurgeDM/Surge/releases/download/v0.8.6/Surge_0.8.6_linux_amd64.tar.gz" - # deploy: ~ - # pre: ~ - # post: ~ - # handler: surge - - name: nvm - src: "https://nodejs.org/dist/v24.16.0/node-v24.16.0-linux-x64.tar.xz" - deploy: ~ - pre: ~ - post: ~ - handler: nvm - - name: difftastic - src: "https://github.com/Wilfred/difftastic/releases/download/0.69.0/difft-x86_64-unknown-linux-gnu.tar.gz" - deploy: ~ - pre: ~ - post: ~ - handler: difftastic - # :]> representing package groups installed from source git repositories - git_repos: - # userspace: - # # @TODO use below to build Podman container instead, to deploy with podman-compose - # # @NOTE https://github.com/papis/papis and https://papis.readthedocs.io/en/latest/ - # - name: papis - # src: "https://github.com/papis/papis.git" - # branch: main - # deploy: ~ - # pre: ~ - # post: ~ - # handler: false - - name: quartz - src: "https://github.com/jackyzha0/quartz.git" - branch: v5.0.0 - deploy: ~ - pre: ~ - post: ~ - handler: quartz diff --git a/group_vars/sukaato_test.yml b/group_vars/sukaato_test.yml deleted file mode 100644 index ddf8dce..0000000 --- a/group_vars/sukaato_test.yml +++ /dev/null @@ -1,550 +0,0 @@ -# > representing password for Linux root user account of VPS -password: "{{ lookup('password', './.tmp/sukaato_test.pass', seed='sukaato_test', encrypt='sha512_crypt') }}" -# > representing API token for VPS cloud service -token: ~ -# representing name and hostname of VPS to be made in VPS cloud service -instance: sukaato -# > representing region options from or for given VPS cloud service -origin: us-east -# > representing Linux distro or OS image available in VPS service to be used for VPS -operating_system: linode/debian13 -# ]> list of control node or local SSH key basenames for root user -ssh_keys: - - ed25519@staging - - ecdsa@staging -# > list of administrative users (in Linux, users that can use "sudo") -admins: - - username: senpai # arbitrary valid user name - services: ~ # ]> if linux system user, assocated servce - # ]> list of control node or local SSH key basenames for this user - ssh_keys: - # @TODO add secondary and teriary Yubikeys - - ecdsa-37851076-sk@staging - - ed25519-37851076-sk@staging - # > hashed (and maybe salted) password - password: "{{ lookup('password', './.tmp/senpai@sukaato_test.pass', seed='senpai:sukaato_test', encrypt='sha512_crypt') }}" -# :]> package groups -pkgs: - # :]> representing package groups installed by package manager via repositories - mngr: - # ]> representing system-level or essential packages - core: - - name: sudo - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - - name: xz-utils - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - - name: wireguard - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - - name: wireguard-tools - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - - name: vagrant - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - - name: qemu-system - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - - name: cron - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - - name: cron-daemon-common - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - - name: qemu-kvm - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - - name: bridge-utils - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - - name: libvirt-clients - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - - name: libvirt-daemon-system - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - - name: gcc - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - - name: git-doc - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - - name: git-delta - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - - name: fastfetch - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - - name: git - uri: ~ - sources: ~ - sigkey: ~ - types: ~ - suites: ~ - comps: ~ - handler: git - - name: fail2ban - uri: ~ - sources: ~ - sigkey: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - - name: crowdsec - uri: ~ - sources: ~ - sigkey: ~ - types: ~ - suites: ~ - comps: ~ - handler: crowdsec - - name: glow - uri: ~ - sigkey: "https://repo.charm.sh/apt/gpg.key" - sources: "https://repo.charm.sh/apt/" - types: deb - suites: "*" - comps: "*" - handler: ~ - - name: vim-vimwiki - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - - name: vim-doc - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - - name: tor - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - - name: i2pd - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - - name: whois - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - # @TODO make sure to create handler inclusion of tasks in file under/at `tasks/contingent/pkg` for below - - name: iptables - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - - name: libpam-google-authenticator - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - - name: gnupg - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - - name: gnupg-agent - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - - name: gocryptfs - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - - name: cryfs - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - - name: tmux - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - - name: cpu-checker - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - - name: libpam-doc - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - - name: headscale - uri: "https://github.com/juanfont/headscale/releases/download/v0.28.0/headscale_0.28.0_linux_amd64.deb" - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: headscale - userspace: - - name: vim - uri: ~ - sources: ~ - sigkey: ~ - types: ~ - suites: ~ - comps: ~ - handler: vim - - name: neovim - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: neovim - - name: distrobox - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - - name: proftpd-core - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - - name: proftpd-doc - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - - name: proftpd-mod-crypto - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - - name: proftpd-mod-ldap - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - - name: proftpd-mod-sqlite - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - - name: aria2 - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - - name: erlang - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - - name: erlang-hex - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - - name: elixir - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - - name: python3.13 - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - - name: python3-venv - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - - name: python3-pip - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - - name: golang - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - - name: yt-dlp - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - - name: syncthing-discosrv - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - - name: syncthing-relaysrv - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - - name: rclone - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - - name: burp - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - - name: rsync - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - # :]> representing package groups installed by shell scripts - script: - # ]> representing user-level or supplemental shell script installations - userspace: - - name: radicle - src: "https://radicle.dev/install" - pre: ~ - post: ~ - handler: radicle - - name: rustup - src: "https://sh.rustup.rs" - pre: ~ - post: ~ - handler: rustup - - name: julia - src: "https://install.julialang.org" - pre: ~ - post: ~ - handler: julia - - name: uv - src: "https://astral.sh/uv/install.sh" - pre: ~ - post: ~ - handler: uv - # :]> representing package groups installed from source archives - archive: - # ]> representing user-level or supplemental source archives - userspace: - - name: surge - src: "https://github.com/SurgeDM/Surge/releases/download/v0.8.6/Surge_0.8.6_linux_amd64.tar.gz" - deploy: ~ - pre: ~ - post: ~ - handler: surge - - name: nvm - src: "https://nodejs.org/dist/v24.16.0/node-v24.16.0-linux-x64.tar.xz" - deploy: ~ - pre: ~ - post: ~ - handler: nvm - - name: difftastic - src: "https://github.com/Wilfred/difftastic/releases/download/0.69.0/difft-x86_64-unknown-linux-gnu.tar.gz" - deploy: ~ - pre: ~ - post: ~ - handler: difftastic - # :]> representing package groups installed from source git repositories - git_repos: - # userspace: - # - name: quartz - # src: "https://github.com/jackyzha0/quartz.git" - # branch: v5.0.0 - # deploy: ~ - # pre: ~ - # post: ~ - # handler: ~ - binaries: - core: - - name: dsnet - src: "https://github.com/naggie/dsnet/releases/download/v0.8.1/dsnet-linux-amd64" - handler: dsnet diff --git a/group_vars/vps.yml b/host_vars/staging0.test.yml similarity index 68% rename from group_vars/vps.yml rename to host_vars/staging0.test.yml index ae2079d..f9f2fd2 100644 --- a/group_vars/vps.yml +++ b/host_vars/staging0.test.yml @@ -1,77 +1,48 @@ # > representing password for Linux root user account of VPS -password: "" +password: "{{ lookup('password', './.tmp/' + inventory_hostname + '.pass', seed=inventory_hostname, encrypt='sha512_crypt') }}" # > representing API token for VPS cloud service -token: "" -# representing name and hostname of VPS to be made in VPS cloud service -instance: sukaato +token: ~ # > representing region options from or for given VPS cloud service origin: us-east # > representing Linux distro or OS image available in VPS service to be used for VPS operating_system: linode/debian13 # ]> list of control node or local SSH key basenames for root user -ssh_keys: [] +ssh_keys: + - ed25519@staging + - ecdsa@staging # > list of administrative users (in Linux, users that can use "sudo") admins: - username: senpai # arbitrary valid user name services: ~ # ]> if linux system user, assocated servce # ]> list of control node or local SSH key basenames for this user - ssh_keys: [] + ssh_keys: + # @TODO add secondary and teriary Yubikeys + - ecdsa-37851076-sk@staging + - ed25519-37851076-sk@staging # > hashed (and maybe salted) password - password: "" + password: "{{ lookup('password', './.tmp/senpai@' + inventory_hostname + '.pass', seed='senpai@' + inventory_hostname, encrypt='sha512_crypt') }}" # :]> package groups pkgs: # :]> representing package groups installed by package manager via repositories mngr: # ]> representing system-level or essential packages core: - - name: sudo + - name: zfsutils-linux uri: ~ sigkey: ~ sources: ~ types: ~ suites: ~ comps: ~ - handler: ~ - - name: xz-utils + handler: default + - name: zfs-dkms uri: ~ sigkey: ~ sources: ~ types: ~ suites: ~ comps: ~ - handler: ~ - - name: wireguard - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - - name: wireguard-tools - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - - name: vagrant - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - - name: qemu-system - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ + handler: default - name: cron uri: ~ sigkey: ~ @@ -79,7 +50,7 @@ pkgs: types: ~ suites: ~ comps: ~ - handler: ~ + handler: default - name: cron-daemon-common uri: ~ sigkey: ~ @@ -87,7 +58,71 @@ pkgs: types: ~ suites: ~ comps: ~ - handler: ~ + handler: default + - name: python3-certbot + uri: ~ + sigkey: ~ + sources: ~ + types: ~ + suites: ~ + comps: ~ + handler: default + - name: python3-certbot-dns-standalone + uri: ~ + sigkey: ~ + sources: ~ + types: ~ + suites: ~ + comps: ~ + handler: certbot + - name: sudo + uri: ~ + sigkey: ~ + sources: ~ + types: ~ + suites: ~ + comps: ~ + handler: default + - name: xz-utils + uri: ~ + sigkey: ~ + sources: ~ + types: ~ + suites: ~ + comps: ~ + handler: default + - name: wireguard + uri: ~ + sigkey: ~ + sources: ~ + types: ~ + suites: ~ + comps: ~ + handler: wireguard + - name: wireguard-tools + uri: ~ + sigkey: ~ + sources: ~ + types: ~ + suites: ~ + comps: ~ + handler: default + - name: vagrant + uri: ~ + sigkey: ~ + sources: ~ + types: ~ + suites: ~ + comps: ~ + handler: default + - name: qemu-system + uri: ~ + sigkey: ~ + sources: ~ + types: ~ + suites: ~ + comps: ~ + handler: default - name: qemu-kvm uri: ~ sigkey: ~ @@ -95,7 +130,7 @@ pkgs: types: ~ suites: ~ comps: ~ - handler: ~ + handler: default - name: bridge-utils uri: ~ sigkey: ~ @@ -103,7 +138,7 @@ pkgs: types: ~ suites: ~ comps: ~ - handler: ~ + handler: default - name: libvirt-clients uri: ~ sigkey: ~ @@ -111,7 +146,7 @@ pkgs: types: ~ suites: ~ comps: ~ - handler: ~ + handler: default - name: libvirt-daemon-system uri: ~ sigkey: ~ @@ -119,7 +154,7 @@ pkgs: types: ~ suites: ~ comps: ~ - handler: ~ + handler: default - name: gcc uri: ~ sigkey: ~ @@ -127,7 +162,7 @@ pkgs: types: ~ suites: ~ comps: ~ - handler: ~ + handler: default - name: git-doc uri: ~ sigkey: ~ @@ -135,7 +170,7 @@ pkgs: types: ~ suites: ~ comps: ~ - handler: ~ + handler: default - name: git-delta uri: ~ sigkey: ~ @@ -143,7 +178,7 @@ pkgs: types: ~ suites: ~ comps: ~ - handler: ~ + handler: default - name: fastfetch uri: ~ sigkey: ~ @@ -151,15 +186,7 @@ pkgs: types: ~ suites: ~ comps: ~ - handler: ~ - - name: vim - uri: ~ - sources: ~ - sigkey: ~ - types: ~ - suites: ~ - comps: ~ - handler: vim + handler: default - name: git uri: ~ sources: ~ @@ -175,15 +202,7 @@ pkgs: types: ~ suites: ~ comps: ~ - handler: ~ - - name: crowdsec - uri: ~ - sources: ~ - sigkey: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ + handler: default - name: glow uri: ~ sigkey: "https://repo.charm.sh/apt/gpg.key" @@ -191,39 +210,7 @@ pkgs: types: deb suites: "*" comps: "*" - handler: ~ - - name: vim-vimwiki - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - - name: vim-doc - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - - name: tor - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - - name: i2pd - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ + handler: default - name: whois uri: ~ sigkey: ~ @@ -231,7 +218,7 @@ pkgs: types: ~ suites: ~ comps: ~ - handler: ~ + handler: default # @TODO make sure to create handler inclusion of tasks in file under/at `tasks/contingent/pkg` for below - name: iptables uri: ~ @@ -240,31 +227,7 @@ pkgs: types: ~ suites: ~ comps: ~ - handler: ~ - - name: libpam-google-authenticator - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - - name: burp - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - - name: rsync - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ + handler: default - name: gnupg uri: ~ sigkey: ~ @@ -272,7 +235,7 @@ pkgs: types: ~ suites: ~ comps: ~ - handler: ~ + handler: default - name: gnupg-agent uri: ~ sigkey: ~ @@ -280,23 +243,7 @@ pkgs: types: ~ suites: ~ comps: ~ - handler: ~ - - name: gocryptfs - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - - name: cryfs - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ + handler: default - name: tmux uri: ~ sigkey: ~ @@ -304,7 +251,7 @@ pkgs: types: ~ suites: ~ comps: ~ - handler: ~ + handler: default - name: cpu-checker uri: ~ sigkey: ~ @@ -312,7 +259,7 @@ pkgs: types: ~ suites: ~ comps: ~ - handler: ~ + handler: default - name: libpam-doc uri: ~ sigkey: ~ @@ -320,7 +267,7 @@ pkgs: types: ~ suites: ~ comps: ~ - handler: ~ + handler: default - name: headscale uri: "https://github.com/juanfont/headscale/releases/download/v0.28.0/headscale_0.28.0_linux_amd64.deb" sigkey: ~ @@ -330,6 +277,38 @@ pkgs: comps: ~ handler: headscale userspace: + - name: libpam-google-authenticator + uri: ~ + sigkey: ~ + sources: ~ + types: ~ + suites: ~ + comps: ~ + handler: libpam-google-authenticator + - name: vim + uri: ~ + sources: ~ + sigkey: ~ + types: ~ + suites: ~ + comps: ~ + handler: vim + - name: vim-vimwiki + uri: ~ + sigkey: ~ + sources: ~ + types: ~ + suites: ~ + comps: ~ + handler: default + - name: vim-doc + uri: ~ + sigkey: ~ + sources: ~ + types: ~ + suites: ~ + comps: ~ + handler: default - name: neovim uri: ~ sigkey: ~ @@ -345,79 +324,15 @@ pkgs: types: ~ suites: ~ comps: ~ - handler: ~ - - name: proftpd-core + handler: default + - name: smartmontools uri: ~ sigkey: ~ sources: ~ types: ~ suites: ~ comps: ~ - handler: ~ - - name: proftpd-doc - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - - name: proftpd-mod-crypto - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - - name: proftpd-mod-ldap - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - - name: proftpd-mod-sqlite - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - - name: aria2 - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - - name: erlang - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - - name: erlang-hex - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - - name: elixir - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ + handler: default - name: python3.13 uri: ~ sigkey: ~ @@ -425,7 +340,7 @@ pkgs: types: ~ suites: ~ comps: ~ - handler: ~ + handler: default - name: python3-venv uri: ~ sigkey: ~ @@ -433,7 +348,7 @@ pkgs: types: ~ suites: ~ comps: ~ - handler: ~ + handler: default - name: python3-pip uri: ~ sigkey: ~ @@ -441,7 +356,7 @@ pkgs: types: ~ suites: ~ comps: ~ - handler: ~ + handler: default - name: golang uri: ~ sigkey: ~ @@ -449,39 +364,15 @@ pkgs: types: ~ suites: ~ comps: ~ - handler: ~ - - name: yt-dlp + handler: default + - name: golang-doc uri: ~ sigkey: ~ sources: ~ types: ~ suites: ~ comps: ~ - handler: ~ - - name: syncthing-discosrv - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - - name: syncthing-relaysrv - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - - name: rclone - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ + handler: default # :]> representing package groups installed by shell scripts script: # ]> representing user-level or supplemental shell script installations @@ -496,11 +387,6 @@ pkgs: pre: ~ post: ~ handler: rustup - - name: julia - src: "https://install.julialang.org" - pre: ~ - post: ~ - handler: julia - name: uv src: "https://astral.sh/uv/install.sh" pre: ~ @@ -510,18 +396,6 @@ pkgs: archive: # ]> representing user-level or supplemental source archives userspace: - - name: surge - src: "https://github.com/SurgeDM/Surge/releases/download/v0.8.6/Surge_0.8.6_linux_amd64.tar.gz" - deploy: ~ - pre: ~ - post: ~ - handler: surge - - name: nvm - src: "https://nodejs.org/dist/v24.16.0/node-v24.16.0-linux-x64.tar.xz" - deploy: ~ - pre: ~ - post: ~ - handler: nvm - name: difftastic src: "https://github.com/Wilfred/difftastic/releases/download/0.69.0/difft-x86_64-unknown-linux-gnu.tar.gz" deploy: ~ @@ -537,4 +411,9 @@ pkgs: # deploy: ~ # pre: ~ # post: ~ - # handler: ~ \ No newline at end of file + # handler: default + binaries: + core: + - name: dsnet + src: "https://github.com/naggie/dsnet/releases/download/v0.8.1/dsnet-linux-amd64" + handler: dsnet diff --git a/group_vars/armitage_test.yml b/host_vars/staging1.test.yml similarity index 77% rename from group_vars/armitage_test.yml rename to host_vars/staging1.test.yml index 7ca4207..f245bc4 100644 --- a/group_vars/armitage_test.yml +++ b/host_vars/staging1.test.yml @@ -1,8 +1,6 @@ # @TODO create inventory group variables akin to structure of sukaato group's for homeserver # > representing password for Linux root user account of VPS -password: "{{ lookup('password', '../.tmp/armitage_test.pass', seed='armitage_test', encrypt='sha512_crypt') }}" -# representing hostname for LAN server; same as host or group variable name -instance: armitage +password: "{{ lookup('password', './.tmp/' + inventory_hostname + '.pass', seed=inventory_hostname, encrypt='sha512_crypt') }}" # > representing Linux distro or OS image to be used for VPS # operating_system: "tftp://hikiki.local:69/debian.iso" operating_system: ~ @@ -20,13 +18,45 @@ admins: - ecdsa-37851076-sk@staging - ed25519-37851076-sk@staging # > hashed (and maybe salted) password - password: "{{ lookup('password', '../.tmp/senpai@armitage_test.pass', seed='senpai:armitage_test', encrypt='sha512_crypt') }}" + password: "{{ lookup('password', './.tmp/senpai@' + inventory_hostname + '.pass', seed='senpai@' + inventory_hostname, encrypt='sha512_crypt') }}" # :]> package groups pkgs: # :]> representing package groups installed by package manager via repositories mngr: # ]> representing system-level or essential packages core: + - name: zfsutils-linux + uri: ~ + sigkey: ~ + sources: ~ + types: ~ + suites: ~ + comps: ~ + handler: default + - name: zfs-dkms + uri: ~ + sigkey: ~ + sources: ~ + types: ~ + suites: ~ + comps: ~ + handler: default + - name: cron + uri: ~ + sigkey: ~ + sources: ~ + types: ~ + suites: ~ + comps: ~ + handler: default + - name: cron-daemon-common + uri: ~ + sigkey: ~ + sources: ~ + types: ~ + suites: ~ + comps: ~ + handler: default - name: xz-utils uri: ~ sigkey: ~ @@ -34,7 +64,7 @@ pkgs: types: ~ suites: ~ comps: ~ - handler: ~ + handler: default - name: wireguard uri: ~ sigkey: ~ @@ -42,7 +72,7 @@ pkgs: types: ~ suites: ~ comps: ~ - handler: ~ + handler: wireguard - name: wireguard-tools uri: ~ sigkey: ~ @@ -50,7 +80,7 @@ pkgs: types: ~ suites: ~ comps: ~ - handler: ~ + handler: default - name: sudo uri: ~ sigkey: ~ @@ -58,7 +88,7 @@ pkgs: types: ~ suites: ~ comps: ~ - handler: ~ + handler: default - name: kitty-terminfo uri: ~ sigkey: ~ @@ -66,7 +96,7 @@ pkgs: types: ~ suites: ~ comps: ~ - handler: ~ + handler: default - name: whois uri: ~ sigkey: ~ @@ -74,7 +104,7 @@ pkgs: types: ~ suites: ~ comps: ~ - handler: ~ + handler: default - name: smartmontools uri: ~ sigkey: ~ @@ -82,23 +112,7 @@ pkgs: types: ~ suites: ~ comps: ~ - handler: ~ - - name: vim-vimwiki - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - - name: vim-doc - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ + handler: default - name: snapd uri: ~ sources: ~ @@ -106,7 +120,7 @@ pkgs: types: ~ suites: ~ comps: ~ - handler: ~ + handler: default - name: git uri: ~ sources: ~ @@ -122,7 +136,7 @@ pkgs: types: ~ suites: ~ comps: ~ - handler: ~ + handler: default - name: git-doc uri: ~ sources: ~ @@ -130,7 +144,7 @@ pkgs: types: ~ suites: ~ comps: ~ - handler: ~ + handler: default - name: git-man uri: ~ sources: ~ @@ -138,7 +152,7 @@ pkgs: types: ~ suites: ~ comps: ~ - handler: ~ + handler: default - name: fail2ban uri: ~ sources: ~ @@ -146,15 +160,7 @@ pkgs: types: ~ suites: ~ comps: ~ - handler: ~ - - name: crowdsec - uri: ~ - sources: ~ - sigkey: ~ - types: ~ - suites: ~ - comps: ~ - handler: crowdsec + handler: default - name: glow uri: ~ sigkey: "https://repo.charm.sh/apt/gpg.key" @@ -162,7 +168,7 @@ pkgs: types: deb suites: "*" comps: "*" - handler: ~ + handler: default - name: pandoc uri: ~ sigkey: ~ @@ -170,7 +176,7 @@ pkgs: types: ~ suites: ~ comps: ~ - handler: ~ + handler: default - name: curl uri: ~ sigkey: ~ @@ -178,7 +184,7 @@ pkgs: types: ~ suites: ~ comps: ~ - handler: ~ + handler: default - name: build-essential uri: ~ sigkey: ~ @@ -186,7 +192,7 @@ pkgs: types: ~ suites: ~ comps: ~ - handler: ~ + handler: default - name: fastfetch uri: ~ sigkey: ~ @@ -194,7 +200,7 @@ pkgs: types: ~ suites: ~ comps: ~ - handler: ~ + handler: default - name: gcc uri: ~ sigkey: ~ @@ -202,7 +208,7 @@ pkgs: types: ~ suites: ~ comps: ~ - handler: ~ + handler: default - name: dpkg-dev uri: ~ sigkey: ~ @@ -210,7 +216,7 @@ pkgs: types: ~ suites: ~ comps: ~ - handler: ~ + handler: default - name: ufw uri: ~ sigkey: ~ @@ -218,7 +224,7 @@ pkgs: types: ~ suites: ~ comps: ~ - handler: ~ + handler: default - name: avahi-daemon uri: ~ sigkey: ~ @@ -226,7 +232,7 @@ pkgs: types: ~ suites: ~ comps: ~ - handler: ~ + handler: default - name: avahi-utils uri: ~ sigkey: ~ @@ -234,39 +240,7 @@ pkgs: types: ~ suites: ~ comps: ~ - handler: ~ - - name: libpam-google-authenticator - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - - name: cron - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - - name: cron-daemon-common - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - - name: tor - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: tor + handler: default - name: libpam-u2f uri: ~ sigkey: ~ @@ -274,7 +248,7 @@ pkgs: types: ~ suites: ~ comps: ~ - handler: ~ + handler: default - name: pamu2fcfg uri: ~ sigkey: ~ @@ -282,7 +256,7 @@ pkgs: types: ~ suites: ~ comps: ~ - handler: ~ + handler: default - name: pcscd uri: ~ sigkey: ~ @@ -290,7 +264,7 @@ pkgs: types: ~ suites: ~ comps: ~ - handler: ~ + handler: default - name: tftpd-hpa uri: ~ sigkey: ~ @@ -298,7 +272,7 @@ pkgs: types: ~ suites: ~ comps: ~ - handler: ~ + handler: default - name: gocryptfs uri: ~ sigkey: ~ @@ -306,7 +280,7 @@ pkgs: types: ~ suites: ~ comps: ~ - handler: ~ + handler: default - name: cryfs uri: ~ sigkey: ~ @@ -314,7 +288,7 @@ pkgs: types: ~ suites: ~ comps: ~ - handler: ~ + handler: default - name: tmux uri: ~ sigkey: ~ @@ -322,7 +296,7 @@ pkgs: types: ~ suites: ~ comps: ~ - handler: ~ + handler: default - name: cpu-checker uri: ~ sigkey: ~ @@ -330,7 +304,7 @@ pkgs: types: ~ suites: ~ comps: ~ - handler: ~ + handler: default - name: libpam-doc uri: ~ sigkey: ~ @@ -338,7 +312,7 @@ pkgs: types: ~ suites: ~ comps: ~ - handler: ~ + handler: default - name: gnupg uri: ~ sigkey: ~ @@ -346,7 +320,7 @@ pkgs: types: ~ suites: ~ comps: ~ - handler: ~ + handler: default - name: gnupg-agent uri: ~ sigkey: ~ @@ -354,8 +328,24 @@ pkgs: types: ~ suites: ~ comps: ~ - handler: ~ + handler: default userspace: + - name: aria2 + uri: ~ + sigkey: ~ + sources: ~ + types: ~ + suites: ~ + comps: ~ + handler: aria + - name: libpam-google-authenticator + uri: ~ + sigkey: ~ + sources: ~ + types: ~ + suites: ~ + comps: ~ + handler: libpam-google-authenticator - name: vim uri: ~ sources: ~ @@ -364,6 +354,22 @@ pkgs: suites: ~ comps: ~ handler: vim + - name: vim-vimwiki + uri: ~ + sigkey: ~ + sources: ~ + types: ~ + suites: ~ + comps: ~ + handler: default + - name: vim-doc + uri: ~ + sigkey: ~ + sources: ~ + types: ~ + suites: ~ + comps: ~ + handler: default - name: neovim uri: ~ sources: ~ @@ -379,7 +385,7 @@ pkgs: types: ~ suites: ~ comps: ~ - handler: ~ + handler: default - name: podman uri: ~ sigkey: ~ @@ -387,7 +393,15 @@ pkgs: types: ~ suites: ~ comps: ~ - handler: ~ + handler: podman + - name: passt + uri: ~ + sigkey: ~ + sources: ~ + types: ~ + suites: ~ + comps: ~ + handler: default - name: podman-compose uri: ~ sigkey: ~ @@ -395,7 +409,7 @@ pkgs: types: ~ suites: ~ comps: ~ - handler: ~ + handler: default - name: distrobox uri: ~ sigkey: ~ @@ -403,79 +417,7 @@ pkgs: types: ~ suites: ~ comps: ~ - handler: ~ - - name: proftpd-core - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - - name: proftpd-doc - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - - name: proftpd-mod-crypto - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - - name: proftpd-mod-ldap - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - - name: proftpd-mod-sqlite - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - - name: erlang - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - - name: erlang-doc - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - - name: erlang-hex - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ - - name: elixir - uri: ~ - sigkey: ~ - sources: ~ - types: ~ - suites: ~ - comps: ~ - handler: ~ + handler: default - name: python3.13 uri: ~ sigkey: ~ @@ -483,7 +425,7 @@ pkgs: types: ~ suites: ~ comps: ~ - handler: ~ + handler: default - name: python3-venv uri: ~ sigkey: ~ @@ -491,7 +433,7 @@ pkgs: types: ~ suites: ~ comps: ~ - handler: ~ + handler: default - name: python3-pip uri: ~ sigkey: ~ @@ -499,7 +441,7 @@ pkgs: types: ~ suites: ~ comps: ~ - handler: ~ + handler: default - name: python3-doc uri: ~ sigkey: ~ @@ -507,7 +449,7 @@ pkgs: types: ~ suites: ~ comps: ~ - handler: ~ + handler: default - name: golang uri: ~ sigkey: ~ @@ -515,7 +457,7 @@ pkgs: types: ~ suites: ~ comps: ~ - handler: ~ + handler: default - name: golang-doc uri: ~ sigkey: ~ @@ -523,7 +465,7 @@ pkgs: types: ~ suites: ~ comps: ~ - handler: ~ + handler: default - name: hugo uri: ~ sigkey: ~ @@ -531,7 +473,7 @@ pkgs: types: ~ suites: ~ comps: ~ - handler: ~ + handler: default - name: yt-dlp uri: ~ sigkey: ~ @@ -539,7 +481,7 @@ pkgs: types: ~ suites: ~ comps: ~ - handler: ~ + handler: default - name: syncthing-discosrv uri: ~ sigkey: ~ @@ -547,7 +489,7 @@ pkgs: types: ~ suites: ~ comps: ~ - handler: ~ + handler: default - name: syncthing-relaysrv uri: ~ sigkey: ~ @@ -555,7 +497,7 @@ pkgs: types: ~ suites: ~ comps: ~ - handler: ~ + handler: default - name: syncthing-relaysrv uri: ~ sigkey: ~ @@ -563,7 +505,7 @@ pkgs: types: ~ suites: ~ comps: ~ - handler: ~ + handler: default - name: burp uri: ~ sigkey: ~ @@ -571,7 +513,7 @@ pkgs: types: ~ suites: ~ comps: ~ - handler: ~ + handler: default - name: rsync uri: ~ sigkey: ~ @@ -579,7 +521,7 @@ pkgs: types: ~ suites: ~ comps: ~ - handler: ~ + handler: default - name: rclone uri: ~ sigkey: ~ @@ -587,39 +529,55 @@ pkgs: types: ~ suites: ~ comps: ~ - handler: ~ - - name: aria2 + handler: default + - name: proftpd uri: ~ sigkey: ~ sources: ~ types: ~ suites: ~ comps: ~ - handler: ~ - - name: mopidy + handler: default + - name: reprepro uri: ~ sigkey: ~ sources: ~ types: ~ suites: ~ comps: ~ - handler: ~ - - name: mopidy-mpd + handler: default + - name: erlang uri: ~ sigkey: ~ sources: ~ types: ~ suites: ~ comps: ~ - handler: ~ - - name: minidlna + handler: default + - name: erlang-hex uri: ~ sigkey: ~ sources: ~ types: ~ suites: ~ comps: ~ - handler: ~ + handler: default + - name: erlang-doc + uri: ~ + sigkey: ~ + sources: ~ + types: ~ + suites: ~ + comps: ~ + handler: default + - name: elixir + uri: ~ + sigkey: ~ + sources: ~ + types: ~ + suites: ~ + comps: ~ + handler: default # :]> representing package groups installed by shell scripts script: # ]> representing user-level or supplemental shell script installations @@ -634,11 +592,11 @@ pkgs: pre: ~ post: ~ handler: rustup - - name: julia - src: "https://install.julialang.org" - pre: ~ - post: ~ - handler: julia + # - name: julia + # src: "https://install.julialang.org" + # pre: ~ + # post: ~ + # handler: julia - name: uv src: "https://astral.sh/uv/install.sh" pre: ~ @@ -648,12 +606,12 @@ pkgs: archive: # ]> representing user-level or supplemental source archives userspace: - # - name: surge - # src: "https://github.com/SurgeDM/Surge/releases/download/v0.8.6/Surge_0.8.6_linux_amd64.tar.gz" - # deploy: ~ - # pre: ~ - # post: ~ - # handler: surge + - name: surge + src: "https://github.com/SurgeDM/Surge/releases/download/v0.8.6/Surge_0.8.6_linux_amd64.tar.gz" + deploy: ~ + pre: ~ + post: ~ + handler: surge - name: nvm src: "https://nodejs.org/dist/v24.16.0/node-v24.16.0-linux-x64.tar.xz" deploy: ~ @@ -668,7 +626,7 @@ pkgs: handler: difftastic # :]> representing package groups installed from source git repositories git_repos: - # userspace: + userspace: # # @TODO use below to build Podman container instead, to deploy with podman-compose # # @NOTE https://github.com/papis/papis and https://papis.readthedocs.io/en/latest/ # - name: papis @@ -678,6 +636,41 @@ pkgs: # pre: ~ # post: ~ # handler: false + - name: skato-compose + src: "https://{{ source_code.host }}/{{ source_code.user }}/{{ source_code.repos.compose.name }}.git" + branch: main + deploy: ~ + pre: ~ + post: ~ + handler: skato_compose + - name: skato-cli + src: "https://{{ source_code.host }}/{{ source_code.user }}/{{ source_code.repos.cli.name }}.git" + branch: main + deploy: ~ + pre: ~ + post: ~ + handler: skato_cli + - name: skato-blog-theme + src: "https://{{ source_code.host }}/{{ source_code.user }}/{{ source_code.repos.blog_theme.name }}.git" + branch: main + deploy: ~ + pre: ~ + post: ~ + handler: skato_blog_theme + - name: skato-blog + src: "https://{{ source_code.host }}/{{ source_code.user }}/{{ source_code.repos.blog.name }}.git" + branch: main + deploy: ~ + pre: ~ + post: ~ + handler: skato_blog + - name: sukaato + src: "https://{{ source_code.host }}/{{ source_code.user }}/{{ source_code.repos.site.name }}.git" + branch: main + deploy: ~ + pre: ~ + post: ~ + handler: sukaato - name: quartz src: "https://github.com/jackyzha0/quartz.git" branch: v5.0.0 diff --git a/hosts.yml.example b/hosts.yml.example deleted file mode 100644 index cd96c87..0000000 --- a/hosts.yml.example +++ /dev/null @@ -1,33 +0,0 @@ -# @TODO use hosts and host groupings that refer or point to VM or containerized servers for testing -ungrouped: - hosts: - staging0: - ansible_host: ~ - staging1: - ansible_host: ~ -sukaato: - hosts: ~ -sukaato_test: - hosts: - staging0: -armitage: - hosts: ~ -armitage_test: - hosts: - staging1: -vps: - children: - sukaato: -vps_test: - children: - sukaato_test: -homeserver: - children: - armitage: -homeserver_test: - children: - armitage_test: -test: - children: - vps_test: - homeserver_test: diff --git a/init@homeserver.yml b/init@homeserver.yml index 591f043..f20bf01 100644 --- a/init@homeserver.yml +++ b/init@homeserver.yml @@ -1,15 +1,15 @@ # @NOTE run 'ansible-playbook' command on this using 'sudo' - name: Initialize homeserver - hosts: "{{ chosen_host | default('armitage') }}" + hosts: "{{ chosen_host | default('staging1.test') }}" remote_user: root vars: harden: true vars_files: + # - vars/certbot_settings@homeserver.yml # REQUIRED - vars/local_facts.yml # REQUIRED - - vars/vim_settings.yml # REQUIRED - - vars/vpn_server.yml # REQUIRED - - vars/tail_net.yml - - vars/crowdsec.yml + - vars/wireguard_settings.yml # REQUIRED + - vars/podpose_settings.yml # REQUIRED + - vars/surge_settings.yml - vars/users@{{ inventory_hostname | default('homeserver') }}.yml - vars/config@{{ inventory_hostname | default('homeserver') }}.yml tasks: @@ -35,12 +35,27 @@ become: true ansible.builtin.hostname: name: "{{ inventory_hostname }}" + - name: Updating hosts file + become: true + ansible.builtin.lineinfile: + path: /etc/hosts + regexp: "^127\\.0\\.1\\.1" + line: "127.0.1.1 {{ inventory_hostname }}" + insertbefore: BOF + state: present - name: Updating host icon name become: true ansible.builtin.command: cmd: "hostnamectl set-icon-name computer-server" + - name: Notifying user that all processes have finished + ansible.builtin.debug: + msg: All processes finished. Hit enter to reboot machine. + - name: Ensuring user has read prior message regarding upcoming reboot + ansible.builtin.pause: - name: Rebooting machine for hostname change become: true ansible.builtin.reboot: - msg: "Rebooting machine" + msg: "Rebooting machine.." + connect_timeout: 0 + test_command: ~ ignore_errors: true \ No newline at end of file diff --git a/init@vps.yml b/init@vps.yml index 2a42ec4..9b78812 100644 --- a/init@vps.yml +++ b/init@vps.yml @@ -1,15 +1,16 @@ # @NOTE run 'ansible-playbook' command on this using 'sudo' - name: Initialize VPS - # hosts: sukaato - hosts: "{{ chosen_host | default('sukaato') }}" - remote_user: root + hosts: "{{ chosen_host | default('staging0.test') }}" + remote_user: "{{ chosen_user | default('root') }}" vars: harden: true vars_files: - vars/local_facts.yml # REQUIRED - - vars/vpn_server.yml # REQUIRED - - vars/tail_net.yml - - vars/crowdsec.yml + - vars/vpn_settings.yml # REQUIRED + - vars/wireguard_settings.yml # REQUIRED + - vars/headscale_settings.yml # REQUIRED + - vars/podpose_settings.yml # REQUIRED + - vars/certbot_settings@vps.yml # REQUIRED - vars/users@{{ inventory_hostname | default('vps') }}.yml - vars/config@{{ inventory_hostname | default('vps') }}.yml tasks: @@ -31,16 +32,60 @@ ansible.builtin.include_role: name: init-server tasks_from: ssh-users - - name: Flush handlers + - name: Flushing handlers ansible.builtin.meta: flush_handlers - - name: Update hostname + - name: Updating hostname become: true ansible.builtin.hostname: name: "{{ inventory_hostname }}" - - name: Update host icon name + - name: Updating hosts file + become: true + ansible.builtin.lineinfile: + path: /etc/hosts + regexp: "^127\\.0\\.1\\.1" + line: "127.0.1.1 {{ inventory_hostname }}" + insertbefore: BOF + state: present + - name: Updating host icon name become: true ansible.builtin.command: cmd: "hostnamectl set-icon-name computer-server" + - name: Opening port 51820 + become: true + ansible.builtin.iptables: + chain: INPUT + protocol: "{{ item }}" + destination_port: 51820 + jump: ACCEPT + comment: Open up port 51820 + loop: + - udp + - tcp + - name: Opening port 443 + become: true + ansible.builtin.iptables: + chain: INPUT + protocol: "{{ item }}" + destination_port: 443 + jump: ACCEPT + comment: Open up port 443 + loop: + - udp + - tcp + - name: Opening ports + become: true + ansible.builtin.iptables: + chain: INPUT + protocol: tcp + destination_port: "{{ item }}" + jump: ACCEPT + comment: "Open up port {{ (item | string) }}" + loop: + - 80 + - 465 + - 587 + - 995 + - 993 - name: Notifying user that all processes have finished ansible.builtin.debug: msg: All processes finished. Hit enter to reboot machine. @@ -51,5 +96,4 @@ ansible.builtin.reboot: msg: "Rebooting machine.." connect_timeout: 0 - test_command: ~ - ignore_errors: true \ No newline at end of file + test_command: ~ \ No newline at end of file diff --git a/roles/init-server/files/letsencrypt/renewal-hooks/post/up-dependents.sh b/roles/init-server/files/letsencrypt/renewal-hooks/post/up-dependents.sh new file mode 100755 index 0000000..0c7d2cb --- /dev/null +++ b/roles/init-server/files/letsencrypt/renewal-hooks/post/up-dependents.sh @@ -0,0 +1,17 @@ +#!/bin/bash +set -euo pipefail + +HTTP_SERVERS=() +HTTP_SERVERS_LEN="${#HTTP_SERVERS[@]}" + +if command -v systemctl > /dev/null 2>&1; then + if (( HTTP_SERVERS_LEN > 0 )); then + for htserv in "${HTTP_SERVERS[@]}" + do + sudo systemctl start "$htserv" + done + fi +fi +if command -v podman > /dev/null 2>&1; then + podman start -a +fi \ No newline at end of file diff --git a/roles/init-server/files/letsencrypt/renewal-hooks/pre/down-dependents.sh b/roles/init-server/files/letsencrypt/renewal-hooks/pre/down-dependents.sh new file mode 100755 index 0000000..a4164ef --- /dev/null +++ b/roles/init-server/files/letsencrypt/renewal-hooks/pre/down-dependents.sh @@ -0,0 +1,17 @@ +#!/bin/bash +set -euo pipefail + +HTTP_SERVERS=() +HTTP_SERVERS_LEN="${#HTTP_SERVERS[@]}" + +if command -v systemctl > /dev/null 2>&1; then + if (( HTTP_SERVERS_LEN > 0 )); then + for htserv in "${HTTP_SERVERS[@]}" + do + sudo systemctl stop "$htserv" + done + fi +fi +if command -v podman > /dev/null 2>&1; then + podman stop -a +fi \ No newline at end of file diff --git a/roles/init-server/files/systemd/system/surge.service b/roles/init-server/files/systemd/system/surge.service new file mode 100644 index 0000000..6586e1e --- /dev/null +++ b/roles/init-server/files/systemd/system/surge.service @@ -0,0 +1,13 @@ +[Unit] +Description=surge +After=network-online.target +Wants=network-online.target + +[Service] +Type=oneshot +ExecStart=surge service start +ExecStop=surge service stop +RemainAfterExit=yes + +[Install] +WantedBy=default.target \ No newline at end of file diff --git a/roles/init-server/files/user/config/containers/registries.conf b/roles/init-server/files/user/config/containers/registries.conf new file mode 100644 index 0000000..a0a9e34 --- /dev/null +++ b/roles/init-server/files/user/config/containers/registries.conf @@ -0,0 +1,9 @@ +# Search these registries when pulling images without full path +unqualified-search-registries = ["docker.io", "quay.io", "ghcr.io"] + +# Registry-specific configuration +# [[registry]] +# location = "docker.io" + +# [[registry.mirror]] +# location = "mirror.gcr.io" \ No newline at end of file diff --git a/roles/init-server/files/user/config/systemd/user/aria2cd.service b/roles/init-server/files/user/config/systemd/user/aria2cd.service new file mode 100644 index 0000000..467e50b --- /dev/null +++ b/roles/init-server/files/user/config/systemd/user/aria2cd.service @@ -0,0 +1,14 @@ +[Unit] +Description=aria2 Daemon +Requires=network.target +After=network.target + +[Service] +Type=forking +ExecStart=/usr/bin/aria2c -D +ExecReload=/usr/bin/kill -HUP $MAINPID +RestartSec=1min +Restart=on-failure + +[Install] +WantedBy=default.target \ No newline at end of file diff --git a/roles/init-server/files/user/journal/mythe-sisyphus-klein.png b/roles/init-server/files/user/journal/mythe-sisyphus-klein.png new file mode 100644 index 0000000..16d3b7b Binary files /dev/null and b/roles/init-server/files/user/journal/mythe-sisyphus-klein.png differ diff --git a/roles/init-server/files/user/srv/domain-root/error/503.html b/roles/init-server/files/user/srv/domain-root/error/503.html new file mode 100644 index 0000000..3f3de25 --- /dev/null +++ b/roles/init-server/files/user/srv/domain-root/error/503.html @@ -0,0 +1,139 @@ + + + + {{.Host}}: {{ph "http.request.uri.path"}} + + + +
+ Sisyphus carrying a boulder +
+
+
+

Under Construction

+

Err. {{ph "http.error.status_code"}}: {{ph "http.error.status_text"}}

+
+
+

{{ph "http.error.message"}}

+ + {{ph "http.error.trace"}} + +
+
+
+ + \ No newline at end of file diff --git a/roles/init-server/files/user/srv/domain-root/error/dark-matter.png b/roles/init-server/files/user/srv/domain-root/error/dark-matter.png new file mode 100644 index 0000000..d9f0c71 Binary files /dev/null and b/roles/init-server/files/user/srv/domain-root/error/dark-matter.png differ diff --git a/roles/init-server/files/user/srv/domain-root/error/mythe-sisyphus-klein.png b/roles/init-server/files/user/srv/domain-root/error/mythe-sisyphus-klein.png new file mode 100644 index 0000000..16d3b7b Binary files /dev/null and b/roles/init-server/files/user/srv/domain-root/error/mythe-sisyphus-klein.png differ diff --git a/roles/init-server/files/usr/local/bin/dsnet-forward.sh b/roles/init-server/files/usr/local/bin/dsnet-forward.sh deleted file mode 100755 index a617366..0000000 --- a/roles/init-server/files/usr/local/bin/dsnet-forward.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/bash -set -euo pipefail - -if [[ "$1" == "start" ]]; then - /usr/sbin/iptables -A FORWARD -i dsnet -p tcp --sport {80,443,465,587,995,110,143,993} -j ACCEPT - /usr/sbin/iptables -t nat -A POSTROUTING -o dsnet -j MASQUERADE -elif [[ "$1" == "stop" ]]; then - /usr/sbin/iptables -D FORWARD -i dsnet -p tcp --sport {80,443,465,587,995,110,143,993} -j ACCEPT - /usr/sbin/iptables -t nat -D POSTROUTING -o dsnet -j MASQUERADE -fi \ No newline at end of file diff --git a/roles/init-server/handlers/core.yml b/roles/init-server/handlers/core.yml index de4a259..5195c75 100644 --- a/roles/init-server/handlers/core.yml +++ b/roles/init-server/handlers/core.yml @@ -5,6 +5,22 @@ ansible.builtin.debug: msg: "No post-installaton or additional installation steps needed--continuing..." listen: default +- name: Setting up Git + ansible.builtin.include_tasks: + file: tasks/contingent/pkg/git.yml + listen: git +- name: Setting up Certbot + ansible.builtin.include_tasks: + file: tasks/contingent/pkg/certbot.yml + listen: certbot +- name: Setting up TOR + ansible.builtin.include_tasks: + file: tasks/contingent/pkg/tor.yml + listen: tor +- name: Setting up Wireguard + ansible.builtin.include_tasks: + file: tasks/contingent/pkg/wireguard.yml + listen: wireguard - name: Setting up Crowdsec ansible.builtin.include_tasks: file: tasks/contingent/pkg/crowdsec.yml @@ -13,14 +29,6 @@ ansible.builtin.include_tasks: file: tasks/contingent/pkg/headscale.yml listen: headscale -- name: Setting up Git - ansible.builtin.include_tasks: - file: tasks/contingent/pkg/git.yml - listen: git -- name: Setting up TOR - ansible.builtin.include_tasks: - file: tasks/contingent/pkg/tor.yml - listen: tor - name: Setting up DSNet ansible.builtin.include_tasks: file: tasks/contingent/pkg/dsnet.yml diff --git a/roles/init-server/handlers/userspace.yml b/roles/init-server/handlers/userspace.yml index 53fcea1..1c4d819 100644 --- a/roles/init-server/handlers/userspace.yml +++ b/roles/init-server/handlers/userspace.yml @@ -37,15 +37,47 @@ ansible.builtin.include_tasks: file: tasks/contingent/pkg/uv.yml listen: uv -- name: Setting up Radicle +- name: Setting up Podman ansible.builtin.include_tasks: - file: tasks/contingent/pkg/radicle.yml - listen: radicle -- name: Setting up Surge + file: tasks/contingent/pkg/podman.yml + listen: podman +- name: Setting up Podman Compose sources ansible.builtin.include_tasks: - file: tasks/contingent/pkg/surge.yml - listen: surge + file: tasks/contingent/pkg/skato_compose.yml + listen: skato_compose - name: Setting up Quartz ansible.builtin.include_tasks: file: tasks/contingent/pkg/quartz.yml listen: quartz +- name: Setting up native CLI tools sources + ansible.builtin.include_tasks: + file: tasks/contingent/pkg/skato_cli.yml + listen: skato_cli +- name: Setting up blog theme + ansible.builtin.include_tasks: + file: tasks/contingent/pkg/skato_blog_theme.yml + listen: skato_blog_theme +- name: Setting up blog + ansible.builtin.include_tasks: + file: tasks/contingent/pkg/skato_blog.yml + listen: skato_blog +- name: Setting up website sources + ansible.builtin.include_tasks: + file: tasks/contingent/pkg/sukaato.yml + listen: sukaato +- name: Setting up Surge + ansible.builtin.include_tasks: + file: tasks/contingent/pkg/surge.yml + listen: surge +- name: Setting up Aria2 + ansible.builtin.include_tasks: + file: tasks/contingent/pkg/aria.yml + listen: aria +- name: Setting up Radicle + ansible.builtin.include_tasks: + file: tasks/contingent/pkg/radicle.yml + listen: radicle +- name: Setting up TOTP + ansible.builtin.include_tasks: + file: tasks/contingent/pkg/libpam-google-authenticator.yml + listen: libpam-google-authenticator diff --git a/roles/init-server/tasks/contingent/pkg/aria.yml b/roles/init-server/tasks/contingent/pkg/aria.yml new file mode 100644 index 0000000..8955ffc --- /dev/null +++ b/roles/init-server/tasks/contingent/pkg/aria.yml @@ -0,0 +1,70 @@ +--- +- 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: Informing user of requirement of two main domains + when: (certbot.domains | length) < 2 or (certbot.domains | length) > 2 + ansible.builtin.fail: + msg: Only two domains allowed and required +- name: Informing user of requirement at least one wildcard + when: (certbot.domains | select("regex", "^\\*\\.") | list | length) == 0 + ansible.builtin.fail: + msg: At least one of the FQDNs must have a wildcard +# - name: Setting the FQDN for development +# when: compose.mode == "dev" +# ansible.builtin.set_fact: +# web_fqdn: "{{ (certbot.domains | map('regex_replace', '\\.([^\\.]*)$', '.test') | reject('regex', '^\\*\\.') | list)[0] }}" +- name: Setting the FQDN + # when: compose.mode == "prod" + ansible.builtin.set_fact: + web_fqdn: "{{ (certbot.domains | reject('regex', '^\\*\\.') | list)[0] }}" +- name: Creating directory to store configuration file + ansible.builtin.file: + path: "{{ ansible_user_home.stdout }}/.aria2" + recurse: true + owner: "{{ ansible_user }}" + group: "{{ ansible_user }}" + mode: "755" + state: directory +- name: Configuring Aria2 + become: true + become_user: "{{ current_user.stdout }}" + ansible.builtin.template: + src: user/aria2/aria2.conf.j2 + dest: "{{ ansible_user_home.stdout }}/.aria2/aria2.conf" + owner: "{{ ansible_user }}" + group: "{{ ansible_user }}" + mode: "644" + force: true + backup: true + # validate: "aria2c --check" +- name: Setting up Aria2 as a service + when: aria.rpc.enabled and not aria.containerized + block: + - name: Creating a user SystemD service unit for Aria2 + become: true + become_user: "{{ current_user.stdout }}" + ansible.builtin.copy: + src: user/config/systemd/user/aria2cd.service + dest: "{{ ansible_user_home.stdout }}/.config/systemd/user/aria2cd.service" + owner: "{{ ansible_user }}" + group: "{{ ansible_user }}" + mode: "644" + force: true + backup: true + - name: Starting and enabling user SystemD service unit for Aria2 + become: true + become_user: "{{ current_user.stdout }}" + ansible.builtin.systemd_service: + name: aria2cd + scope: user + enabled: true + state: started + daemon_reload: true \ No newline at end of file diff --git a/roles/init-server/tasks/contingent/pkg/certbot.yml b/roles/init-server/tasks/contingent/pkg/certbot.yml new file mode 100644 index 0000000..c806ea2 --- /dev/null +++ b/roles/init-server/tasks/contingent/pkg/certbot.yml @@ -0,0 +1,166 @@ +--- +- name: Informing user of requirement of two main domains + when: (certbot.domains | length) < 2 or (certbot.domains | length) > 2 + ansible.builtin.fail: + msg: Only two domains allowed and required +- name: Informing user of requirement at least one wildcard + when: (certbot.domains | select("regex", "^\\*\\.") | list | length) == 0 + ansible.builtin.fail: + msg: At least one of the FQDNs must have a wildcard +# - name: Modifying FQDN list for development +# when: "certbot.mode == 'dev'" +# ansible.builtin.set_fact: +# web_fqdns: "{{ certbot.domains | map('regex_replace', '\\.([^\\.]*)$', '.test') | list }}" +- name: Modifying FQDN list for development + # when: "certbot.mode == 'prod'" + ansible.builtin.set_fact: + web_fqdns: "{{ certbot.domains }}" +- name: Creating domain arguments for certbot + ansible.builtin.set_fact: + certbot_domains: "{{ ['-d'] | product(web_fqdns) | map('join', '=') | list }}" +- name: Getting public IP + community.general.ipify_facts: + validate_certs: false + timeout: 20 +- name: Starting domain name registration with standalone DNS + when: "certbot.auth_method == 'dns' and not certbot.containerized" + ignore_errors: true + block: + - name: Opening port 53 + become: true + ansible.builtin.iptables: + chain: INPUT + protocol: tcp + destination_port: 53 + jump: ACCEPT + comment: Opening up port 53 + # @NOTE https://github.com/siilike/certbot-dns-standalone + - name: Exemplifying needed ACME record + ansible.builtin.set_fact: + acme_record: | + {{ inventory_hostname }} IN A {{ ipify_public_ip }} + _acme-challenge.{{ inventory_hostname }} IN CNAME {{ inventory_hostname }}.acme.{{ inventory_hostname }}. + acme.{{ inventory_hostname }} IN NS ns.acme.{{ inventory_hostname }}. + ns.acme.{{ inventory_hostname }} IN A {{ ipify_public_ip }} + - name: Informing user of need to set up ACME record + ansible.builtin.debug: + msg: "Please set ACME record in domain name provider:\n {{ acme_record }}" + - name: Waiting for user to set up ACME records + ansible.builtin.pause: + - name: Running certbot to authenticate and acquire domain name certificates + become: true + when: "certbot.mode == 'dev'" + ansible.builtin.command: + argv: + - certbot + - certonly + - "--staging" + - "--debug" + - "--authenticator=dns-standalone" + - "--email={{ certbot.email }}" + - "--agree-tos" + - "--non-interactive" + - "--dns-standalone-address={{ ipify_public_ip }}" + # - "--dns-standalone-ipv6-address={{ ansible_default_ipv6.address | default(ansible_all_ipv6_addresses[0]) }}" + - "--dns-standalone-port={{ certbot.port }}" + - "{{ certbot_domains[0] }}" + - "{{ certbot_domains[1] }}" + - name: Running certbot to authenticate and acquire domain name certificates + become: true + when: "certbot.mode == 'prod'" + ansible.builtin.command: + argv: + - certbot + - certonly + - "--authenticator=dns-standalone" + - "--email={{ certbot.email }}" + - "--agree-tos" + - "--non-interactive" + - "--dns-standalone-address={{ ipify_public_ip }}" + # - "--dns-standalone-ipv6-address={{ ansible_default_ipv6.address | default(ansible_all_ipv6_addresses[0]) }}" + - "--dns-standalone-port={{ certbot.port }}" + - "{{ certbot_domains[0] }}" + - "{{ certbot_domains[1] }}" +- name: Starting domain name registration with standalone option + when: "certbot.auth_method == 'standalone' and not certbot.containerized" + ignore_errors: true + block: + - name: Opening port 80 + become: true + ansible.builtin.iptables: + chain: INPUT + protocol: tcp + destination_port: 80 + jump: ACCEPT + comment: Open up port 80 + - name: Acquiring domain certificates + become: true + when: "certbot.mode == 'dev'" + ansible.builtin.command: + argv: + - certbot + - certonly + - "--staging" + - "--debug" + - "--standalone" + - "--preferred-challenges=http-01" + - "--email={{ certbot.email }}" + - "--agree-tos" + - "--non-interactive" + - "{{ certbot_domains[0] }}" + - "{{ certbot_domains[1] }}" + - name: Acquiring domain certificates + become: true + when: "certbot.mode == 'dev'" + ansible.builtin.command: + argv: + - certbot + - certonly + - "--standalone" + - "--email {{ certbot.email }}" + - "--agree-tos" + - "--non-interactive" + - "--preferred-challenges http-01" + - "{{ certbot_domains[0] }}" + - "{{ certbot_domains[1] }}" + - name: Creating needed directory for renewal pre- hooks + become: true + ansible.builtin.file: + path: /etc/letsencrypt/renewal-hooks/pre + recurse: true + owner: root + group: root + mode: "755" + state: directory + - name: Copying renewal pre- hook to renewal pre- hook path + become: true + ansible.builtin.copy: + src: letsencrypt/renewal-hooks/pre/down-dependents.sh + dest: /etc/letsencrypt/renewal-hooks/pre/ + owner: root + group: root + mode: "755" + force: true + backup: true + - name: Creating needed directory for renewal post- hooks + become: true + ansible.builtin.file: + path: /etc/letsencrypt/renewal-hooks/post + recurse: true + owner: root + group: root + mode: "755" + state: directory + - name: Copying renewal post- hook to renewal post- hook path + become: true + ansible.builtin.copy: + src: letsencrypt/renewal-hooks/post/up-dependents.sh + dest: /etc/letsencrypt/renewal-hooks/post/ + owner: root + group: root + mode: "755" + force: true + backup: true +- name: Starting domain name registration with webroot option + when: "certbot.auth_method == 'webroot' and not certbot.containerized" + block: [] \ No newline at end of file diff --git a/roles/init-server/tasks/contingent/pkg/crowdsec.yml b/roles/init-server/tasks/contingent/pkg/crowdsec.yml index 1d48126..2f60651 100644 --- a/roles/init-server/tasks/contingent/pkg/crowdsec.yml +++ b/roles/init-server/tasks/contingent/pkg/crowdsec.yml @@ -1,40 +1,65 @@ -- name: Restarting SystemD service - become: true - ansible.builtin.systemd_service: - name: crowdsec - scope: system - enabled: true - state: started -- name: Changing the address and port of the Crowdsec server - become: true - ansible.builtin.lineinfile: - path: /etc/crowdsec/config.yaml - regexp: "^ {4}listen_uri" - line: " listen_uri: localhost:{{ crowdsec.port }}" - owner: root - group: root - mode: "644" -- name: Changing the address of the Crowdsec Prometheus server - become: true - ansible.builtin.lineinfile: - path: /etc/crowdsec/config.yaml - regexp: "^ {2}listen_addr" - line: " listen_addr: localhost" - owner: root - group: root - mode: "644" -- name: Changing target or expected address for credentials of the Crowdsec local API - become: true - ansible.builtin.lineinfile: - path: /etc/crowdsec/local_api_credentials.yaml - regexp: "^url" - line: "url: http://localhost:{{ crowdsec.port }}" - owner: root - group: root - mode: "644" -- name: Restarting SystemD service - become: true - ansible.builtin.systemd_service: - name: crowdsec - scope: system - state: restarted \ No newline at end of file +- name: Preparing non-containerized Crowdsec + when: not crowdsec.containerized + block: + - name: Changing the address and port of the Crowdsec server + become: true + ansible.builtin.lineinfile: + path: /etc/crowdsec/config.yaml + insertafter: EOF + regexp: "^ {4}listen_uri" + line: " listen_uri: localhost:{{ crowdsec.port }}" + owner: root + group: root + mode: "644" + - name: Changing the address of the Crowdsec Prometheus server + become: true + ansible.builtin.lineinfile: + path: /etc/crowdsec/config.yaml + regexp: "^ {2}listen_addr" + insertafter: EOF + line: " listen_addr: localhost" + owner: root + group: root + mode: "644" + - name: Changing target or expected address for credentials of the Crowdsec local API + become: true + ansible.builtin.lineinfile: + path: /etc/crowdsec/local_api_credentials.yaml + insertafter: EOF + regexp: "^url" + line: "url: http://localhost:{{ crowdsec.port }}" + owner: root + group: root + mode: "644" + - name: Restarting SystemD service + become: true + ansible.builtin.systemd_service: + name: crowdsec + scope: system + state: restarted + - name: Adding remediation component or bouncer + ansible.builtin.command: + cmd: "cscli bouncers add {{ item }}" + loop: "{{ crowdsec.bouncers }}" + - name: Installing Crowdsec collections + ansible.builtin.command: + cmd: "cscli collections install {{ item }}" + loop: "{{ crowdsec.colls }}" + - name: Installing Crowdsec parsers + ansible.builtin.command: + cmd: "cscli parsers install {{ item }}" + loop: "{{ crowdsec.parsers }}" + - name: Installing Crowdsec scenarios + ansible.builtin.command: + cmd: "cscli scenarios install {{ item }}" + loop: "{{ crowdsec.scenarios }}" + - name: Installing Crowdsec postoverflows + ansible.builtin.command: + cmd: "cscli postoverflows install {{ item }}" + loop: "{{ crowdsec.postoverflows }}" + - name: Restarting SystemD service + become: true + ansible.builtin.systemd_service: + name: crowdsec + scope: system + state: restarted \ No newline at end of file diff --git a/roles/init-server/tasks/contingent/pkg/difftastic.yml b/roles/init-server/tasks/contingent/pkg/difftastic.yml index e169a7f..f14f665 100644 --- a/roles/init-server/tasks/contingent/pkg/difftastic.yml +++ b/roles/init-server/tasks/contingent/pkg/difftastic.yml @@ -5,6 +5,7 @@ cmd: "echo ~{{ ansible_user }}" register: ansible_user_home - name: Linking binaries to directories already in PATH environment variable + ignore_errors: true ansible.builtin.file: src: "{{ ansible_user_home.stdout }}/downloads/archives/released/difftastic/{{ item }}" dest: "{{ ansible_user_home.stdout }}/.local/bin/{{ item }}" @@ -13,6 +14,7 @@ - difft - name: Linking binaries to directories already in PATH environment variable become: true + ignore_errors: true ansible.builtin.file: src: "{{ ansible_user_home.stdout }}/downloads/archives/released/difftastic/{{ item }}" dest: "/usr/bin/{{ item }}" diff --git a/roles/init-server/tasks/contingent/pkg/dsnet.yml b/roles/init-server/tasks/contingent/pkg/dsnet.yml index e7fb4a8..69d7080 100644 --- a/roles/init-server/tasks/contingent/pkg/dsnet.yml +++ b/roles/init-server/tasks/contingent/pkg/dsnet.yml @@ -29,7 +29,7 @@ ansible.builtin.shell: cmd: "dsnet add {{ item.name }}{{ idx }} --owner {{ current_user.stdout }} --description 'For {{ item.name }}--{{ item.desc }}' --confirm > {{ ansible_user_home.stdout }}/.wg/authorized_clients.d/{{ item.name }}{{ (idx | string) }}.conf" creates: "{{ ansible_user_home.stdout }}/.wg/authorized_clients.d/{{ item.name }}{{ idx }}.conf" - loop: "{{ vpn_server.clients }}" + loop: "{{ vpn.clients }}" loop_control: index_var: idx - name: Changing ownership of consequent DSNet VPN service client configurations @@ -37,8 +37,9 @@ path: "{{ ansible_user_home.stdout }}/.wg/authorized_clients.d/{{ item.name }}{{ (idx | string) }}.conf" owner: "{{ ansible_user }}" group: "{{ ansible_user }}" + mode: "600" state: file - loop: "{{ vpn_server.clients }}" + loop: "{{ vpn.clients }}" loop_control: index_var: idx - name: Pausing to inquire about how to proceed @@ -52,30 +53,47 @@ - name: Acquiring contents of DSNet VPN service client configuration files ansible.builtin.slurp: src: "{{ ansible_user_home.stdout }}/.wg/authorized_clients.d/{{ item.name }}{{ (idx | string) }}.conf" - loop: "{{ vpn_server.clients }}" + loop: "{{ vpn.clients }}" loop_control: index_var: idx register: vpn_client_configs - name: Presenting contents of DSNet VPN service client configurations to control node ansible.builtin.debug: - msg: "Copy this client configuration of the DSNet VPN service:\n {{ item.content }}" + msg: "Copy this client configuration of the DSNet VPN service:\n {{ item.content | b64decode }}" loop: "{{ vpn_client_configs.results }}" - name: Giving opportunity to manually copy contents of DSNet VPN service client configuration files ansible.builtin.pause: - name: Providing DSNet VPN service client configuration files to control node machine when: data_method.user_input == "fetch" block: + - name: Informing user of inventory requirements for VPN clients + when: not item.name in groups.homeserver + ansible.builtin.fail: + msg: The VPN client must be the name of an inventory host in a homeserver group + loop: "{{ vpn.clients }}" + - name: Dupliciating DSNet VPN service client configuration files to control node + when: item.name in groups.homeserver + ansible.builtin.fetch: + src: "{{ ansible_user_home.stdout }}/.wg/authorized_clients.d/{{ item.name }}{{ (idx | string) }}.conf" + dest: "./.tmp/{{ inventory_hostname }}-dsnet/" + flat: true + loop: "{{ vpn.clients }}" + loop_control: + index_var: idx - name: Dupliciating DSNet VPN service client configuration files to control node ansible.builtin.fetch: src: "{{ ansible_user_home.stdout }}/.wg/authorized_clients.d/{{ item.name }}{{ (idx | string) }}.conf" - dest: "./.tmp/{{ inventory_hostname }}-dsnet/wg/" + dest: "./roles/init-server/files/user/wg/containerized/{{ item.name }}{{ (idx | string) }}.conf" flat: true - loop: "{{ vpn_server.clients }}" + loop: "{{ vpn.clients }}" loop_control: index_var: idx - name: Informing control node of acquired files ansible.builtin.debug: - msg: "The DSNet VPS service client configuration files have been duplicated to '/var/tmp/{{ inventory_hostname }}/wg/' at the control node." + msg: "The DSNet VPS service client configuration files have been duplicated to \"{{ item }}\" at the control node." + loop: + - "./.tmp/{{ inventory_hostname }}-dsnet/" + - "./roles/init-server/files/user/wg/" - name: Giving control node user time to read the aforementiioned message ansible.builtin.pause: seconds: 30 @@ -106,12 +124,12 @@ daemon_reload: true - name: Copying script for DSNet iptables rules become: true - ansible.builtin.copy: - src: usr/local/bin/dsnet-forward.sh - dest: /usr/local/bin/ + ansible.builtin.template: + src: usr/local/bin/dsnet-forward.sh.j2 + dest: /usr/local/bin/dsnet-forward.sh owner: root group: root - mode: "744" + mode: "755" force: true backup: true - name: Creating SystemD unit for DSNet iptables rules @@ -123,25 +141,19 @@ group: root force: true backup: true -- name: Reloading SystemD and enabling iptables rules SystemD unit +- name: Reloading SystemD become: true ansible.builtin.systemd_service: name: thrunet - enabled: true daemon_reload: true -- name: Forwarding network traffic on certain ports to Wireguard VPS service interface +- name: Opening port 51820 become: true ansible.builtin.iptables: - chain: FORWARD - protocol: "{{ item[0][0] }}" - source_port: "{{ item[0][1] }}" - in_interface: "{{ item[1] }}" + chain: INPUT + protocol: "{{ item }}" + destination_port: 51820 jump: ACCEPT - loop: "{{ vpn_server.forwards | product([vpn_server.interface]) }}" -- name: Forwarding network traffic on certain ports to Wireguard VPS service interface - become: true - ansible.builtin.iptables: - table: nat - chain: POSTROUTING - out_interface: "{{ vpn_server.interface }}" - jump: MASQUERADE \ No newline at end of file + comment: Open up port 51820 + loop: + - udp + - tcp diff --git a/roles/init-server/tasks/contingent/pkg/headscale.yml b/roles/init-server/tasks/contingent/pkg/headscale.yml index 16850c0..d2fab35 100644 --- a/roles/init-server/tasks/contingent/pkg/headscale.yml +++ b/roles/init-server/tasks/contingent/pkg/headscale.yml @@ -8,6 +8,23 @@ when: ansible_facts["system"] == "Linux" ansible.builtin.shell: cmd: "echo {{ ansible_user }}" + register: current_user +- name: Informing user of requirement of two main domains + when: (certbot.domains | length) < 2 or (certbot.domains | length) > 2 + ansible.builtin.fail: + msg: Only two domains allowed and required +- name: Informing user of requirement at least one wildcard + when: (certbot.domains | select("regex", "^\\*\\.") | list | length) == 0 + ansible.builtin.fail: + msg: At least one of the FQDNs must have a wildcard +# - name: Setting the FQDN for development +# when: compose.mode == "dev" +# ansible.builtin.set_fact: +# web_fqdn: "{{ (certbot.domains | map('regex_replace', '\\.([^\\.]*)$', '.test') | reject('regex', '^\\*\\.') | list)[0] }}" +- name: Setting the FQDN + # when: compose.mode == "prod" + ansible.builtin.set_fact: + web_fqdn: "{{ (certbot.domains | reject('regex', '^\\*\\.') | list)[0] }}" - name: Configuring Headscale become: true ansible.builtin.template: @@ -18,6 +35,7 @@ mode: "644" force: true backup: true + # validate: "headscale configtest" - name: Starting SystemD service become: true ansible.builtin.systemd_service: @@ -28,12 +46,55 @@ - name: Registering a headscale user become: true ansible.builtin.command: - # cmd: "headscale users create {{ item.username }} -d '{{ item.dname }}' -e '{{ item.email }}' -p '{{ pfp | default(default_pfp) }}'" - cmd: "headscale users create {{ item.username }} -d '{{ item.dname }}' -e '{{ item.email }}'" - # vars: - # default_pfp: ~ - loop: "{{ tail.users }}" + cmd: "headscale users create {{ headscale.users.admin.username }} -d '{{ headscale.users.admin.dname }}' -e '{{ headscale.users.admin.email }}'" register: headscale_registration changed_when: - "'User created' in headscale_registration.stdout" - - headscale_registration.rc == 0 \ No newline at end of file +- name: Creating an authentication key for this registered headscale user + become: true + ansible.builtin.command: + cmd: "headscale preauthkeys create -e 24h -u 1" + register: tailscale_admin_authkey +- name: Pausing to inquire about how to proceed + ansible.builtin.pause: + prompt: "Type \"fetch\" to get the DSNet VPN service client configuration files, or \"show\" to see their contents for manual copying instead" + echo: true + register: data_method +- name: Choosing Headscale authentication key to control node for copying + when: data_method.user_input == "show" + block: + - name: Presenting Headscale authentication key to Control Node + ansible.builtin.debug: + msg: "Copy this client configuration of the headscale service:\n {{ tailscale_admin_authkey.stdout }}" + - name: Giving opportunity to manually copy Headscale authentication key + ansible.builtin.pause: +- name: Choosing Headscale service client configuration files to control node machine + when: data_method.user_input == "fetch" + block: + - name: Creating temporary file on managed node that stores Headscale authentication key + ansible.builtin.copy: + content: "{{ tailscale_admin_authkey.stdout }}" + dest: "/tmp/headscale.key" + owner: "{{ ansible_user }}" + group: "{{ ansible_user }}" + mode: "644" + register: tailscale_admin_authkey_file + - name: Placing Headscale authentication key into file on control node + ansible.builtin.fetch: + src: "{{ tailscale_admin_authkey_file.dest }}" + dest: "./.tmp/{{ inventory_hostname }}-{{ headscale.users.admin.username }}@headscale/headscale.key" + flat: true + - name: Placing Headscale authentication key into file on control node + ansible.builtin.fetch: + src: "{{ tailscale_admin_authkey_file.dest }}" + dest: "./roles/init-server/files/{{ item.name }}-{{ headscale.users.admin.username }}@headscale/headscale{{ (idx | string) }}.key" + flat: true + loop: "{{ headscale.clients }}" + loop_control: + index_var: idx + - name: Informing control node of acquired files + ansible.builtin.debug: + msg: "The Headscale authentication key files have been duplicated to './.tmp/{{ inventory_hostname }}-{{ headscale.users.admin.username }}@headscale/headscale.key' at the control node." + - name: Giving control node user time to read the aforementiioned message + ansible.builtin.pause: + seconds: 30 \ No newline at end of file diff --git a/roles/init-server/tasks/contingent/pkg/julia.yml b/roles/init-server/tasks/contingent/pkg/julia.yml index 2283ad0..d022a56 100644 --- a/roles/init-server/tasks/contingent/pkg/julia.yml +++ b/roles/init-server/tasks/contingent/pkg/julia.yml @@ -15,13 +15,14 @@ ansible.builtin.shell: cmd: "{{ ansible_user_home.stdout }}/.local/bin/julia-install.sh --yes" creates: "{{ ansible_user_home.stdout }}/.juliaup/bin" + async: 900 + poll: 5 - name: Linking binaries to directories already in PATH environment variable become: true + ignore_errors: true ansible.builtin.file: src: "{{ ansible_user_home.stdout }}/.juliaup/bin/{{ item }}" dest: "/usr/bin/{{ item }}" - owner: root - group: root state: link loop: - julia diff --git a/roles/init-server/tasks/contingent/pkg/libpam-google-authenticator.yml b/roles/init-server/tasks/contingent/pkg/libpam-google-authenticator.yml new file mode 100644 index 0000000..38deece --- /dev/null +++ b/roles/init-server/tasks/contingent/pkg/libpam-google-authenticator.yml @@ -0,0 +1,110 @@ +--- +- name: Acquiring home of current user + when: ansible_facts["system"] == "Linux" + ansible.builtin.shell: + cmd: "echo ~{{ ansible_user }}" + register: ansible_user_home +- name: Acquiring home of current user + when: ansible_facts["system"] == "Linux" + ansible.builtin.shell: + cmd: "echo {{ ansible_user }}" + register: current_user +- name: Setting up TOTP using Google Authenticator + become: true + become_user: "{{ current_user.stdout }}" + ansible.builtin.command: + argv: + - "google-authenticator" + - "-t" + - "-d" + - "-f" + - "-C" + - "-q" + - "-l {{ ansible_user }}@{{ inventory_hostname }}" + - "-i {{ inventory_hostname }}" + - "--qr-mode=NONE" + - "-r 7" + - "-R 300" + - "-w 9" + creates: "{{ ansible_user_home.stdout }}/.google_authenticator" +- name: Pausing to inquire about how to proceed + ansible.builtin.pause: + prompt: "Type \"fetch\" to get the TOTP secret and backup codes, or \"show\" to see it for manual copying instead" + echo: true + register: data_method +- name: Choosing to present TOTP secret and backup codes to Control Node + when: data_method.user_input == "show" + block: + - name: Acquiring contents of file containing TOTP secret and backup codes + ansible.builtin.slurp: + src: "{{ ansible_user_home.stdout }}/.google_authenticator" + register: totp_token + - name: Presenting TOTP secret and backup codes to Control Node + ansible.builtin.debug: + msg: "Make sure to store the following TOTP secret and backup codes for Google Authenticator:\n {{ totp_token.content | b64decode }}" + - name: Giving opportunity to manually copy TOTP secret and backup codes + ansible.builtin.pause: +- name: Choosing to provide file on control node containing TOTP secret and backup codes + when: data_method.user_input == "fetch" + block: + - name: Placing TOTP secret and backup codes into file on control node + ansible.builtin.fetch: + src: "{{ ansible_user_home.stdout }}/.google_authenticator" + dest: "./.tmp/{{ inventory_hostname }}-google-auth/google_auth.secret" + flat: true + - name: Informing control node of acquired files + ansible.builtin.debug: + msg: "The TOTP secret and backup codes file has been duplicated to './.tmp/{{ inventory_hostname }}-google-auth/google-auth.secret' at the control node." + - name: Giving control node user time to read the aforementiioned message + ansible.builtin.pause: + seconds: 30 +- name: Adding Google Authenticator OTP module PAM authentication line for SSH + become: true + ansible.builtin.lineinfile: + path: /etc/pam.d/sshd + line: "auth sufficient pam_google_authenticator.so nullok" + insertafter: "include common-auth$" + owner: root + group: root + mode: "644" +- name: Prioritizing authentication methods in SSH + become: true + ansible.builtin.lineinfile: + path: /etc/ssh/sshd_config.d/auth.conf + line: "KbdInteractiveAuthentication yes # enable if implementing TOTP 2FA" + regexp: "^KbdInteractiveAuthentication" + owner: root + group: root + mode: "644" +- name: Prioritizing authentication methods in SSH + become: true + ansible.builtin.lineinfile: + path: /etc/ssh/sshd_config.d/auth.conf + line: "AuthenticationMethods publickey keyboard-interactive:pam" + insertafter: "^KbdInteractiveAuthentication" + owner: root + group: root + mode: "644" +# - name: Adding Google Authenticator OTP module PAM authentication line for SSH +# become: true +# ansible.builtin.lineinfile: +# path: /etc/pam.d/sudo +# line: "auth required pam_google_authenticator.so nullok" +# insertafter: "include common-auth$" +# owner: root +# group: root +# mode: "644" +# - name: Adding Google Authenticator OTP module PAM authentication line for SSH +# become: true +# ansible.builtin.lineinfile: +# path: /etc/pam.d/su +# line: "auth required pam_google_authenticator.so nullok" +# insertafter: "include common-auth$" +# owner: root +# group: root +# mode: "644" +- name: Restarting SystemD SSH service + become: true + ansible.builtin.systemd_service: + name: sshd + state: restarted \ No newline at end of file diff --git a/roles/init-server/tasks/contingent/pkg/nvm.yml b/roles/init-server/tasks/contingent/pkg/nvm.yml index bd8be17..a3b4c52 100644 --- a/roles/init-server/tasks/contingent/pkg/nvm.yml +++ b/roles/init-server/tasks/contingent/pkg/nvm.yml @@ -18,43 +18,38 @@ ansible.builtin.set_fact: prebuilt_nodepaths: "{{ prebuilt_nodes.files | map(attribute='path') }}" - name: Linking binaries to directories already in PATH environment variable + ignore_errors: true ansible.builtin.file: src: "{{ item[0] }}/bin/{{ item[1] }}" dest: "/usr/bin/{{ item[1] }}" - owner: root - group: root state: link loop: "{{ prebuilt_nodepaths | product(['node']) }}" - name: Linking binaries to directories already in PATH environment variable + ignore_errors: true ansible.builtin.file: src: "{{ item[0] }}/lib/node_modules/corepack/dist/{{ item[1] }}.js" dest: "/usr/bin/{{ item[1] }}" - owner: root - group: root state: link loop: "{{ prebuilt_nodepaths | product(['corepack']) }}" - name: Linking binaries to directories already in PATH environment variable + ignore_errors: true ansible.builtin.file: src: "{{ item[0] }}/lib/node_modules/npm/bin/{{ item[1] }}-cli.js" dest: "/usr/bin/{{ item[1] }}" - owner: root - group: root state: link loop: "{{ prebuilt_nodepaths | product(['npm','npx']) }}" - name: Link includes to directories already recognized by system + ignore_errors: true ansible.builtin.file: src: "{{ item[0] }}/include/{{ item[1] }}" dest: "/usr/include/{{ item[1] }}" - owner: root - group: root state: link loop: "{{ prebuilt_nodepaths | product(['node']) }}" - name: Link requisite libraries to directories already recognized by system + ignore_errors: true ansible.builtin.file: src: "{{ item[0] }}/lib/{{ item[1] }}" dest: "/usr/lib/{{ item[1] }}" - owner: root - group: root state: link loop: "{{ prebuilt_nodepaths | product(['node_modules']) }}" - name: Create man1 subdirectory for man pages @@ -66,11 +61,10 @@ mode: "644" state: directory - name: Link shared resources to directories already recognized by system + ignore_errors: true ansible.builtin.file: src: "{{ item[0] }}/share/man/man1/{{ item[1] }}.1" dest: "/usr/share/man/man1/{{ item[1] }}.1" - owner: root - group: root state: link loop: "{{ prebuilt_nodepaths | product(['node']) }}" - name: Create man1 subdirectory for man pages @@ -82,11 +76,10 @@ mode: "644" state: directory - name: Link shared resources to directories already recognized by system + ignore_errors: true ansible.builtin.file: src: "{{ item[0] }}/share/doc/{{ item[1] }}" dest: "/usr/share/doc/{{ item[1] }}" - owner: root - group: root state: link loop: "{{ prebuilt_nodepaths | product(['node']) }}" # - name: Reboot machine for shell environment change diff --git a/roles/init-server/tasks/contingent/pkg/podman.yml b/roles/init-server/tasks/contingent/pkg/podman.yml new file mode 100644 index 0000000..82dbbb3 --- /dev/null +++ b/roles/init-server/tasks/contingent/pkg/podman.yml @@ -0,0 +1,65 @@ +--- +- 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: Ensuring user namespace support is enabled + become: true + ansible.posix.sysctl: + name: kernel.unprivileged_userns_clone + value: "1" + sysctl_set: true + state: present +- name: Ensuring user namespace support is enabled + become: true + ansible.posix.sysctl: + name: net.ipv4.ip_unprivileged_port_start + value: "0" + sysctl_set: true + state: present +- name: Creating container directory + ansible.builtin.file: + path: "{{ ansible_user_home.stdout }}/.config/containers" + recurse: true + owner: "{{ ansible_user }}" + group: "{{ ansible_user }}" + mode: "755" + state: directory +- name: Configuring container storage + become: true + become_user: "{{ current_user.stdout }}" + ansible.builtin.template: + src: user/config/containers/storage.conf.j2 + dest: "{{ ansible_user_home.stdout }}/.config/containers/storage.conf" + owner: "{{ ansible_user }}" + group: "{{ ansible_user }}" + mode: "644" + force: true + backup: true +- name: Configuring container image registries + become: true + become_user: "{{ current_user.stdout }}" + ansible.builtin.copy: + src: user/config/containers/registries.conf + dest: "{{ ansible_user_home.stdout }}/.config/containers/" + owner: "{{ ansible_user }}" + group: "{{ ansible_user }}" + mode: "644" + force: true + backup: true +# @NOTE https://oneuptime.com/blog/post/2026-01-27-podman-rootless/view#configuring-registries +# @NOTE https://github.com/podman-container-tools/podman/blob/main/docs/tutorials/rootless_tutorial.md#using-volumes +# @NOTE https://github.com/containers/podman-compose/issues/166#issuecomment-1550515230 +- name: Enabling and starting SystemD unit service for automatic restart of containers/pods + become: true + ansible.builtin.systemd_service: + name: podman-restart + scope: system + enabled: true + state: started \ No newline at end of file diff --git a/roles/init-server/tasks/contingent/pkg/quartz.yml b/roles/init-server/tasks/contingent/pkg/quartz.yml index 1fe7803..57ccf1f 100644 --- a/roles/init-server/tasks/contingent/pkg/quartz.yml +++ b/roles/init-server/tasks/contingent/pkg/quartz.yml @@ -4,23 +4,180 @@ ansible.builtin.shell: cmd: "echo ~{{ ansible_user }}" register: ansible_user_home +- name: Acquiring home of current user + when: ansible_facts["system"] == "Linux" + ansible.builtin.shell: + cmd: "echo {{ ansible_user }}" + register: current_user +- name: Informing user of requirement of two main domains + when: (certbot.domains | length) < 2 or (certbot.domains | length) > 2 + ansible.builtin.fail: + msg: Only two domains allowed and required +- name: Informing user of requirement at least one wildcard + when: (certbot.domains | select("regex", "^\\*\\.") | list | length) == 0 + ansible.builtin.fail: + msg: At least one of the FQDNs must have a wildcard +# - name: Setting the FQDN for development +# when: compose.mode == "dev" +# ansible.builtin.set_fact: +# web_fqdn: "{{ (certbot.domains | map('regex_replace', '\\.([^\\.]*)$', '.test') | reject('regex', '^\\*\\.') | list)[0] }}" +- name: Setting the FQDN for production + # when: compose.mode == "prod" + ansible.builtin.set_fact: + web_fqdn: "{{ (certbot.domains | reject('regex', '^\\*\\.') | list)[0] }}" +- name: Linking repository to another path + ignore_errors: true + ansible.builtin.file: + src: "{{ ansible_user_home.stdout }}/repos/.foreign/quartz" + dest: "{{ ansible_user_home.stdout }}/repos/skato-quartz" + state: link - name: Installing NodeJS dependencies of quartz software + become: true + become_user: "{{ current_user.stdout }}" community.general.npm: path: "{{ ansible_user_home.stdout }}/repos/.foreign/quartz" state: latest - name: Configuring quartz software block: + - name: Creating path for Quartz content files (path for Obsidian vaults) + ansible.builtin.file: + path: "{{ ansible_user_home.stdout }}/journal/notes" + recurse: true + owner: "{{ ansible_user }}" + group: "{{ ansible_user }}" + mode: "755" + state: directory + - name: Creating some initial text content for Quartz + become: true + become_user: "{{ current_user.stdout }}" + ansible.builtin.template: + src: "user/journal/notes/index.md.j2" + dest: "{{ ansible_user_home.stdout }}/journal/notes/index.md" + owner: "{{ ansible_user }}" + group: "{{ ansible_user }}" + mode: "644" + backup: true + - name: Creating some initial image content for Quartz + become: true + become_user: "{{ current_user.stdout }}" + ansible.builtin.copy: + src: user/journal/mythe-sisyphus-klein.png + dest: "{{ ansible_user_home.stdout }}/journal/notes/mythe-sisyphus-klein.png" + owner: "{{ ansible_user }}" + group: "{{ ansible_user }}" + mode: "644" + backup: true - name: Initializing quartz website + become: true + become_user: "{{ current_user.stdout }}" ansible.builtin.command: + argv: + - npx + - "-y" + - quartz + - create + - "-b" + - notes.{{ web_fqdn }}" + - "-t" + - obsidian + - "-s" + - "{{ ansible_user_home.stdout }}/journal/notes" + - "-X" + - symlink chdir: "{{ ansible_user_home.stdout }}/repos/.foreign/quartz" - cmd: npx quartz create + creates: "{{ ansible_user_home.stdout }}/repos/.foreign/quartz/content/index.md" - name: Installing quartz plugins referenced in website template + become: true + become_user: "{{ current_user.stdout }}" ansible.builtin.command: + argv: + - npx + - "-y" + - quartz + - plugin + - install chdir: "{{ ansible_user_home.stdout }}/repos/.foreign/quartz" - cmd: npx quartz plugin install --from-config -# - name: Starting quartz site web server -# ansible.builtin.command: -# chdir: "{{ ansible_user_home.stdout }}/repos/.foreign/quartz" -# cmd: npx quartz build --serve -# register: stdout -# changed_when: stdout \ No newline at end of file +- name: Starting quartz site web server + become: true + become_user: "{{ current_user.stdout }}" + ansible.builtin.command: + argv: + - npx + - "-y" + - quartz + - build + - "-o" + - "{{ ansible_user_home.stdout }}/srv/notes.{{ web_fqdn }}" + - "--concurrency" + - "3" + chdir: "{{ ansible_user_home.stdout }}/repos/.foreign/quartz" + creates: "{{ ansible_user_home.stdout }}/srv/notes.{{ web_fqdn }}/index.html" +- name: Creating directory for caddy configuration + ansible.builtin.file: + path: "{{ ansible_user_home.stdout }}/.config/caddy" + recurse: true + owner: "{{ ansible_user }}" + group: "{{ ansible_user }}" + state: directory +- name: Adding Caddyfile subdomain entry + when: "(caddy is defined and caddy != None) and caddy.containerized and mode == 'prod'" + ansible.builtin.blockinfile: + path: "{{ ansible_user_home.stdout }}/.config/caddy/Caddyfile" + block: | + notes.{{ web_fqdn }} { + respond 503 + # root /srv/notes.{{ web_fqdn }} + file_server + encode gzip + + handle_errors { + root /srv/{{ web_fqdn }} + rewrite /error/{err.status_code}.html + templates + } + } + prepend_newline: true + marker: "# <-- {mark} ANSIBLE MANAGED NOTES DOMAIN -->" + owner: "{{ ansible_user }}" + group: "{{ ansible_user }}" + mode: "644" + create: true + state: present +- name: Adding Caddyfile subdomain entry + when: "(caddy is defined and caddy != None) and caddy.containerized and (mode == 'dev' or caddy.scheme == 'http')" + ansible.builtin.blockinfile: + path: "{{ ansible_user_home.stdout }}/.config/caddy/Caddyfile" + block: | + http://notes.{{ web_fqdn }} { + respond 503 + # root /srv/notes.{{ web_fqdn }} + file_server + encode gzip + + handle_errors { + root /srv/{{ web_fqdn }} + rewrite /error/{err.status_code}.html + templates + } + } + prepend_newline: true + marker: "# <-- {mark} ANSIBLE MANAGED NOTES DOMAIN -->" + owner: "{{ ansible_user }}" + group: "{{ ansible_user }}" + mode: "644" + create: true + state: present +- name: Checking the status of podman containers + ansible.builtin.command: + argv: + - podman + - ps + register: podman_status +- name: Restarting webserver / reverse proxy container + become: true + become_user: "{{ current_user.stdout }}" + when: "'revproxy0' in podman_status.stdout and (caddy is defined and caddy != None) and caddy.containerized" + containers.podman.podman_container: + name: "{{ compose.containers.webserver.name }}" + state: started + force_restart: true \ No newline at end of file diff --git a/roles/init-server/tasks/contingent/pkg/radicle.yml b/roles/init-server/tasks/contingent/pkg/radicle.yml index b2efd26..ee55838 100644 --- a/roles/init-server/tasks/contingent/pkg/radicle.yml +++ b/roles/init-server/tasks/contingent/pkg/radicle.yml @@ -15,10 +15,13 @@ ansible.builtin.shell: cmd: "{{ ansible_user_home.stdout }}/.local/bin/radicle-install.sh" creates: "{{ ansible_user_home.stdout }}/.radicle" + async: 600 + poll: 5 - name: Bootstrapping Radicle become: true block: - name: Linking binaries to directories already in PATH environment variable + ignore_errors: true ansible.builtin.file: src: "{{ ansible_user_home.stdout }}/.radicle/bin/{{ item }}" dest: "/usr/bin/{{ item }}" @@ -36,6 +39,7 @@ mode: "644" state: directory - name: Link manpages to Linux manpage directories + ignore_errors: true ansible.builtin.file: src: "{{ ansible_user_home.stdout }}/.radicle/man/man1/{{ item }}.1" dest: "/usr/share/man/man1/{{ item }}.1" diff --git a/roles/init-server/tasks/contingent/pkg/rustup.yml b/roles/init-server/tasks/contingent/pkg/rustup.yml index 4a56538..52fc730 100644 --- a/roles/init-server/tasks/contingent/pkg/rustup.yml +++ b/roles/init-server/tasks/contingent/pkg/rustup.yml @@ -15,8 +15,11 @@ ansible.builtin.shell: cmd: "{{ ansible_user_home.stdout }}/.local/bin/rustup-install.sh -yq" creates: "{{ ansible_user_home.stdout }}/.cargo/bin" + async: 600 + poll: 5 - name: Linking binaries to directories already in PATH environment variable become: true + ignore_errors: true ansible.builtin.file: src: "{{ ansible_user_home.stdout }}/.cargo/bin/{{ item }}" dest: "/usr/bin/{{ item }}" diff --git a/roles/init-server/tasks/contingent/pkg/skato_blog.yml b/roles/init-server/tasks/contingent/pkg/skato_blog.yml new file mode 100644 index 0000000..a0ef739 --- /dev/null +++ b/roles/init-server/tasks/contingent/pkg/skato_blog.yml @@ -0,0 +1,171 @@ +--- +- name: Acquiring home of current user + when: ansible_facts["system"] == "Linux" + ansible.builtin.shell: + cmd: "echo ~{{ ansible_user }}" + register: ansible_user_home +- name: Acquiring home of current user + when: ansible_facts["system"] == "Linux" + ansible.builtin.shell: + cmd: "echo {{ ansible_user }}" + register: current_user +- name: Informing user of requirement of two main domains + when: (certbot.domains | length) < 2 or (certbot.domains | length) > 2 + ansible.builtin.fail: + msg: Only two domains allowed and required +- name: Informing user of requirement at least one wildcard + when: (certbot.domains | select("regex", "^\\*\\.") | list | length) == 0 + ansible.builtin.fail: + msg: At least one of the FQDNs must have a wildcard +# - name: Setting the FQDN for development +# when: compose.mode == "dev" +# ansible.builtin.set_fact: +# web_fqdn: "{{ (certbot.domains | map('regex_replace', '\\.([^\\.]*)$', '.test') | reject('regex', '^\\*\\.') | list)[0] }}" +- name: Setting the FQDN + # when: compose.mode == "prod" + ansible.builtin.set_fact: + web_fqdn: "{{ (certbot.domains | reject('regex', '^\\*\\.') | list)[0] }}" +- name: Moving git repository from initial path + block: + - name: Recursively copying directory and its contents to elsewhere + ansible.builtin.copy: + src: "{{ ansible_user_home.stdout }}/repos/.foreign/{{ source_code.repos.blog.name }}" + remote_src: true + dest: "{{ ansible_user_home.stdout }}/repos/" + owner: "{{ ansible_user }}" + group: "{{ ansible_user }}" + register: new_blog_path + - name: Deleting directory at previous path + ansible.builtin.file: + path: "{{ ansible_user_home.stdout }}/repos/.foreign/{{ source_code.repos.blog.name }}" + state: absent + - name: Creating directory for new bare repository + ansible.builtin.file: + path: "{{ ansible_user_home.stdout }}/src" + recurse: true + owner: "{{ ansible_user }}" + group: "{{ ansible_user }}" + state: directory + - name: Creating bare repository + ansible.builtin.command: + cmd: "git init --bare {{ source_code.repos.blog.name }}.git" + chdir: "{{ ansible_user_home.stdout }}/src" + creates: "{{ ansible_user_home.stdout }}/src/{{ source_code.repos.blog.name }}.git" +- name: Running Hugo blog + when: source_code.repos.blog.run + block: + - name: Creating path for Hugo content files + when: caddy.containerized and (compose.containers.webserver is defined or compose.containers.webserver != None) + ansible.builtin.file: + path: "{{ ansible_user_home.stdout }}/journal/blog" + recurse: true + owner: "{{ ansible_user }}" + group: "{{ ansible_user }}" + mode: "755" + state: directory + - name: Creating some initial text content for Hugo + become: true + become_user: "{{ current_user.stdout }}" + when: caddy.containerized and (compose.containers.webserver is defined or compose.containers.webserver != None) + ansible.builtin.template: + src: "user/journal/blog/_index.md.j2" + dest: "{{ ansible_user_home.stdout }}/journal/blog/index.md" + owner: "{{ ansible_user }}" + group: "{{ ansible_user }}" + mode: "644" + backup: true + - name: Creating some initial image content for Hugo + become: true + become_user: "{{ current_user.stdout }}" + when: caddy.containerized and (compose.containers.webserver is defined or compose.containers.webserver != None) + ansible.builtin.copy: + src: "user/journal/mythe-sisyphus-klein.png" + dest: "{{ ansible_user_home.stdout }}/journal/blog/mythe-sisyphus-klein.png" + owner: "{{ ansible_user }}" + group: "{{ ansible_user }}" + mode: "644" + backup: true + - name: Creating subdirectory for blog website root + when: caddy.containerized and (compose.containers.webserver is defined or compose.containers.webserver != None) + ansible.builtin.file: + path: "{{ ansible_user_home.stdout }}/srv/blog.{{ web_fqdn }}" + owner: "{{ ansible_user }}" + group: "{{ ansible_user }}" + mode: "755" + state: directory + - name: Build Hugo blog at additional webroot + when: caddy.containerized and (compose.containers.webserver is defined or compose.containers.webserver != None) + ansible.builtin.command: + argv: + - hugo + - "--quiet" + - "-b" + - "https://blog.{{ web_fqdn }}/" + - "-c" + - "{{ ansible_user_home.stdout }}/journal/blog" + - "-d" + - "{{ ansible_user_home.stdout }}/srv/blog.{{ web_fqdn }}" + - "--cleanDestinationDir" + chdir: "{{ new_blog_path.dest }}" + creates: "{{ ansible_user_home.stdout }}/srv/blog.{{ web_fqdn }}/index.html" + # @TODO write error Caddy template HTML file at the blog's web root + - name: Adding Caddyfile subdomain entry + when: caddy.containerized and mode == 'prod' and (compose.containers.webserver is defined or compose.containers.webserver != None) + ansible.builtin.blockinfile: + path: "{{ ansible_user_home.stdout }}/.config/caddy/Caddyfile" + block: | + blog.{{ web_fqdn }} { + respond 503 + # root /srv/blog.{{ web_fqdn }} + file_server + encode gzip + + handle_errors { + root /srv/{{ web_fqdn }} + rewrite /error/{err.status_code}.html + templates + } + } + prepend_newline: true + marker: "# <-- {mark} ANSIBLE MANAGED BLOG DOMAIN -->" + owner: "{{ ansible_user }}" + group: "{{ ansible_user }}" + mode: "644" + state: present + - name: Adding Caddyfile subdomain entry + when: caddy.containerized and (mode == 'dev' or caddy.scheme == 'http') and (compose.containers.webserver is defined or compose.containers.webserver != None) + ansible.builtin.blockinfile: + path: "{{ ansible_user_home.stdout }}/.config/caddy/Caddyfile" + block: | + http://blog.{{ web_fqdn }} { + respond 503 + # root /srv/blog.{{ web_fqdn }} + file_server + encode gzip + + handle_errors { + root /srv/{{ web_fqdn }} + rewrite /error/{err.status_code}.html + templates + } + } + prepend_newline: true + marker: "# <-- {mark} ANSIBLE MANAGED BLOG DOMAIN -->" + owner: "{{ ansible_user }}" + group: "{{ ansible_user }}" + mode: "644" + state: present +- name: Checking the status of podman containers + ansible.builtin.command: + argv: + - podman + - ps + register: podman_status +- name: Restarting webserver / reverse proxy container + become: true + become_user: "{{ current_user.stdout }}" + when: "'revproxy0' in podman_status.stdout and (caddy is defined and caddy != None) and caddy.containerized" + containers.podman.podman_container: + name: "{{ compose.containers.webserver.name }}" + state: started + force_restart: true \ No newline at end of file diff --git a/roles/init-server/tasks/contingent/pkg/skato_blog_theme.yml b/roles/init-server/tasks/contingent/pkg/skato_blog_theme.yml new file mode 100644 index 0000000..204fe4b --- /dev/null +++ b/roles/init-server/tasks/contingent/pkg/skato_blog_theme.yml @@ -0,0 +1,45 @@ +--- +- name: Acquiring home of current user + when: ansible_facts["system"] == "Linux" + ansible.builtin.shell: + cmd: "echo ~{{ ansible_user }}" + register: ansible_user_home +- name: Acquiring home of current user + when: ansible_facts["system"] == "Linux" + ansible.builtin.shell: + cmd: "echo {{ ansible_user }}" + register: current_user +- name: Moving git repository from initial path + block: + - name: Recursively copying directory and its contents to elsewhere + ansible.builtin.copy: + src: "{{ ansible_user_home.stdout }}/repos/.foreign/{{ source_code.repos.blog_theme.name }}" + remote_src: true + dest: "{{ ansible_user_home.stdout }}/repos/" + owner: "{{ ansible_user }}" + group: "{{ ansible_user }}" + register: new_compose_path + - name: Deleting directory at previous path + ansible.builtin.file: + path: "{{ ansible_user_home.stdout }}/repos/.foreign/{{ source_code.repos.blog_theme.name }}" + state: absent + - name: Creating directory for new bare repository + ansible.builtin.file: + path: "{{ ansible_user_home.stdout }}/src" + recurse: true + owner: "{{ ansible_user }}" + group: "{{ ansible_user }}" + state: directory + - name: Creating bare repository + ansible.builtin.command: + cmd: "git init --bare {{ source_code.repos.blog_theme.name }}.git" + chdir: "{{ ansible_user_home.stdout }}/src" + creates: "{{ ansible_user_home.stdout }}/src/{{ source_code.repos.blog_theme.name }}.git" +- name: Running Hugo blog theme + when: source_code.repos.blog_theme.run + # become: true + # become_user: "{{ current_user.stdout }}" + block: + - name: Warning about lack of implementation + ansible.builtin.debug: + msg: Not yet implemented \ No newline at end of file diff --git a/roles/init-server/tasks/contingent/pkg/skato_cli.yml b/roles/init-server/tasks/contingent/pkg/skato_cli.yml new file mode 100644 index 0000000..dcd3333 --- /dev/null +++ b/roles/init-server/tasks/contingent/pkg/skato_cli.yml @@ -0,0 +1,45 @@ +--- +- name: Acquiring home of current user + when: ansible_facts["system"] == "Linux" + ansible.builtin.shell: + cmd: "echo ~{{ ansible_user }}" + register: ansible_user_home +- name: Acquiring home of current user + when: ansible_facts["system"] == "Linux" + ansible.builtin.shell: + cmd: "echo {{ ansible_user }}" + register: current_user +- name: Moving git repository from initial path + block: + - name: Recursively copying directory and its contents to elsewhere + ansible.builtin.copy: + src: "{{ ansible_user_home.stdout }}/repos/.foreign/{{ source_code.repos.cli.name }}" + remote_src: true + dest: "{{ ansible_user_home.stdout }}/repos/" + owner: "{{ ansible_user }}" + group: "{{ ansible_user }}" + register: new_compose_path + - name: Deleting directory at previous path + ansible.builtin.file: + path: "{{ ansible_user_home.stdout }}/repos/.foreign/{{ source_code.repos.cli.name }}" + state: absent + - name: Creating directory for new bare repository + ansible.builtin.file: + path: "{{ ansible_user_home.stdout }}/src" + recurse: true + owner: "{{ ansible_user }}" + group: "{{ ansible_user }}" + state: directory + - name: Creating bare repository + ansible.builtin.command: + cmd: "git init --bare {{ source_code.repos.cli.name }}.git" + chdir: "{{ ansible_user_home.stdout }}/src" + creates: "{{ ansible_user_home.stdout }}/src/{{ source_code.repos.cli.name }}.git" +- name: Running CLI utility + when: source_code.repos.cli.run + # become: true + # become_user: "{{ current_user.stdout }}" + block: + - name: Warning about lack of implementation + ansible.builtin.debug: + msg: Not yet implemented \ No newline at end of file diff --git a/roles/init-server/tasks/contingent/pkg/skato_compose.yml b/roles/init-server/tasks/contingent/pkg/skato_compose.yml new file mode 100644 index 0000000..560f9cc --- /dev/null +++ b/roles/init-server/tasks/contingent/pkg/skato_compose.yml @@ -0,0 +1,836 @@ +--- +- name: Acquiring home of current user + when: ansible_facts["system"] == "Linux" + ansible.builtin.shell: + cmd: "echo ~{{ ansible_user }}" + register: ansible_user_home +- name: Acquiring home of current user + when: ansible_facts["system"] == "Linux" + ansible.builtin.shell: + cmd: "echo {{ ansible_user }}" + register: current_user +- name: Informing user of requirement of two main domains + when: (certbot.domains | length) < 2 or (certbot.domains | length) > 2 + ansible.builtin.fail: + msg: Only two domains allowed and required +- name: Informing user of requirement at least one wildcard + when: (certbot.domains | select("regex", "^\\*\\.") | list | length) == 0 + ansible.builtin.fail: + msg: At least one of the FQDNs must have a wildcard +# - name: Setting the FQDN for development +# when: compose.mode == "dev" +# ansible.builtin.set_fact: +# web_fqdn: "{{ (certbot.domains | map('regex_replace', '\\.([^\\.]*)$', '.test') | reject('regex', '^\\*\\.') | list)[0] }}" +- name: Setting the FQDN for production + # when: compose.mode == "prod" + ansible.builtin.set_fact: + web_fqdn: "{{ (certbot.domains | reject('regex', '^\\*\\.') | list)[0] }}" +- name: Moving git repository from initial path + block: + - name: Recursively copying directory and its contents to elsewhere + become: true + become_user: "{{ current_user.stdout }}" + ansible.builtin.copy: + src: "{{ ansible_user_home.stdout }}/repos/.foreign/{{ source_code.repos.compose.name }}" + remote_src: true + dest: "{{ ansible_user_home.stdout }}/repos/" + owner: "{{ ansible_user }}" + group: "{{ ansible_user }}" + register: new_compose_path + - name: Deleting directory at previous path + ansible.builtin.file: + path: "{{ ansible_user_home.stdout }}/repos/.foreign/{{ source_code.repos.compose.name }}" + state: absent + - name: Creating directory for new bare repository + ansible.builtin.file: + path: "{{ ansible_user_home.stdout }}/src" + recurse: true + owner: "{{ ansible_user }}" + group: "{{ ansible_user }}" + state: directory + - name: Creating bare repository + ansible.builtin.command: + cmd: "git init --bare {{ source_code.repos.compose.name }}.git" + chdir: "{{ ansible_user_home.stdout }}/src" + creates: "{{ ansible_user_home.stdout }}/src/{{ source_code.repos.compose.name }}.git" +- name: Creating required SMTP-related container secret + become: true + # become_user: "{{ current_user.stdout }}" + ansible.builtin.lineinfile: + line: "{{ email.smtp.password }}" + path: "{{ ansible_user_home.stdout }}/.podsecrets/email.pass" + insertafter: EOF + owner: "{{ ansible_user }}" + group: "{{ ansible_user }}" + mode: "644" + create: true + backup: true +- name: Creating environment file + become: true + become_user: "{{ current_user.stdout }}" + ansible.builtin.template: + src: user/all.env.j2 + dest: "{{ ansible_user_home.stdout }}/.all.env" + owner: "{{ ansible_user }}" + group: "{{ ansible_user }}" + mode: "644" + force: true + backup: true + register: environ +- name: Creating environment file for email + become: true + become_user: "{{ current_user.stdout }}" + ansible.builtin.template: + src: user/email.env.j2 + dest: "{{ ansible_user_home.stdout }}/.email.env" + owner: "{{ ansible_user }}" + group: "{{ ansible_user }}" + mode: "644" + force: true + backup: true + register: email_environ +- name: Creating a directory for container secrets + ansible.builtin.file: + path: "{{ ansible_user_home.stdout }}/.podsecrets" + recurse: true + owner: "{{ ansible_user }}" + group: "{{ ansible_user }}" + mode: "644" + state: directory +- name: Creating directory for DBMS server configuration + ansible.builtin.file: + path: "{{ ansible_user_home.stdout }}/.config/{{ item }}" + recurse: true + owner: "{{ ansible_user }}" + group: "{{ ansible_user }}" + mode: "755" + state: directory + loop: + - caddy + - letsencrypt + - mysql + - redis + - gitea + - opengist + - tailscale + - glance +- name: Creating directory for main website root + ansible.builtin.file: + path: "{{ ansible_user_home.stdout }}/srv/{{ web_fqdn }}" + recurse: true + owner: "{{ ansible_user }}" + group: "{{ ansible_user }}" + mode: "755" + state: directory +- name: Creating directory for caddy configuration + ansible.builtin.file: + path: "{{ ansible_user_home.stdout }}/.config/caddy" + recurse: true + owner: "{{ ansible_user }}" + group: "{{ ansible_user }}" + state: directory +# - name: Pulling all needed container images for Compose services +# become: true +# become_user: "{{ current_user.stdout }}" +# ansible.builtin.command: +# cmd: podman-compose pull +# chdir: "{{ new_compose_path.dest }}{{ source_code.repos.compose.rpath | default('/independent') }}" +- name: Calculating desired container states + block: + - name: Calculating desired container state for VPN client + ansible.builtin.set_fact: + # @TODO write case of at least one vpn client having a boolean attribute declaring whether it is a container + vpn_run: "{{ source_code.repos.compose.run and (vpn.clients | selectattr('name', 'in', web_fqdn) | length) == 1 and (compose.containers.vpn is defined and compose.containers.vpn != None) }}" + - name: Calculating desired container state for web server or reverse proxy server + ansible.builtin.set_fact: + server_run: "{{ source_code.repos.compose.run and caddy.containerized and (compose.containers.webserver is defined and compose.containers.webserver != None) }}" + - name: Calculatng desired container state for ACME challenge + ansible.builtin.set_fact: + ssl_run: "{{ server_run and certbot.containerized and (compose.containers.ssl is defined and compose.containers.ssl != None) }}" + - name: Calculating desired container state for database management + ansible.builtin.set_fact: + dbms_run: "{{ source_code.repos.compose.run and mysql.containerized and (compose.containers.db is defined and compose.containers.db != None) }}" + - name: Calculating desired container state for caching server + ansible.builtin.set_fact: + cache_run: "{{ source_code.repos.compose.run and redis.containerized and (compose.containers.cache is defined and compose.containers.cache != None) }}" + - name: Calculating desired container state for cloud server + ansible.builtin.set_fact: + cloud_run: "{{ source_code.repos.compose.run and nextcloud.containerized and (compose.containers.cloud is defined and compose.containers.cloud != None) }}" + - name: Calculating desired container state for forge server + ansible.builtin.set_fact: + forge_run: "{{ source_code.repos.compose.run and gitea.containerized and (compose.containers.forge is defined and compose.containers.forge != None ) }}" + - name: Calculating desired container state for pastebin server + ansible.builtin.set_fact: + pbin_run: "{{ source_code.repos.compose.run and gist.containerized and (compose.containers.pastebin is defined and compose.containers.pastebin != None) }}" + - name: Calculating desired container state for tailnet client + ansible.builtin.set_fact: + tail_run: "{{ source_code.repos.compose.run and tailscale.containerized and (compose.containers.tail is defined and compose.containers.tail != None) }}" + - name: Calculating desired container state for tailnet dashboard + ansible.builtin.set_fact: + dash_run: "{{ source_code.repos.compose.run and glance.containerized and (compose.containers.dash is defined and compose.containers.dash != None) }}" +- name: Running VPN client Compose files + when: vpn_run + block: + - name: Creating subdirectory for VPN client container specified by Compose file + ansible.builtin.file: + path: "{{ ansible_user_home.stdout }}/.wg/containerized" + recurse: true + owner: "{{ ansible_user }}" + group: "{{ ansible_user }}" + state: directory + - name: Copying VPN client configuration files + become: true + become_user: "{{ current_user.stdout }}" + when: item.name == inventory_hostname + ansible.builtin.copy: + src: "user/wg/containerized/{{ item.name }}{{ (idx | string) }}.conf" + dest: "{{ ansible_user_home.stdout }}/.wg/containerized/" + owner: "{{ ansible_user }}" + group: "{{ ansible_user }}" + mode: "644" + force: true + backup: true + loop: "{{ vpn.clients }}" + loop_control: + index_var: idx + - name: Creating and deploying VPN client container specified by Compose file + become: true + become_user: "{{ current_user.stdout }}" + when: source_code.repos.compose.run and (vpn.clients | selectattr("name", "in", web_fqdn) | length) == 1 and (compose.containers.vpn is defined and compose.containers.vpn != None) + ansible.builtin.command: + cmd: "podman-compose up -d {{ compose.containers.vpn.name }}" + chdir: "{{ new_compose_path.dest }}{{ source_code.repos.compose.rpath | default('/independent') }}" + - name: Opening port 51820 + become: true + ansible.builtin.iptables: + chain: INPUT + protocol: "{{ item }}" + destination_port: 51820 + jump: ACCEPT + comment: Open up port 51820 + loop: + - udp + - tcp +- name: Spinning up database management container specified by Compose file + when: dbms_run + block: + - name: Creating required container secret for DBMS server container's root account + become: true + # become_user: "{{ current_user.stdout }}" + ansible.builtin.lineinfile: + line: "{{ mysql.password }}" + path: "{{ ansible_user_home.stdout }}/.podsecrets/root-mysql.pass" + insertafter: EOF + owner: "{{ ansible_user }}" + group: "{{ ansible_user }}" + mode: "644" + create: true + backup: true + - name: Creatng required container secret for DBMS server container's primary non-root account + become: true + # become_user: "{{ current_user.stdout }}" + ansible.builtin.lineinfile: + line: "{{ mysql.users.admin.password }}" + path: "{{ ansible_user_home.stdout }}/.podsecrets/user-mysql.pass" + insertafter: EOF + owner: "{{ ansible_user }}" + group: "{{ ansible_user }}" + mode: "644" + create: true + backup: true + - name: Creating environment file for DBMS server container specified in Compose file + become: true + become_user: "{{ current_user.stdout }}" + ansible.builtin.template: + src: user/mysql.env.j2 + dest: "{{ ansible_user_home.stdout }}/.mysql.env" + owner: "{{ ansible_user }}" + group: "{{ ansible_user }}" + mode: "644" + force: true + backup: true + register: mysql_environ + - name: Creating and deploying DBMS server container specified by Compose file + become: true + become_user: "{{ current_user.stdout }}" + ansible.builtin.command: + cmd: "podman-compose --env-file {{ mysql_environ.dest }} --env-file {{ environ.dest }} up -d {{ compose.containers.db.name }}" + chdir: "{{ new_compose_path.dest }}{{ source_code.repos.compose.rpath | default('/independent') }}" + # @TODO see if manual creation of additional databases is necessary for the DBMS server container + # REDIS +- name: Spinning up caching container specified by Compose file + when: cache_run + block: + - name: Creating environment file for DBMS server container specified in Compose file + become: true + become_user: "{{ current_user.stdout }}" + ansible.builtin.template: + src: user/redis.env.j2 + dest: "{{ ansible_user_home.stdout }}/.redis.env" + owner: "{{ ansible_user }}" + group: "{{ ansible_user }}" + mode: "644" + force: true + backup: true + register: redis_environ + - name: Creating and deploying cache server container specified by Compose file + become: true + become_user: "{{ current_user.stdout }}" + ansible.builtin.command: + cmd: "podman-compose --env-file {{ environ.dest }} up -d {{ compose.containers.cache.name }}" + chdir: "{{ new_compose_path.dest }}{{ source_code.repos.compose.rpath | default('/independent') }}" +- name: Spinning up cloud container specified by Compose file + when: cloud_run + block: + - name: Creating database necessary for cloud server container specified by Compose file + become: true + become_user: "{{ current_user.stdout }}" + when: dbms_run + containers.podman.podman_container_exec: + name: "{{ compose.containers.db.name }}" + argv: + - mysql + - "-u" + - "{{ mysql.users.admin.username }}" + - "-p{{ mysql.users.admin.password }}" + - "-e" + - "'CREATE DATABASE IF NOT EXISTS {{ mysql.users.admin.databases.nextcloud.name }};'" + detach: true + - name: Creating required cache-related container secret for cloud server container specified by Compose file + become: true + # become_user: "{{ current_user.stdout }}" + when: cache_run + ansible.builtin.lineinfile: + line: "{{ redis.password }}" + dest: "{{ ansible_user_home.stdout }}/.podsecrets/redis.pass" + insertafter: EOF + owner: "{{ ansible_user }}" + group: "{{ ansible_user }}" + mode: "644" + create: true + backup: true + - name: Creating environment file for cloud server container specified by Compose file + become: true + become_user: "{{ current_user.stdout }}" + ansible.builtin.template: + src: user/nextcloud.env.j2 + dest: "{{ ansible_user_home.stdout }}/.nextcloud.env" + owner: "{{ ansible_user }}" + group: "{{ ansible_user }}" + mode: "644" + force: true + backup: true + register: nextcloud_environ + - name: Creating and deploying DBMS server container specified by Compose file + become: true + become_user: "{{ current_user.stdout }}" + ansible.builtin.command: + cmd: "podman-compose --env-file {{ mysql_environ.dest }} --env-file {{ email_environ.dest }} --env-file {{ nextcloud_environ.dest }} --env-file {{ environ.dest }} up -d {{ compose.containers.cloud.name }}" + chdir: "{{ new_compose_path.dest }}{{ source_code.repos.compose.rpath | default('/independent') }}" + - name: Adding Caddyfile subdomain entry + when: "server_run and mode == 'prod'" + ansible.builtin.blockinfile: + path: "{{ ansible_user_home.stdout }}/.config/caddy/Caddyfile" + block: | + {{ nextcloud.subdomain }}.{{ web_fqdn }} { + root /srv/{{ nextcloud.subdomain }}.{{ web_fqdn }} + file_server + php_fastcgi localhost:9000 + + handle_errors { + root /srv/{{ web_fqdn }} + rewrite /error/{err.status_code}.html + templates + encode gzip + } + } + prepend_newline: true + marker: "# <-- {mark} ANSIBLE MANAGED CLOUD DOMAIN -->" + owner: "{{ ansible_user }}" + group: "{{ ansible_user }}" + create: true + mode: "644" + state: present + - name: Adding Caddyfile subdomain entry + when: "server_run and (mode == 'dev' or caddy.scheme == 'http')" + ansible.builtin.blockinfile: + path: "{{ ansible_user_home.stdout }}/.config/caddy/Caddyfile" + block: | + http://{{ nextcloud.subdomain }}.{{ web_fqdn }} { + root /srv/{{ nextcloud.subdomain }}.{{ web_fqdn }} + file_server + php_fastcgi localhost:9000 + + handle_errors { + root /srv/{{ web_fqdn }} + rewrite /error/{err.status_code}.html + templates + encode gzip + } + } + prepend_newline: true + marker: "# <-- {mark} ANSIBLE MANAGED CLOUD DOMAIN -->" + owner: "{{ ansible_user }}" + group: "{{ ansible_user }}" + create: true + mode: "644" + state: present + # - name: Restarting webserver / reverse proxy container + # become: true + # become_user: "{{ current_user.stdout }}" + # when: server_run + # containers.podman.podman_container: + # name: "{{ compose.containers.webserver.name }}" + # state: started + # force_restart: true +- name: Spinning up forge container specified by Compose file + when: forge_run + block: + - name: Creating database necessary for forge server container specified by Compose file + become: true + become_user: "{{ current_user.stdout }}" + when: dbms_run + containers.podman.podman_container_exec: + name: "{{ compose.containers.db.name }}" + argv: + - mysql + - "-u" + - "{{ mysql.users.admin.username }}" + - "-p{{ mysql.users.admin.password }}" + - "-e" + - "'CREATE DATABASE IF NOT EXISTS {{ mysql.users.admin.databases.gitea.name }};'" + detach: true + - name: Creating environment file for forge server container specified by Compose file + become: true + become_user: "{{ current_user.stdout }}" + ansible.builtin.template: + src: user/gitea.env.j2 + dest: "{{ ansible_user_home.stdout }}/.gitea.env" + owner: "{{ ansible_user }}" + group: "{{ ansible_user }}" + mode: "644" + force: true + backup: true + register: gitea_environ + - name: Creating and deploying forge server container specified by Compose file + become: true + become_user: "{{ current_user.stdout }}" + ansible.builtin.command: + cmd: "podman-compose --env-file {{ mysql_environ.dest }} --env-file {{ email_environ.dest }} --env-file {{ gitea_environ.dest }} --env-file {{ environ.dest }} up -d {{ compose.containers.forge.name }}" + chdir: "{{ new_compose_path.dest }}{{ source_code.repos.compose.rpath | default('/independent') }}" + - name: Adding Caddyfile subdomain entry + when: "server_run and mode == 'prod'" + ansible.builtin.blockinfile: + path: "{{ ansible_user_home.stdout }}/.config/caddy/Caddyfile" + block: | + {{ gitea.subdomain }}.{{ web_fqdn }} { + reverse_proxy localhost:3000 + + handle_errors { + root /srv/{{ web_fqdn }} + rewrite /error/{err.status_code}.html + file_server + templates + encode gzip + } + } + prepend_newline: true + marker: "# <-- {mark} ANSIBLE MANAGED CLOUD DOMAIN -->" + owner: "{{ ansible_user }}" + group: "{{ ansible_user }}" + create: true + mode: "644" + state: present + - name: Adding Caddyfile subdomain entry + when: "server_run and (mode == 'dev' or caddy.scheme == 'http')" + ansible.builtin.blockinfile: + path: "{{ ansible_user_home.stdout }}/.config/caddy/Caddyfile" + block: | + http://{{ gitea.subdomain }}.{{ web_fqdn }} { + reverse_proxy localhost:3000 + + handle_errors { + root /srv/{{ web_fqdn }} + rewrite /error/{err.status_code}.html + file_server + templates + encode gzip + } + } + prepend_newline: true + marker: "# <-- {mark} ANSIBLE MANAGED CLOUD DOMAIN -->" + owner: "{{ ansible_user }}" + group: "{{ ansible_user }}" + create: true + mode: "644" + state: present + # - name: Restarting webserver / reverse proxy container + # become: true + # become_user: "{{ current_user.stdout }}" + # when: server_run + # containers.podman.podman_container: + # name: "{{ compose.containers.webserver.name }}" + # state: started + # force_restart: true +- name: Spinning up pastebin container specified by Compose file + when: pbin_run + block: + - name: Creating database necessary for pastebin server container specified by Compose file + become: true + become_user: "{{ current_user.stdout }}" + when: dbms_run + containers.podman.podman_container_exec: + name: "{{ compose.containers.db.name }}" + argv: + - mysql + - "-u" + - "{{ mysql.users.admin.username }}" + - "-p{{ mysql.users.admin.password }}" + - "-e" + - "'CREATE DATABASE IF NOT EXISTS {{ mysql.users.admin.databases.opengist.name }};'" + detach: true + - name: Creating environment file for pastebin server container specified by Compose file + become: true + become_user: "{{ current_user.stdout }}" + when: pbin_run + ansible.builtin.template: + src: user/opengist.env.j2 + dest: "{{ ansible_user_home.stdout }}/.opengist.env" + owner: "{{ ansible_user }}" + group: "{{ ansible_user }}" + mode: "644" + force: true + backup: true + register: opengist_environ + - name: Creating gist configuration file + become: true + become_user: "{{ current_user.stdout }}" + when: pbin_run + ansible.builtin.template: + src: user/config/opengist/config.yml.j2 + dest: "{{ ansible_user_home.stdout }}/.config/opengist/config.yml" + owner: "{{ ansible_user }}" + group: "{{ ansible_user }}" + mode: "644" + force: true + backup: true + - name: Creating and deploying pastebin server container specified by Compose file + become: true + become_user: "{{ current_user.stdout }}" + when: pbin_run + ansible.builtin.command: + cmd: "podman-compose --env-file {{ opengist_environ.dest }} --env-file {{ mysql_environ.dest }} --env-file {{ environ.dest }} up -d {{ compose.containers.pastebin.name }}" + chdir: "{{ new_compose_path.dest }}{{ source_code.repos.compose.rpath | default('/independent') }}" + - name: Adding Caddyfile subdomain entry + when: "server_run and mode == 'prod'" + ansible.builtin.blockinfile: + path: "{{ ansible_user_home.stdout }}/.config/caddy/Caddyfile" + block: | + {{ gist.subdomain }}.{{ web_fqdn }} { + reverse_proxy localhost:6157 + + handle_errors { + root /srv/{{ web_fqdn }} + rewrite /error/{err.status_code}.html + file_server + templates + encode gzip + } + } + prepend_newline: true + marker: "# <-- {mark} ANSIBLE MANAGED CLOUD DOMAIN -->" + owner: "{{ ansible_user }}" + group: "{{ ansible_user }}" + create: true + mode: "644" + state: present + - name: Adding Caddyfile subdomain entry + when: "server_run and (mode == 'dev' or caddy.scheme == 'http')" + ansible.builtin.blockinfile: + path: "{{ ansible_user_home.stdout }}/.config/caddy/Caddyfile" + block: | + http://{{ gist.subdomain }}.{{ web_fqdn }} { + reverse_proxy localhost:6157 + + handle_errors { + root /srv/{{ web_fqdn }} + rewrite /error/{err.status_code}.html + file_server + templates + encode gzip + } + } + prepend_newline: true + marker: "# <-- {mark} ANSIBLE MANAGED CLOUD DOMAIN -->" + owner: "{{ ansible_user }}" + group: "{{ ansible_user }}" + create: true + mode: "644" + state: present + # - name: Restarting webserver / reverse proxy container + # become: true + # become_user: "{{ current_user.stdout }}" + # when: server_run + # containers.podman.podman_container: + # name: "{{ compose.containers.webserver.name }}" + # state: started + # force_restart: true +- name: Spinning up web or reverse proxy server container specified by Compose file + when: server_run + block: + - name: Creating directory for website subdomains + ansible.builtin.file: + path: "{{ ansible_user_home.stdout }}/srv/{{ item }}.{{ web_fqdn }}" + recurse: true + owner: "{{ ansible_user }}" + group: "{{ ansible_user }}" + state: directory + loop: + - certbot + - notes + - blog + - name: Creating directory for Caddy configuration + ansible.builtin.file: + path: "{{ ansible_user_home.stdout }}/.caddy" + recurse: true + owner: "{{ ansible_user }}" + group: "{{ ansible_user }}" + state: directory + - name: Creating and deploying webserver / reverse proxy server container specified by Compose file + become: true + become_user: "{{ current_user.stdout }}" + ansible.builtin.command: + cmd: "podman-compose --env-file {{ environ.dest }} up -d {{ compose.containers.webserver.name }}" + chdir: "{{ new_compose_path.dest }}{{ source_code.repos.compose.rpath | default('/independent') }}" + - name: Creating volume subdirectory for main website root's error pages + ansible.builtin.file: + path: "{{ ansible_user_home.stdout }}/srv/{{ web_fqdn }}/error" + recurse: true + owner: "{{ ansible_user }}" + group: "{{ ansible_user }}" + state: directory + - name: Creating image files for main website root's error path + become: true + become_user: "{{ current_user.stdout }}" + ansible.builtin.copy: + src: "user/srv/domain-root/error/{{ item }}" + dest: "{{ ansible_user_home.stdout }}/srv/{{ web_fqdn }}/error/" + owner: "{{ ansible_user }}" + group: "{{ ansible_user }}" + backup: true + mode: "644" + loop: + - 503.html + - "mythe-sisyphus-klein.png" + - "dark-matter.png" + - name: Creating or updating Caddyfile at directory + when: "mode == 'prod' and ssl_run" + ansible.builtin.blockinfile: + path: "{{ ansible_user_home.stdout }}/.config/caddy/Caddyfile" + block: | + http://{{ web_fqdn }} { + handle /.well-known/acme-challenge/* { + reverse_proxy localhost:80 + } + handle { + redir https://{host}{uri} 308 + } + } + :80 { + root /srv/certbot.{{ web_fqdn }} + browse + } + {{ web_fqdn }} { + respond 503 + # root /srv/{{ web_fqdn }} + file_server + + header /.well-known/openpgpkey/* { + Content-Type application/octet-stream + Access-Control-Allow-Origin * + } + + handle_errors { + rewrite /error/{err.status_code}.html + templates + } + } + prepend_newline: true + marker: "# <-- {mark} ANSIBLE MANAGED ROOT DOMAIN -->" + create: true + owner: "{{ ansible_user }}" + group: "{{ ansible_user }}" + mode: "644" + state: present + - name: Creating or updating Caddyfile at directory + when: "mode == 'prod' and not ssl_run" + ansible.builtin.blockinfile: + path: "{{ ansible_user_home.stdout }}/.config/caddy/Caddyfile" + block: | + {{ web_fqdn }} { + respond 503 + # root /srv/{{ web_fqdn }} + file_server + + header /.well-known/openpgpkey/* { + Content-Type application/octet-stream + Access-Control-Allow-Origin * + } + + handle_errors { + rewrite /error/{err.status_code}.html + templates + } + } + prepend_newline: true + marker: "# <-- {mark} ANSIBLE MANAGED ROOT DOMAIN -->" + create: true + owner: "{{ ansible_user }}" + group: "{{ ansible_user }}" + mode: "644" + state: present + - name: Creating or updating Caddyfile at directory + when: "mode == 'dev' or caddy.scheme == 'http'" + ansible.builtin.blockinfile: + path: "{{ ansible_user_home.stdout }}/.config/caddy/Caddyfile" + block: | + http://{{ web_fqdn }} { + respond 503 + # root /srv/{{ web_fqdn }} + file_server + + header /.well-known/openpgpkey/* { + Content-Type application/octet-stream + Access-Control-Allow-Origin * + } + + handle_errors { + rewrite /error/{err.status_code}.html + templates + } + } + prepend_newline: true + marker: "# <-- {mark} ANSIBLE MANAGED ROOT DOMAIN -->" + create: true + owner: "{{ ansible_user }}" + group: "{{ ansible_user }}" + mode: "644" + state: present + - name: Opening port 443 + become: true + ansible.builtin.iptables: + chain: INPUT + protocol: "{{ item }}" + destination_port: 443 + jump: ACCEPT + comment: Open up port 443 + loop: + - udp + - tcp + - name: Opening ports + become: true + ansible.builtin.iptables: + chain: INPUT + protocol: tcp + destination_port: "{{ item }}" + jump: ACCEPT + comment: "Open up port {{ (item | string) }}" + loop: + - 80 + # - name: Restarting webserver / reverse proxy container + # become: true + # become_user: "{{ current_user.stdout }}" + # containers.podman.podman_container: + # name: "{{ compose.containers.webserver.name }}" + # state: started + # force_restart: true +- name: Spinning up ACME challenge container specified by Compose file + when: ssl_run + ignore_errors: true + block: + - name: Creating environment file for SSL/TLS certificate acquisition container specified in Compose file + become: true + become_user: "{{ current_user.stdout }}" + ansible.builtin.template: + src: user/certbot.env.j2 + dest: "{{ ansible_user_home.stdout }}/.certbot.env" + owner: "{{ ansible_user }}" + group: "{{ ansible_user }}" + mode: "644" + force: true + backup: true + register: certbot_environ + - name: Creating and deploying SSL/TLS certificate acquisition container specified by Compose file + become: true + become_user: "{{ current_user.stdout }}" + ansible.builtin.command: + cmd: "podman-compose --env-file {{ certbot_environ.dest }} --env-file {{ environ.dest }} up -d {{ compose.containers.ssl.name }}" + chdir: "{{ new_compose_path.dest }}{{ source_code.repos.compose.rpath | default('/independent') }}" +- name: Spinning up tailnet container specified by Compose file + when: tail_run + block: + - name: Creating required tailnet container secret for tailnet container specified by Compose file + become: true + # become_user: "{{ current_user.stdout }}" + when: item.name == inventory_hostname + ansible.builtin.copy: + src: "{{ item.name }}-{{ headscale.users.admin.username }}@headscale/headscale{{ (idx | string) }}.key" + dest: "{{ ansible_user_home.stdout }}/.podsecrets/headscale.key" + owner: "{{ ansible_user }}" + group: "{{ ansible_user }}" + mode: "644" + force: true + backup: true + loop: "{{ headscale.clients }}" + loop_control: + index_var: idx + - name: Creating tailnet configuration file + become: true + become_user: "{{ current_user.stdout }}" + ansible.builtin.template: + src: user/config/tailscale/conf.json.j2 + dest: "{{ ansible_user_home.stdout }}/.config/tailscale/conf.json" + owner: "{{ ansible_user }}" + group: "{{ ansible_user }}" + mode: "644" + force: true + backup: true + - name: Creating and deploying tailnet container specified by Compose file + become: true + become_user: "{{ current_user.stdout }}" + ansible.builtin.command: + cmd: "podman-compose --env-file {{ environ.dest }} up -d {{ compose.containers.tail.name }}" + chdir: "{{ new_compose_path.dest }}{{ source_code.repos.compose.rpath | default('/independent') }}" +- name: Spinning up dashboard container specified by Compose file + when: tail_run and dash_run + block: + - name: Creating glance configuration file + become: true + become_user: "{{ current_user.stdout }}" + ansible.builtin.template: + src: user/config/glance/glance.yml.j2 + dest: "{{ ansible_user_home.stdout }}/.config/glance/glance.yml" + owner: "{{ ansible_user }}" + group: "{{ ansible_user }}" + mode: "644" + force: true + backup: true + - name: Creating and deploying dashboard container specified by Compose file + become: true + become_user: "{{ current_user.stdout }}" + ansible.builtin.command: + cmd: "podman-compose up -d {{ compose.containers.dash.name }}" + chdir: "{{ new_compose_path.dest }}{{ source_code.repos.compose.rpath | default('/independent') }}" +- name: Restarting webserver / reverse proxy container + become: true + become_user: "{{ current_user.stdout }}" + when: server_run + containers.podman.podman_container: + name: "{{ compose.containers.webserver.name }}" + state: started + force_restart: true +- name: Making running containers persist on user logout + become: true + ansible.builtin.shell: + cmd: loginctl enable-linger $(whoami) + diff --git a/roles/init-server/tasks/contingent/pkg/sukaato.yml b/roles/init-server/tasks/contingent/pkg/sukaato.yml new file mode 100644 index 0000000..ac12df7 --- /dev/null +++ b/roles/init-server/tasks/contingent/pkg/sukaato.yml @@ -0,0 +1,45 @@ +--- +- name: Acquiring home of current user + when: ansible_facts["system"] == "Linux" + ansible.builtin.shell: + cmd: "echo ~{{ ansible_user }}" + register: ansible_user_home +- name: Acquiring home of current user + when: ansible_facts["system"] == "Linux" + ansible.builtin.shell: + cmd: "echo {{ ansible_user }}" + register: current_user +- name: Moving git repository from initial path + block: + - name: Recursively copying directory and its contents to elsewhere + ansible.builtin.copy: + src: "{{ ansible_user_home.stdout }}/repos/.foreign/{{ source_code.repos.site.name }}" + remote_src: true + dest: "{{ ansible_user_home.stdout }}/repos/" + owner: "{{ ansible_user }}" + group: "{{ ansible_user }}" + register: new_compose_path + - name: Deleting directory at previous path + ansible.builtin.file: + path: "{{ ansible_user_home.stdout }}/repos/.foreign/{{ source_code.repos.site.name }}" + state: absent + - name: Creating directory for new bare repository + ansible.builtin.file: + path: "{{ ansible_user_home.stdout }}/src" + recurse: true + owner: "{{ ansible_user }}" + group: "{{ ansible_user }}" + state: directory + - name: Creating bare repository + ansible.builtin.command: + cmd: "git init --bare {{ source_code.repos.site.name }}.git" + chdir: "{{ ansible_user_home.stdout }}/src" + creates: "{{ ansible_user_home.stdout }}/src/{{ source_code.repos.site.name }}.git" +- name: Running website + when: source_code.repos.site.run + # become: true + # become_user: "{{ current_user.stdout }}" + block: + - name: Warning about lack of implementation + ansible.builtin.debug: + msg: Not yet implemented \ No newline at end of file diff --git a/roles/init-server/tasks/contingent/pkg/surge.yml b/roles/init-server/tasks/contingent/pkg/surge.yml index ea14874..ae4b3ce 100644 --- a/roles/init-server/tasks/contingent/pkg/surge.yml +++ b/roles/init-server/tasks/contingent/pkg/surge.yml @@ -6,52 +6,81 @@ register: ansible_user_home - name: Linking binaries to directories already in PATH environment variable become: true + ignore_errors: true ansible.builtin.file: src: "{{ ansible_user_home.stdout }}/downloads/archives/released/surge/{{ item }}" dest: "/usr/bin/{{ item }}" state: link loop: - surge -- name: Installing accompanying complementary Surge system service - ansible.builtin.command: - cmd: surge service install -- name: Acquiring API token for remote Surge service control - ansible.builtin.command: - cmd: surge token - register: surge_token -- name: Pausing to inquire about how to proceed - ansible.builtin.pause: - prompt: "Type \"fetch\" to get the Surge API token, or \"show\" to see it for manual copying instead" - echo: true - register: data_method -- name: Choosing to present Surge API token to Control Node - when: data_method.user_input == "show" +- name: Starting to spin up the Surge service + when: surge.service.enabled and not surge.containerized block: + - name: Installing accompanying complementary Surge system service + become: true + ansible.builtin.command: + cmd: surge service install + - name: Creating corresponding SystemD service unit + become: true + ansible.builtin.copy: + src: systemd/system/surge.service + dest: /etc/systemd/system/surge.service + owner: root + group: root + force: true + backup: true + - name: Acquiring API token for remote Surge service control + become: true + ansible.builtin.command: + cmd: surge token + register: surge_token + - name: Pausing to inquire about how to proceed + ansible.builtin.pause: + prompt: "Type \"fetch\" to get the Surge API token, or \"show\" to see it for manual copying instead" + echo: true + register: data_method - name: Presenting Surge API token to Control Node + when: data_method.user_input == "show" ansible.builtin.debug: msg: "Make sure to store the following API token for Surge:\n {{ surge_token.stdout }}" - name: Giving opportunity to manually copy Surge API token + when: data_method.user_input == "show" ansible.builtin.pause: -- name: Choosing to provide file on control node containing Surge's API token - when: data_method.user_input == "fetch" - block: - name: Creating temporary file on managed node that stores Surge API token become: true + when: data_method.user_input == "fetch" ansible.builtin.copy: content: "{{ surge_token.stdout }}" - dest: /tmp/surge.token + dest: /tmp/surge.secret owner: "{{ ansible_user }}" group: "{{ ansible_user }}" mode: "644" register: surge_token - name: Placing Surge API token into file on control node + when: data_method.user_input == "fetch" ansible.builtin.fetch: src: "{{ surge_token.dest }}" dest: "./.tmp/{{ inventory_hostname }}-surge/surge.secret" flat: true + - name: Placing Surge API token into file on control node + when: data_method.user_input == "fetch" + ansible.builtin.fetch: + src: "{{ surge_token.dest }}" + dest: "./roles/init-server/files/{{ inventory_hostname }}-surge/surge.secret" + flat: true - name: Informing control node of acquired files + when: data_method.user_input == "fetch" ansible.builtin.debug: - msg: "The Surge API token file have been duplicated to '/var/tmp/{{ inventory_hostname }}/surge.token' at the control node." + msg: "The Surge API token file have been duplicated to './.tmp/{{ inventory_hostname }}-surge/surge.secret' at the control node." - name: Giving control node user time to read the aforementiioned message + when: data_method.user_input == "fetch" ansible.builtin.pause: - seconds: 30 \ No newline at end of file + seconds: 30 + - name: Starting and enabling Surge SystemD service unit + become: true + ansible.builtin.systemd_service: + name: surge + scope: system + state: started + enabled: true + daemon_reload: true \ No newline at end of file diff --git a/roles/init-server/tasks/contingent/pkg/uv.yml b/roles/init-server/tasks/contingent/pkg/uv.yml index e434cf1..c93329d 100644 --- a/roles/init-server/tasks/contingent/pkg/uv.yml +++ b/roles/init-server/tasks/contingent/pkg/uv.yml @@ -15,8 +15,11 @@ ansible.builtin.shell: cmd: "{{ ansible_user_home.stdout }}/.local/bin/uv-install.sh" creates: "{{ ansible_user_home.stdout }}/.local/bin/uv" + async: 600 + poll: 5 - name: Linking binaries to directories already in PATH environment variable become: true + ignore_errors: true ansible.builtin.file: src: "{{ ansible_user_home.stdout }}/.local/bin/{{ item }}" dest: "/usr/bin/{{ item }}" diff --git a/roles/init-server/tasks/contingent/pkg/vim.yml b/roles/init-server/tasks/contingent/pkg/vim.yml index f994454..b243296 100644 --- a/roles/init-server/tasks/contingent/pkg/vim.yml +++ b/roles/init-server/tasks/contingent/pkg/vim.yml @@ -37,6 +37,7 @@ force: true mode: "644" follow_redirects: safe + timeout: 300 - name: Configuring ViM become: true become_user: "{{ current_user.stdout }}" diff --git a/roles/init-server/tasks/contingent/pkg/wireguard.yml b/roles/init-server/tasks/contingent/pkg/wireguard.yml new file mode 100644 index 0000000..8a3a124 --- /dev/null +++ b/roles/init-server/tasks/contingent/pkg/wireguard.yml @@ -0,0 +1,57 @@ +--- +- name: Enabling Wireguard kernel module + become: true + community.general.modprobe: + name: wireguard + persistent: present + state: present +- name: Enable IP forwarding + become: true + when: wireguard.ip_forward + block: + - name: Enabling IPv4 forwarding + ansible.posix.sysctl: + name: net.ipv4.ip_forward + value: "1" + sysctl_set: true + state: present + - name: Marking IPv4 forwarded traffic as valid + ansible.posix.sysctl: + name: net.ipv4.conf.all.src_valid_mark + value: "1" + sysctl_set: true + state: present + - name: Enabling IPv6 forwarding + ansible.posix.sysctl: + name: net.ipv6.conf.all.forwarding + value: "1" + sysctl_set: true + state: present + - name: Marking IPv6 traffic as valid + ansible.posix.sysctl: + name: net.ipv6.conf.all.src_valid_mark + value: "1" + sysctl_set: true + state: present +- name: Preparing to allow Wireguard logging + when: "wireguard.debug" + block: + - name: Creating subdirectory for system kernel debugging + become: true + ansible.builtin.file: + path: /sys/kernel/debug/dynamic_debug + recurse: true + owner: root + group: root + mode: "755" + state: directory + - name: Enabling Wireguard system logging + become: true + ansible.builtin.copy: + content: "module wireguard +p" + dest: /sys/kernel/debug/dynamic_debug/control + owner: root + group: root + mode: "644" + force: true + diff --git a/roles/init-server/tasks/core@install-pkgs.yml b/roles/init-server/tasks/core@install-pkgs.yml index aa5e0ec..2f3e986 100644 --- a/roles/init-server/tasks/core@install-pkgs.yml +++ b/roles/init-server/tasks/core@install-pkgs.yml @@ -87,13 +87,6 @@ # @TODO uncomment below before continuing with testing previous task # - name: Premature end of play # ansible.builtin.meta: end_play - - name: Updating package cache - ansible.builtin.apt: - update_cache: true - - name: Updating package cache - ansible.builtin.apt: - upgrade: dist - autoremove: true - name: Registering a package source when: item.sources != None ansible.builtin.deb822_repository: @@ -108,6 +101,10 @@ - name: Updating package cache ansible.builtin.apt: update_cache: true + - name: Upgrading + ansible.builtin.apt: + upgrade: dist + autoremove: true - name: Installing a local package in managed node when: item.uri != None ansible.builtin.apt: @@ -121,6 +118,8 @@ name: "{{ item.name }}" state: present notify: "{{ item.handler | default('default') }}" + async: 600 + poll: 5 loop: "{{ ((pkgs.mngr.core | default([]))) | rejectattr('uri', 'search', '\\.deb$') }}" tags: - get_mngr_pkgs @@ -137,7 +136,8 @@ owner: "{{ ansible_user }}" group: "{{ ansible_user }}" force: true - mode: "744" + mode: "755" + timeout: 300 notify: "{{ ((pkgs.script.core | default([])))[idx].handler | default('default') }}" loop: "{{ (pkgs.script.core | default([])) }}" loop_control: @@ -206,7 +206,6 @@ dest: "{{ ansible_user_home.stdout }}/repos/.foreign/{{ item.name }}" version: "{{ item.branch }}" clone: true - single_branch: true notify: "{{ item.handler | default('default') }}" loop: "{{ (pkgs.git_repos.core | default([])) }}" register: installation_repos @@ -225,9 +224,10 @@ dest: "/usr/bin/{{ item.name }}" owner: root group: root - mode: "744" + mode: "755" force: true backup: true notify: "{{ item.handler }}" + timeout: 300 loop: "{{ (pkgs.binaries.core | default([])) }}" diff --git a/roles/init-server/tasks/netrc.yml b/roles/init-server/tasks/netrc.yml new file mode 100644 index 0000000..7d111c9 --- /dev/null +++ b/roles/init-server/tasks/netrc.yml @@ -0,0 +1,20 @@ +--- +- 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: Copying NetRC file + become: true + become_user: "{{ current_user.stdout }}" + ansible.builtin.template: + src: user/netrc.j2 + dest: "{{ ansible_user_home.stdout }}/.netrc" + owner: "{{ ansible_user }}" + group: "{{ ansible_user }}" + mode: "600" \ No newline at end of file diff --git a/roles/init-server/tasks/spawn.yml b/roles/init-server/tasks/spawn.yml index 398e78c..4dc778d 100644 --- a/roles/init-server/tasks/spawn.yml +++ b/roles/init-server/tasks/spawn.yml @@ -2,6 +2,22 @@ --- # tasks file for roles/init-vps # @NOTE server deployment method is based on task tags compiled herein +- name: Informing user of requirement of two main domains + when: (certbot.domains | length) < 2 or (certbot.domains | length) > 2 + ansible.builtin.fail: + msg: Only two domains allowed and required +- name: Informing user of requirement at least one wildcard + when: (certbot.domains | select("regex", "^\\*\\.") | list | length) == 0 + ansible.builtin.fail: + msg: At least one of the FQDNs must have a wildcard +# - name: Setting the FQDN for development +# when: mode == "dev" +# ansible.builtin.set_fact: +# fqdn: "{{ (certbot.domains | map('regex_replace', '\\.([^\\.]*)$', '.test') | reject('regex', '^\\*\\.') | list)[0] }}" +- name: Setting the FQDN + # when: mode == "prod" + ansible.builtin.set_fact: + fqdn: "{{ (certbot.domains | reject('regex', '^\\*\\.') | list)[0] }}" - name: Finding SSH public keys for root delegate_facts: true delegate_to: localhost @@ -44,7 +60,7 @@ - name: Creating the VPS linode.cloud.instance: api_token: "{{ token | prompted_token.user_input }}" - label: "{{ instance }}" + label: "{{ fqdn }}" type: g6-standard-2 image: "{{ operating_system }}" disk_encryption: enabled @@ -86,7 +102,7 @@ ansible.builtin.wait_for_connection: delay: 20 timeout: 300 - loop: "{{ groups[instance] | default(hostvars[instance]) }}" + loop: "{{ groups[fqdn] | default(hostvars[fqdn]) }}" - name: Checking if that server has required operating system delegate_to: "{{ item }}" delegate_facts: true @@ -94,7 +110,7 @@ when: ansible_facts["system"] != "Linux" and item is ansible.utils['ip_pref'] ansible.builtin.fail: msg: Unsupported operating system found - loop: "{{ groups[instance] | default(hostvars[instance]) }}" + loop: "{{ groups[fqdn] | default(hostvars[fqdn]) }}" - name: Checking if that server has required Linux distro delegate_to: "{{ item }}" delegate_facts: true @@ -102,7 +118,7 @@ when: ansible_facts["system"] == "Linux" and ansible_facts["os_family"] != "Debian" and item is ansible.utils['ip_pref'] ansible.builtin.fail: msg: Unsupported Linux distro found - loop: "{{ groups[instance] | default(hostvars[instance]) }}" + loop: "{{ groups[fqdn] | default(hostvars[fqdn]) }}" - name: Providing authorized keys for server root account delegate_to: "{{ item[0] }}" delegate_facts: true @@ -112,6 +128,6 @@ user: "{{ ansible_user }}" key: "{{ lookup('file', item[1]) }}" state: present - loop: "{{ (groups[instance] | default(hostvars[instance])) | product(root_pubkey_paths) }}" + loop: "{{ (groups[fqdn] | default(hostvars[fqdn])) | product(root_pubkey_paths) }}" tags: - lan diff --git a/roles/init-server/tasks/userspace@install-pkgs.yml b/roles/init-server/tasks/userspace@install-pkgs.yml index 295899b..3326d26 100644 --- a/roles/init-server/tasks/userspace@install-pkgs.yml +++ b/roles/init-server/tasks/userspace@install-pkgs.yml @@ -88,13 +88,6 @@ # @TODO uncomment below before continuing with testing previous task # - name: Premature end of play # ansible.builtin.meta: end_play - - name: Updating package cache - ansible.builtin.apt: - update_cache: true - - name: Updating package cache - ansible.builtin.apt: - upgrade: dist - autoremove: true - name: Registering a package source when: item.sources != None ansible.builtin.deb822_repository: @@ -109,6 +102,10 @@ - name: Updating package cache ansible.builtin.apt: update_cache: true + - name: Upgrading + ansible.builtin.apt: + upgrade: dist + autoremove: true - name: Installing a local package in managed node when: item.uri != None ansible.builtin.apt: @@ -122,6 +119,8 @@ name: "{{ item.name }}" state: latest notify: "{{ item.handler | default('default') }}" # @TODO create corresponding roles/init-vps handlers + async: 600 + poll: 5 loop: "{{ (pkgs.mngr.userspace | default([])) | rejectattr('uri', 'search', '\\.deb$') }}" tags: - get_mngr_pkgs @@ -138,7 +137,8 @@ owner: "{{ ansible_user }}" group: "{{ ansible_user }}" force: true - mode: "744" + mode: "755" + timeout: 300 notify: "{{ (pkgs.script.userspace | default([]))[idx].handler | default('default') }}" loop: "{{ (pkgs.script.userspace | default([])) }}" loop_control: @@ -206,7 +206,6 @@ dest: "{{ ansible_user_home.stdout }}/repos/.foreign/{{ item.name }}" version: "{{ item.branch }}" clone: true - single_branch: true notify: "{{ item.handler | default('default') }}" loop: "{{ (pkgs.git_repos.userspace | default([])) }}" register: installation_repos @@ -225,8 +224,9 @@ dest: "/usr/bin/{{ item.name }}" owner: root group: root - mode: "744" + mode: "755" force: true backup: true notify: "{{ item.handler }}" + timeout: 300 loop: "{{ (pkgs.binaries.userspace | default([])) }}" \ No newline at end of file diff --git a/roles/init-server/templates/headscale/config.yaml.j2 b/roles/init-server/templates/headscale/config.yaml.j2 index 9e2b101..a2b63e7 100644 --- a/roles/init-server/templates/headscale/config.yaml.j2 +++ b/roles/init-server/templates/headscale/config.yaml.j2 @@ -10,13 +10,29 @@ # # https://myheadscale.example.com:443 # -server_url: {{ tail.scheme + '://' + tail.domain + tail.port }} +{% if mode == 'prod' %} +{% if headscale.port is defined and headscale.port != None %} +server_url: {{ headscale.scheme + '://' + web_fqdn + ':' + (headscale.port | string) }} +{% else %} +server_url: {{ headscale.scheme + '://' + web_fqdn + ':80' }} +{% endif %} +{% else %} +{% if headscale.port is defined and headscale.port != None %} +server_url: {{ 'http://' + web_fqdn + ':' + (headscale.port | string) }} +{% else %} +server_url: {{ 'http://' + web_fqdn + ':443' }} +{% endif %} +{% endif %} # Address to listen to / bind to on the server # # For production: # listen_addr: 0.0.0.0:8080 -listen_addr: {{ '0.0.0.0' + tail.port }} +{% if headscale.port is defined and headscale.port != None %} +listen_addr: {{ '0.0.0.0' + ':' + (headscale.port | string) }} +{% else %} +listen_addr: 0.0.0.0:80 +{% endif %} # Address to listen to /metrics and /debug, you may want # to keep this endpoint private to your internal network @@ -31,8 +47,8 @@ metrics_listen_addr: 127.0.0.1:9090 # # For production: # grpc_listen_addr: 0.0.0.0:50443 -{% if tail.grpc.expose %} -grpc_listen_addr: {{ '0.0.0.0' + tail.grpc.port }} +{% if headscale.grpc.expose %} +grpc_listen_addr: {{ '0.0.0.0' + ':' + (headscale.grpc.port | string) }} {% else %} grpc_listen_addr: 127.0.0.1:50443 {% endif %} @@ -41,7 +57,7 @@ grpc_listen_addr: 127.0.0.1:50443 # mode. This is not recommended as the traffic will # be unencrypted. Only enable if you know what you # are doing. -{% if tail.grpc.secure %} +{% if headscale.grpc.secure %} grpc_allow_insecure: false {% else %} grpc_allow_insecure: true @@ -253,6 +269,7 @@ database: # # in the 'ssl' field. Refers to https://www.postgresql.org/docs/current/libpq-ssl.html Table 34.1. # ssl: false +{% if mode == 'prod' or headscale.scheme == 'https' %} ### TLS configuration # ## Let's encrypt / ACME @@ -260,32 +277,42 @@ database: # headscale supports automatically requesting and setting up # TLS for a domain with Let's Encrypt. # + +{% if certbot is undefined or certbot == None %} # URL to ACME directory -acme_url: https://acme-v02.api.letsencrypt.org/directory +# acme_url: https://acme-v02.api.letsencrypt.org/directory # Email to register with ACME provider -acme_email: "" +# acme_email: "" # Domain name to request a TLS certificate for: -tls_letsencrypt_hostname: "" +# tls_letsencrypt_hostname: "" # Path to store certificates and metadata needed by # letsencrypt # For production: -tls_letsencrypt_cache_dir: /var/lib/headscale/cache +# tls_letsencrypt_cache_dir: /var/lib/headscale/cache # Type of ACME challenge to use, currently supported types: # HTTP-01 or TLS-ALPN-01 # See: https://headscale.net/stable/ref/tls/ -tls_letsencrypt_challenge_type: HTTP-01 +# tls_letsencrypt_challenge_type: HTTP-01 # When HTTP-01 challenge is chosen, letsencrypt must set up a # verification endpoint, and it will be listening on: # :http = port 80 -tls_letsencrypt_listen: ":http" - +# tls_letsencrypt_listen: ":http" +{% else %} +{% if not certbot.containerized %} ## Use already defined certificates: -tls_cert_path: "" -tls_key_path: "" +tls_cert_path: {{ '/etc/letsencrypt/live/' + web_fqdn + '/fullchain.pem' }} +tls_key_path: {{ '/etc/letsencrypt/live/' + web_fqdn + '/privkey.pem' }} +{% else %} +tls_cert_path: {{ ansible_user_home.stdout + '/.config/letsencrypt/live/' + web_fqdn + '/fullchain.pem' }} +tls_key_path: {{ ansible_user_home.stdout + '/.config/letsencrypt/live/' + web_fqdn + '/privkey.pem' }} +## Use already defined certificates: +{% endif %} +{% endif %} +{% endif %} log: # Valid log levels: panic, fatal, error, warn, info, debug, trace @@ -335,7 +362,7 @@ dns: # `base_domain` must be a FQDN, without the trailing dot. # The FQDN of the hosts will be # `hostname.base_domain` (e.g., _myhost.example.com_). - base_domain: {{ tail.magic_dns.domain }} + base_domain: {{ headscale.magic_dns.domain }} # Whether to use the local DNS settings of a node or override the local DNS # settings (default) and force the use of Headscale's DNS configuration. @@ -343,7 +370,7 @@ dns: # List of DNS servers to expose to clients. nameservers: - global: {{ tail.magic_dns.nameservers }} + global: {{ headscale.magic_dns.nameservers }} # NextDNS (see https://tailscale.com/docs/integrations/nextdns). # "abc123" is example NextDNS ID, replace with yours. diff --git a/roles/init-server/templates/user/all.env.j2 b/roles/init-server/templates/user/all.env.j2 new file mode 100644 index 0000000..2d4aa4d --- /dev/null +++ b/roles/init-server/templates/user/all.env.j2 @@ -0,0 +1,17 @@ +{% if compose.mode == "dev" %} +SERVER_FQDN_SCHEME=http +SERVER_FQDN={{ (certbot.domains | map("regex_replace", "\\.([^\\.]*)$", ".test") | reject("regex", "^\\*\\.") | list)[0] }} +{% elif compose.mode == "prod" %} +SERVER_FQDN_SCHEME=https +SERVER_FQDN={{ (certbot.domains | reject("regex", "^\\*\\.") | list)[0] }} +{% endif %} + +{% if nextcloud.subdomain is defined and nextcloud != None %} +NEXTCLOUD_SUBDOMAIN={{ nextcloud.subdomain }} +{% endif %} +{% if gitea is defined and gitea != None %} +GITEA_SUBDOMAIN={{ gitea.subdomain }} +{% endif %} +{% if gist is defined and gist != None %} +OG_SUBDOMAIN={{ gist.subdomain }} +{% endif %} \ No newline at end of file diff --git a/roles/init-server/templates/user/aria2/aria2.conf.j2 b/roles/init-server/templates/user/aria2/aria2.conf.j2 new file mode 100644 index 0000000..02dbc00 --- /dev/null +++ b/roles/init-server/templates/user/aria2/aria2.conf.j2 @@ -0,0 +1,196 @@ +# GENERAL +max-concurrent-downloads={{ aria.dl.max.concurrent | string }} +dir={{ ansible_user_home.stdout + "/downloads/aria2" }} +log={{ ansible_user_home.stdout + "/.aria2/aria2.log" }} +log-level={{ aria.log }} +console-log-level=notice +continue=true + +{% if aria.dl.resume %} +always-resume=true +{% else %} +always-resume=false +{% endif %} + +{% if aria.dl.overwriting %} +allow-overwrite=true +{% else %} +allow-overwrite=false +{% endif %} + +{% if aria.dl.autorenaming %} +auto-file-renaming=true +{% else %} +auto-file-renaming=false +{% endif %} + +file-allocation={{ aria.alloc }} +disk-cache={{ aria.dcache | string }} +enable-mmap=true +enable-color=true +human-readable=true +keep-unfinished-download-result=true +max-download-result=500 +max-resume-failure-tries=0 + +# RPC +{% if aria.rpc.enabled %} +enable-rpc=true + +{% if mode == "prod" or aria.rpc.scheme == "https" %} +rpc-secure=true + +{% if not certbot.containerized %} +rpc-certificate={{ "/etc/letsencrypt/live/" + web_fqdn + "/fullchain.pem" }} +rpc-private-key={{ "/etc/letsencrypt/live/" + web_fqdn + "/privkey.pem" }} +{% else %} +rpc-certificate={{ ansible_user_home.stdout + "/.config/letsencrypt/live/" + web_fqdn + "/fullchain.pem" }} +rpc-private-key={{ ansible_user_home.stdout + "/.config/letsencrypt/live/" + web_fqdn + "/privkey.pem" }} +{% endif %} + +{% endif %} + +{% if aria.rpc.listen_all %} +rpc-listen-all=true +{% else %} +rpc-listen-all=false +{% endif %} + +rpc-listen-port={{ aria.rpc.port | string }} + +{% if aria.rpc.credentials is undefined or aria.rpc.credentials == None %} +rpc-secret={{ aria.rpc.secret | default(lookup('password', './.tmp/' + inventory_hostname + '-aria/aria.secret', chars=['ascii_lowercase', 'digits'], length=32)) }} +{% else %} +rpc-user={{ aria.rpc.credentials.username }} +rpc-password={{ aria.rpc.credentials.password }} +{% endif %} + +{% else %} +enable-rpc=false +{% endif %} + + +# (HT/SF/F)TP +{% if aria.conn.proxy.enabled %} +all-proxy={{ aria.conn.proxy.uri }} +no-proxy={{ aria.conn.proxy.excluded | join(",") }} +{% endif %} + +max-connection-per-server={{ aria.conn.max.per_server | string }} +split={{ aria.conn.split | string }} +max-tries={{ aria.conn.max.attempts | string }} +retry-wait=15 +netrc-path={{ ansible_user_home.stdout + "/.netrc" }} +server-stat-if={{ ansible_user_home.stdout + "/.aria2/dl.log" }} +server-stat-of={{ ansible_user_home.stdout + "/.aria2/dl.log" }} +uri-selector={{ aria.dl.algorithm }} + + +# HTTP +{% if aria.http.gzip %} +http-accept-gzip=true +{% else %} +http-accept-gzip=false +{% endif %} + +{% if aria.http.cache %} +http-no-cache=true +{% else %} +http-no-cache=false +{% endif %} + +{% if aria.http.sustain %} +enable-http-keep-alive=true +{% else %} +enable-http-keep-alive=false +{% endif %} + +{% if aria.http.agent is defined and aria.http.agent != None %} +user-agent={{ aria.http.agent }} +{% endif %} + + +# (S)FTP +{% if aria.ftp.mode == "passive" %} +ftp-pasv=true +{% elif aria.ftp.mode == "active" %} +ftp-pasv=false +{% endif %} + +ftp-type={{ aria.ftp.data_type }} + + +# METALINKS/TORRENTS + + +# TORRENTS +bt-detach-seed-only=true + +{% if aria.trnt.local_discovery %} +bt-enable-lpd=true +{% else %} +bt-enable-lpd=false +{% endif %} + +{% if aria.trnt.encrypt %} +bt-force-encryption=true +{% else %} +bt-force-encryption=false +{% endif %} + +bt-max-peers={{ aria.trnt.peers.max }} + +{% if aria.trnt.trackers is defined and aria.trnt.trackers != None and (aria.trnt.trackers | length) > 0 %} +bt-tracker={{ aria.trnt.trackers | join(",") }} +{% endif %} + +{% if aria.trnt.dht.enabled %} +enable-dht=true +enable-dht6=true +dht-file-path={{ ansible_user_home.stdout + "/.aria2/dht.dat" }} +dht-file-path6={{ ansible_user_home.stdout + "/.aria2/dht6.dat" }} + +{% if aria.trnt.dht.entrypoint is defined and aria.trnt.dht.entrypoint != None %} +dht-entry-point={{ aria.trnt.dht.entrypoint }} +dht-entry-point6={{ aria.trnt.dht.entrypoint }} +{% endif %} + +dht-listen-port={{ aria.trnt.dht.port | string }} +{% endif %} + +{% if aria.trnt.peers.agent is defined and aria.trnt.peers.agent != None %} +peer-agent={{ aria.trnt.peers.agent }} +{% endif %} + +{% if aria.trnt.peers.prefix is defined and aria.trnt.peers.prefix != None %} +peer-id-prefix={{ aria.trnt.peers.prefix }} +{% endif %} + +{% if aria.trnt.peers.exchange %} +enable-peer-exchange=true +{% else %} +enable-peer-exchange=false +{% endif %} + +seed-ratio={{ aria.trnt.seeding.ratio | string }} +seed-time={{ aria.trnt.seeding.time | string }} + +max-overall-upload-limit={{ aria.ul.max.overall | string }} +max-upload-limit={{ aria.ul.max.per_entry | string }} + +# METALINK +{% if aria.meta.follow == "mem" %} +follow-metalink={{ aria.meta.follow }} +{% elif aria.meta.follow %} +follow-metalink=true +{% else %} +follow-metalink=false +{% endif %} + +metalink-language={{ aria.meta.lang }} + +{% if aria.meta.locs is defined and aria.meta.locs != None and (aria.meta.locs | length) > 0 %} +metalink-location={{ aria.meta.locs | join(",") }} +{% endif %} + +metalink-preferred-protocol={{ aria.meta.protocol_pref }} \ No newline at end of file diff --git a/roles/init-server/templates/user/certbot.env.j2 b/roles/init-server/templates/user/certbot.env.j2 new file mode 100644 index 0000000..a39bd61 --- /dev/null +++ b/roles/init-server/templates/user/certbot.env.j2 @@ -0,0 +1,14 @@ +CERTBOT_EMAIL="{{ certbot.email }}" +CERTBOT_AUTHENTICATOR={{ certbot.auth_method }} +SERVER_WEBROOT_PATH={{ ansible_user_home.stdout + "/srv/acme." + inventory_hostname }} +{% if compose.mode == "dev" %} +# @TODO find a better way to have processed the below in Ansible +CERTBOT_CHALLENGE_DOMAINS={{ certbot.domains | map("regex_replace", "\\.([^\\.]*)$", ".test") | list | join(",") }} +STAGING=1 +DEBUG=1 +VERBOSE=1 +RUN_ONCE=1 +{% elif compose.mode == "prod" %} +CERTBOT_CHALLENGE_DOMAINS={{ certbot.domains | join(",") }} +CRON={{ certbot.cron }} +{% endif %} diff --git a/roles/init-server/templates/user/config/caddy/Caddyfile.j2 b/roles/init-server/templates/user/config/caddy/Caddyfile.j2 new file mode 100644 index 0000000..8ab3ff9 --- /dev/null +++ b/roles/init-server/templates/user/config/caddy/Caddyfile.j2 @@ -0,0 +1,11 @@ +http://<< inventory_hostname >> { + handle /.well-known/acme-challenge/* { + reverse_proxy localhost:80 + } +} + +:80 { + root * /srv/<< inventory_hostname >> + file_server + encode gzip +} diff --git a/roles/init-server/templates/user/config/containers/storage.conf.j2 b/roles/init-server/templates/user/config/containers/storage.conf.j2 new file mode 100644 index 0000000..0cbf02f --- /dev/null +++ b/roles/init-server/templates/user/config/containers/storage.conf.j2 @@ -0,0 +1,15 @@ +[storage] +# Storage driver - use overlay with fuse-overlayfs for rootless +driver = "overlay" + +# Root directory for storage (default: $HOME/.local/share/containers/storage) +# Uncomment to customize: +graphroot = "{{ ansible_user_home.stdout }}/volumes" + +# Run directory for transient data +runroot = "/run/user/1000/containers" + +[storage.options] +[storage.options.overlay] +# Use fuse-overlayfs for rootless overlay support on older kernels +mount_program = "/usr/bin/fuse-overlayfs" \ No newline at end of file diff --git a/roles/init-server/templates/user/config/glance/glance.yml.j2 b/roles/init-server/templates/user/config/glance/glance.yml.j2 new file mode 100644 index 0000000..20b0330 --- /dev/null +++ b/roles/init-server/templates/user/config/glance/glance.yml.j2 @@ -0,0 +1,339 @@ +server: + port: {{ glance.port }} + {% if glance.proxied %} + proxied: true + {% endif %} + base-url: / +pages: + - name: home + head-widgets: + - type: search + search-engine: {{ glance.search.engine }} + bangs: + - title: Linux Kernel + shortcut: "@linuxkernel" + url: "https://www.kernel.org/doc/html/latest/search.html?q={QUERY}" + - title: Linux + shortcut: "@linux" + url: https://cse.google.com/cse?cx=017644269519104757279%3Agm62gtzaoky&q={QUERY}&sa=go + - title: Debian + shortcut: "@deb" + url: https://search.debian.org/cgi-bin/omega?DB=en&P={QUERY} + - title: C++ + shortcut: "@cpp" + url: https://learn.microsoft.com/en-us/search/?scope=C%2B%2B&view=msvc-170&terms={QUERY} + - title: Rust + shortcut: "@rust" + url: https://doc.rust-lang.org/book/?search={QUERY} + - title: Python + shortcut: "@python" + url: https://docs.python.org/3/search.html?check_keywords=yes&area=default&q={QUERY} + - title: Python Click + shortcut: "@pyclick" + url: https://click.palletsprojects.com/en/stable/search/?q={QUERY} + - title: Ansible + shortcut: "@ansible" + url: https://docs.ansible.com/projects/ansible/latest/search.html?q={QUERY}&check_keywords=yes&area=default + - title: Podman + shortcut: "@podman" + url: https://docs.podman.io/en/latest/search.html?q={QUERY} + - title: Podman Compose + shortcut: "@podcompose" + url: https://docs.podman.io/en/latest/search.html?q={QUERY} + - title: Elixir + shortcut: "@elixir" + url: https://hexdocs.pm/?packages=elixir%3A1.20.2%2Ceex%3A1.20.2%2Cex_unit%3A1.20.2%2Ciex%3A1.20.2%2Clogger%3A1.20.2%2Cmix%3A1.20.2&q={QUERY} + - title: Elixir Phoenix + shortcut: "@exphoenix" + url: https://hexdocs.pm/?q={QUERY}&packages=plug%3Alatest%2Cphoenix%3Alatest%2Cphoenix_html%3Alatest%2Cphoenix_live_view%3Alatest%2Cphoenix_pubsub%3Alatest%2Cphoenix_template%3Alatest + - title: Javascript + shortcut: "@js" + shortcut: https://javascript.info/search?query={QUERY} + - title: MDN + shortcut: "@mdn" + url: https://developer.mozilla.org/en-US/search?q={QUERY} + - title: PHP + shortcut: "@php" + url: https://www.php.net/search.php#gsc.tab=0&gsc.q={QUERY}&gsc.sort= + - title: PostgreSQL + shortcut: "@pgsql" + url: https://www.postgresql.org/search/?q={QUERY} + - title: MySQL + shortcut: "@mysql" + url: https://dev.mysql.com/doc/search/?q={QUERY} + - title: Julia + shortcut: "@julia" + url: https://docs.julialang.org/en/v1/?q={QUERY} + - title: Gitea + shortcut: "@gitea" + url: https://docs.gitea.com/search/?q={QUERY} + - title: Git + shortcut: "@git" + url: https://git-scm.com/search/results?search={QUERY}&language=en + - title: Elixir Phoenix + shortcut: "@exphoenix" + url: https://hexdocs.pm/?q={QUERY}&packages=plug%3Alatest%2Cphoenix%3Alatest%2Cphoenix_html%3Alatest%2Cphoenix_live_view%3Alatest%2Cphoenix_pubsub%3Alatest%2Cphoenix_template%3Alatest + # @TODO add more documentation searches + - type: group + widgets: + - type: clock + hour-format: 24h + timezones: + - timezone: {{ glance.timezone.id}} + label: {{ glance.timezone.name }} + - type: weather + units: metric + hour-format: 24h + location: {{ glance.weather_loc }} + columns: + - size: small + widgets: + - type: calendar + first-day-of-week: sunday + - type: bookmarks + groups: + - title: strat + links: + - title: The New Oil + url: https://thenewoil.org/en/ + - title: Resilient by Design + url: https://theanarchistlibrary.org/library/the-techno-anarchist-resilient-by-design + - title: complang dox + links: + - name: Raspberry Pi + url: https://www.raspberrypi.com/documentation/ + - name: Arduino + url: https://docs.arduino.cc/ + - name: NASM x86 Assembly + url: https://www.tutorialspoint.com/assembly_programming/index.htm + - name: WASM + url: https://webassembly.org/docs/faq/ + - name: Linux Kernel + url: https://www.kernel.org/doc/html/latest/index.html + - name: Linux + url: https://tldp.org/guides.html + - name: Debian + url: https://www.debian.org/doc/ + - name: Zig + url: https://ziglang.org/documentation/ + - name: Rust + url: https://doc.rust-lang.org/ + - name: Cargo + url: https://doc.rust-lang.org/cargo/ + - name: C++ + url: https://learn.microsoft.com/en-us/cpp/ + - name: vcpkg + url: https://learn.microsoft.com/en-us/vcpkg/ + - name: C# + url: https://learn.microsoft.com/en-us/dotnet/csharp/ + - name: nuget + url: https://learn.microsoft.com/en-us/nuget/ + - name: Python + url: https://docs.python.org/ + - name: Python uv + url: https://docs.astral.sh/uv/ + - name: Ansible + url: https://docs.ansible.com/projects/ansible/latest/ + - name: Podman + url: https://docs.podman.io/en/latest/ + - name: Podman Compose + url: https://docs.podman.io/en/latest/markdown/podman-compose.1.html + - name: Erlang + url: https://www.erlang.org/docs.html + - name: Elixir + url: https://elixir-lang.org/docs.html + - name: Hex + url: https://hex.pm/docs/usage + - name: Lua + url: https://www.lua.org/docs.html + - name: LuaRocks + url: https://luarocks.org/docs + - name: GDScript + url: https://docs.godotengine.org/en/latest/tutorials/scripting/gdscript/index.html + - name: Julia + url: https://docs.julialang.org/ + - name: NodeJS + url: https://nodejs.org/docs/latest/api/ + - name: NPMJS + url: https://docs.npmjs.com/ + - name: Go + url: https://go.dev/doc/ + - name: CSS + url: https://www.w3.org/Style/CSS/Overview.en.html + - name: HTML + url: https://html.spec.whatwg.org/multipage/ + - name: Javascript + url: https://javascript.info/ + - name: Javascript DOM + url: https://dom.spec.whatwg.org/ + - name: JSON + url: https://www.json.org/json-en.html + - name: Client-Side Web Languages + url: https://developer.mozilla.org/en-US/ + - name: PHP + url: https://www.php.net/docs.php + - name: PHP Composer + url: https://getcomposer.org/doc/ + - name: SQL + url: https://www.postgresql.org/docs/current/sql.html + - name: SASS + url: https://sass-lang.com/documentation/ + - name: YAML + url: https://www.yaml.info/ + - name: TOML + url: https://toml.io/en/ + - name: ActivityPub + url: https://activitypub.rocks/ + - name: SuperCollider + url: https://doc.sccode.org/ + - name: CSound + url: https://csound.com/docs/manual/index.html + - name: FAUST + url: https://faustdoc.grame.fr/ + - name: regexp + url: https://regexbox.com/cheatsheet + - title: warez dox + links: + - name: glance + url: https://github.com/glanceapp/glance/tree/main/docs + - name: Nextcloud + url: https://docs.nextcloud.com/ + - name: Wireguard + url: https://www.wireguard.com/#conceptual-overview + - name: Headscale + url: https://docs.headscale.org/ + - name: Tailscale + url: https://tailscale.com/docs + - name: Gitea + url: https://docs.gitea.com/ + - name: OpenGist + url: https://opengist.io/docs/ + - name: Caddy + url: https://caddyserver.com/docs/ + - name: MySQL + url: https://dev.mysql.com/doc/ + - name: Certbot + url: https://eff-certbot.readthedocs.io/en/stable/ + - name: git + url: https://git-scm.dev/doc + # - title: api + # - title: src + # - title: warez + - size: full + widgets: + - type: split-column + widgets: + - type: rss + title: technoscience + style: detailed-list + collapse-after: 5 + feeds: + - url: https://feeds.arstechnica.com/arstechnica/features + title: arstechnica + - url: https://rss.slashdot.org/Slashdot/slashdotMain + title: slashdot + - url: https://torrentfreak.com/feed/ + title: torrentfreak + - url: https://blog.p2pfoundation.net/feed/ + title: p2p foundation + - url: https://www.wired.com/feed/category/backchannel/latest/rss + title: wired + - url: https://www.quantamagazine.org/feed/ + title: quanta + - url: https://www.sciencedaily.com/rss/matter_energy/telecommunications.xml + title: scidaily - telecomms + - url: https://www.sciencedaily.com/rss/computers_math/quantum_computers.xml + title: scidaily - quancomp + - url: https://www.sciencedaily.com/rss/matter_energy/engineering_and_construction.xml + title: scidaily - engi + - url: https://www.sciencedaily.com/rss/matter_energy/energy_and_resources.xml + title: scidaily - energy & fuel + - url: https://www.sciencedaily.com/rss/earth_climate/energy.xml + title: scidaily - climate change + - url: https://www.sciencedaily.com/rss/earth_climate/global_warming.xml + title: scidaily - global warming + - url: https://www.sciencedaily.com/rss/earth_climate/sustainability.xml + title: scidaily - sustainability + - url: https://www.sciencedaily.com/rss/computers_math/computer_programming.xml + title: scidaily - compprog + - url: https://www.sciencedaily.com/rss/computers_math/information_technology.xml + title: scidaily - infotech + - url: https://phys.org/rss-feed/biology-news/ecology/ + title: phys - ecology + - type: rss + title: politics + style: detailed-list + collapse-after: 5 + feeds: + - url: https://www.democracynow.org/democracynow.rss + title: democracy now + - url: https://www.nakedcapitalism.com/feed + title: naked capitalism + - url: https://www.thenews.coop/feed/ + title: co-operative news + - url: http://feeds.propublica.org/propublica/main + title: propublica + - url: https://unicornriot.ninja/feed/rss/ + title: unicorn riot + - url: https://crimethinc.com/feed + title: crimethinc + - url: https://anarchistnews.org/rss.xml + title: anarchist news + - type: rss + title: misc + style: detailed-list + collapse-after: 5 + feeds: + - url: https://www.radicalphilosophy.com/feed + title: radical philosophy + - url: http://spectrejournal.com/feed/rss + title: spectre + - url: https://nautil.us/feed + title: nautilus + - url: https://theconversation.com/us/home-page/articles.atom + title: the conversation + - url: https://thebaffler.com/latest/feed + title: the baffler + - type: videos + style: horizontal-cards + channels: + - UCjEDZ_R_ypSc-MUBRkiW1lw + - UCIZ5ZOeiXYbmKTl_85ghNPw + - UCdcemy56JtVTrsFIOoqvV8g + - UCSkzHxIcfoEr69MWBdo0ppg + - UCW6TXMZ5Pq6yL6_k5NZ2e0Q + - UC4a-Gbdw7vOaccHmFo40b9g + - UCwbyKKmjVdCpWzZZY-WnajA + - UCMMBpWfWUd3xlcOxrot_neA + - UCJXa3_WNNmIpewOtCHf3B0g + - UCmfF7JZv26UUKyRedViGIlw + - UCEmQRq5bxIUNGvAWj41AoaA + - UCHkYOD-3fZbuGhwsADBd9ZQ + - UCHa8J-xnRYOg5VuudfWpBgg + - UCJZv4d5rbIKd4QHMPkcABCw + - UCZUyPT9DkJWmS_DzdOi7RIA + - UChbS_z6KHQiIu9et38O37eQ + - UCxX9wt5FWQUAAz4UrysqK9A + - UCX6b17PVsYBQ0ip5gyeme-Q + - UCk0fGHsCEzGig-rSzkfCjMw + - UCYO_jab_esuFRV4b17AJtAw + - UChKIQpndVpX1ung-7IkGhzA + - UCaM7SQvF5q9sz4NgL16PNRA + - UC7pdnrWVj8eDfCI0bRe_0kQ + - UCtuXekfqj-paqsxtqVNCC2A + - UCgkjg1UbcQZHW40IO1BEt5A + - UCGKEMK3s-ZPbjVOIuAV8clQ + - UCbiGcwDWZjz05njNPrJU7jA + - UC6biysICWOJ-C3P4Tyeggzg + - UCbi3ei431gvBpgZ3R-_Wk5Q + - UCA5yXa0rDsGaJFOuj6pxw1w + - UCDG73pGqESS1XcEVY_0xwWw + - UCR2uRTQ53V_egXKFflMMaaw + - UCzGUT9PjV3SMBwjWXUYh4HA + - name: services + columns: + - size: full + widgets: + - type: docker-containers + title: status + hide-by-default: false diff --git a/roles/init-server/templates/user/config/opengist/config.yml.j2 b/roles/init-server/templates/user/config/opengist/config.yml.j2 new file mode 100644 index 0000000..1353f9a --- /dev/null +++ b/roles/init-server/templates/user/config/opengist/config.yml.j2 @@ -0,0 +1,9 @@ +db-uri: {{ gist.db.type + "://" + mysql.users.admin.username + ":" + mysql.users.admin.password + "@localhost:3306/" + mysql.users.admin.databases.opengist.name }} +{% if mode == "dev" %} +log-level: debug +{% else %} +log-level: info +{% endif %} +custom.static-links: + - name: Playbooks + path: {{ "https://" + gitea.subdomain + "." + web_fqdn + "/admin/skato-ansible" }} \ No newline at end of file diff --git a/roles/init-server/templates/user/config/tailscale/conf.json.j2 b/roles/init-server/templates/user/config/tailscale/conf.json.j2 new file mode 100644 index 0000000..4839ede --- /dev/null +++ b/roles/init-server/templates/user/config/tailscale/conf.json.j2 @@ -0,0 +1,39 @@ +{ + "TCP": { +<% if mode == "prod" %> + "443": { + "HTTPS": true + } +<% elif mode == "dev" or tailscale.scheme == "http" %> + "80": { + "HTTPS": false + } +<% endif %> + }, + "Web": { +<% if mode == "prod" %> + "${TS_CERT_DOMAIN}:443": { + "Handlers": { + "/": { + "Proxy": "http://localhost:8080" + } + } + } +<% elif mode == "dev" or tailscale.scheme == "http" %> + "${TS_CERT_DOMAIN}:80": { + "Handlers": { + "/": { + "Proxy": "http://localhost:8080" + } + } + } +<% endif %> + }, + "AllowFunnel": { +<% if mode == "prod" %> + "${TS_CERT_DOMAIN}:443": false +<% elif mode == "dev" or tailscale.scheme == "http" %> + "${TS_CERT_DOMAIN}:80": false +<% endif %> + } +} \ No newline at end of file diff --git a/roles/init-server/templates/user/email.env.j2 b/roles/init-server/templates/user/email.env.j2 new file mode 100644 index 0000000..957849f --- /dev/null +++ b/roles/init-server/templates/user/email.env.j2 @@ -0,0 +1,10 @@ +{% if email.smtp is defined or email.smtp != None %} +EMAIL_SEND_PROTOCOL=smtp +EMAIL_SMTP_HOST={{ email.smtp.host }} +EMAIL_SMTP_PORT={{ email.smtp.port }} +EMAIL_SMTP_SECURE={{ email.smtp.conn_mode }} +EMAIL_SMTP_USERNAME={{ email.smtp.username }} +EMAIL_SMTP_AUTHTYPE={{ email.smtp.auth_meth.upper() }} +EMAIL_SMTP_USER_ALIAS={{ (email.smtp.alias | split("@"))[0] }} +EMAIL_SMTP_EMAIL_ALIAS={{ (email.smtp.alias | split("@"))[1] }} +{% endif %} \ No newline at end of file diff --git a/roles/init-server/templates/user/flexget/config.yml.j2 b/roles/init-server/templates/user/flexget/config.yml.j2 index 9b931b9..91003e1 100644 --- a/roles/init-server/templates/user/flexget/config.yml.j2 +++ b/roles/init-server/templates/user/flexget/config.yml.j2 @@ -38,7 +38,7 @@ tasks: populate_folders: {% if download_mode == 'direct' %} proxy: - https: 'socks5://<< sox.hostname >>:<< sox.port >>' + https: 'socks5://<< tor.proxy.hostname >>:<< tor.proxy.port >>' {% endif %} if: - "'batch' in title.lower()": reject @@ -63,16 +63,19 @@ tasks: template: limited_series {% if flexget.download_mode == 'aria2' %} aria2: - server: << aria.hostname >> - port: << aria.port >> - {% if aria.secret != None or aria.secret is defined %} - secret: << aria.secret >> + server: << aria.rpc.hostname >> + port: << aria.rpc.port >> + {% if aria.rpc.secret != None and aria.rpc.secret is defined %} + secret: << aria.rpc.secret >> + {% elif aria.rpc.credentials != None and aria.rpc.credentials is defined %} + username: << aria.rpc.credentials.username >> + password: << aria.rpc.credentials.password >> {% endif %} - {% if aria.credentials != None or aria.credentials is defined %} - username: << aria.credentials.username >> - password: << aria.credentials.password >> + {% if mode == 'prod' %} + scheme: << aria.rpc.scheme >> + {% else %} + scheme: http {% endif %} - scheme: << aria.scheme >> rpc_mode: json rpc_path: jsonrpc path: '~/downloads/media/vids/{{ series_name }}' @@ -85,21 +88,25 @@ tasks: fap_queue: {% if download_mode == 'direct' %} proxy: - https: 'socks5://<< sox.hostname >>:<< sox.port >>' + https: 'socks5://<< tor.proxy.hostname >>:<< tor.proxy.port >>' {% endif %} template: porn_vids {% if flexget.download_mode == 'aria2' %} aria2: - server: << aria.hostname >> - port: << aria.port >> - {% if aria.secret != None or aria.secret is defined %} - secret: << aria.secret >> + server: << aria.rpc.hostname >> + port: << aria.rpc.port >> + {% if aria.rpc.secret != None and aria.rpc.secret is defined %} + secret: << aria.rpc.secret >> {% endif %} - {% if aria.credentials != None or aria.credentials is defined %} - username: << aria.credentials.username >> - password: << aria.credentials.password >> + {% if aria.rpc.credentials != None and aria.rpc.credentials is defined %} + username: << aria.rpc.credentials.username >> + password: << aria.rpc.credentials.password >> + {% endif %} + {% if mode == 'prod' %} + scheme: << aria.rpc.scheme >> + {% else %} + scheme: http {% endif %} - scheme: << aria.scheme >> rpc_mode: json rpc_path: jsonrpc path: ~/downloads/.xxx/media/vids @@ -112,21 +119,25 @@ tasks: film_queue: {% if download_mode == 'direct' %} proxy: - https: 'socks5://<< sox.hostname >>:<< sox.port >>' + https: 'socks5://<< tor.proxy.hostname >>:<< tor.proxy.port >>' {% endif %} template: feature_films {% if flexget.download_mode == 'aria2' %} aria2: - server: << aria.hostname >> - port: << aria.port >> - {% if aria.secret != None or aria.secret is defined %} - secret: << aria.secret >> + server: << aria.rpc.hostname >> + port: << aria.rpc.port >> + {% if aria.rpc.secret != None or aria.rpc.secret is defined %} + secret: << aria.rpc.secret >> {% endif %} - {% if aria.credentials != None or aria.credentials is defined %} - username: << aria.credentials.username >> - password: << aria.credentials.password >> + {% if aria.rpc.credentials != None or aria.rpc.credentials is defined %} + username: << aria.rpc.credentials.username >> + password: << aria.rpc.credentials.password >> + {% endif %} + {% if mode == 'prod' %} + scheme: << aria.rpc.scheme >> + {% else %} + scheme: http {% endif %} - scheme: << aria.scheme >> rpc_mode: json rpc_path: jsonrpc path: ~/downloads/media/vids diff --git a/roles/init-server/templates/user/gitea.env.j2 b/roles/init-server/templates/user/gitea.env.j2 new file mode 100644 index 0000000..0e740f1 --- /dev/null +++ b/roles/init-server/templates/user/gitea.env.j2 @@ -0,0 +1,17 @@ +GITEA_MODE={{ mode | default("dev") }} +GITEA_NAME={{ (web_fqdn | split("."))[0].upper() + " Nous" }} +GITEA_SSH_PORT={{ gitea.ssh.port }} +GITEA_LANDING={{ gitea.site.landing }} +GITEA_TRUSTED_PROXIES={{ gitea.trusted.proxies | join(",") }} + +{% if gitea.site.registration.enabled %} +GITEA_PROHIBIT_REGISTRATION=false +{% else %} +GITEA_PROHIBIT_REGISTRATION=true +{% endif %} + +GITEA_DB_TYPE={{ gitea.db.type }} + +{% if gitea.db.type == "mysql" %} +GITEA_DB_NAME={{ gitea.db.name }} +{% endif %} \ No newline at end of file diff --git a/roles/init-server/templates/user/journal/blog/_index.md.j2 b/roles/init-server/templates/user/journal/blog/_index.md.j2 new file mode 100644 index 0000000..bb0badf --- /dev/null +++ b/roles/init-server/templates/user/journal/blog/_index.md.j2 @@ -0,0 +1,12 @@ ++++ +title = '{{ web_fqdn }}' +draft = false ++++ + +![sisyphus-with-boulder](./mythe-sisyphus-klein.png) + +## Under Construction + +### Err. 503: Service Unavailable + +Working on building or migrating the content, layout or theme for this blog. diff --git a/roles/init-server/templates/user/journal/notes/index.md.j2 b/roles/init-server/templates/user/journal/notes/index.md.j2 new file mode 100644 index 0000000..474efb7 --- /dev/null +++ b/roles/init-server/templates/user/journal/notes/index.md.j2 @@ -0,0 +1,11 @@ +--- +title: {{ web_fqdn }} +--- + +![sisyphus-with-boulder](./mythe-sisyphus-klein.png) + +## Under Construction + +### Err. 503: Service Unavailable + +Working on building or migrating Obsidian vault entries for this server. diff --git a/roles/init-server/templates/user/journal/notes/mythe-sisyphus-klein.png b/roles/init-server/templates/user/journal/notes/mythe-sisyphus-klein.png new file mode 100644 index 0000000..16d3b7b Binary files /dev/null and b/roles/init-server/templates/user/journal/notes/mythe-sisyphus-klein.png differ diff --git a/roles/init-server/templates/user/mysql.env.j2 b/roles/init-server/templates/user/mysql.env.j2 new file mode 100644 index 0000000..43c2970 --- /dev/null +++ b/roles/init-server/templates/user/mysql.env.j2 @@ -0,0 +1,3 @@ +MYSQL_DB_HOST=localhost +MYSQL_DB_USER={{ mysql.users.admin.username }} +MYSQL_DB_NAME={{ mysql.users.admin.databases.init.name }} \ No newline at end of file diff --git a/roles/init-server/templates/user/netrc.j2 b/roles/init-server/templates/user/netrc.j2 new file mode 100644 index 0000000..aa2b8b6 --- /dev/null +++ b/roles/init-server/templates/user/netrc.j2 @@ -0,0 +1,3 @@ +machine {{ source_code.host }} +login {{ source_code.user }} +password {{ source_code.http_password }} \ No newline at end of file diff --git a/roles/init-server/templates/user/nextcloud.env.j2 b/roles/init-server/templates/user/nextcloud.env.j2 new file mode 100644 index 0000000..a6e6327 --- /dev/null +++ b/roles/init-server/templates/user/nextcloud.env.j2 @@ -0,0 +1,19 @@ +{% if nextcloud.db.type == "mysql" or nextcloud.db.type == "mariadb" %} +NEXTCLOUD_DB_NAME={{ nextcloud.db.name | default("nextcloud") }} +{% elif nextcloud.db.type == "sqlite" %} +SQLITE_DATABASE={{ nextcloud.db.name + ".db" }} +{% endif %} + +{% if not nextcloud.rewrite_ip %} +NEXTCLOUD_APACHE_DISABLE_REWRITE_IP=1 +{% endif %} + +NEXTCLOUD_TRUSTED_PROXIES={{ nextcloud.trusted.proxies | join(" ") }} +NEXTCLOUD_TRUSTED_FQDNS={{ "cloud." + web_fqdn }} +{% if compose.mode == "prod" %} +NEXTCLOUD_URL_REWRITE={{ "https://cloud." + web_fqdn }} +NEXTCLOUD_PROTOCOL_REWRITE=https +{% elif compose.mode == "dev" %} +NEXTCLOUD_URL_REWRITE={{ "http://cloud." + web_fqdn }} +NEXTCLOUD_PROTOCOL_REWRITE=http +{% endif %} \ No newline at end of file diff --git a/roles/init-server/templates/user/opengist.env.j2 b/roles/init-server/templates/user/opengist.env.j2 new file mode 100644 index 0000000..3c2a7dc --- /dev/null +++ b/roles/init-server/templates/user/opengist.env.j2 @@ -0,0 +1,18 @@ +OG_DB_TYPE={{ gist.db.type }} + +{% if gist.db.type == "mysql" %} +OG_DB_NAME={{ gist.db.name }} +{% endif %} + +OG_SEARCH_DEFAULT={{ gist.search.priority | join(",") }} + +{% if ssh is defined and ssh != None %} +OG_SSH_PORT={{ gist.ssh.port }} +OG_SSH_GIT_ENABLED=true +{% else %} +OG_SSH_GIT_ENABLED=false +{% endif %} + +OG_NAME={{ (web_fqdn | split("."))[0].upper() + " Grimoire" }} +OG_LOGO=logo.svg +OG_FAVICON=logo.ico \ No newline at end of file diff --git a/roles/init-server/templates/user/redis.env.j2 b/roles/init-server/templates/user/redis.env.j2 new file mode 100644 index 0000000..4770c04 --- /dev/null +++ b/roles/init-server/templates/user/redis.env.j2 @@ -0,0 +1 @@ +REDIS_PARAMS={{ "--requirepass " + redis.password + " --appendonly yes" }} \ No newline at end of file diff --git a/roles/init-server/templates/user/vimrc.j2 b/roles/init-server/templates/user/vimrc.j2 index b2dbac1..813ddbd 100644 --- a/roles/init-server/templates/user/vimrc.j2 +++ b/roles/init-server/templates/user/vimrc.j2 @@ -56,7 +56,7 @@ set wildmenu " Make wildmenu behave like similar to Bash completion. set wildmode=list:longest -{% if vimrc.typed_paths.ignore is defined or vimrc.typed_paths.ignore != None %} +{% if vimrc.typed_paths.ignore is defined and vimrc.typed_paths.ignore != None %} " There are certain files that we would never want to edit with Vim. " Wildmenu will ignore files with these extensions. diff --git a/roles/init-server/templates/usr/local/bin/dsnet-forward.sh.j2 b/roles/init-server/templates/usr/local/bin/dsnet-forward.sh.j2 new file mode 100755 index 0000000..909d116 --- /dev/null +++ b/roles/init-server/templates/usr/local/bin/dsnet-forward.sh.j2 @@ -0,0 +1,22 @@ +#!/bin/bash +set -euo pipefail + +if [[ "$1" == "start" ]]; then + /usr/sbin/iptables -A FORWARD -i dsnet -p tcp --sport 80 -j ACCEPT # HTTP + /usr/sbin/iptables -A FORWARD -i dsnet -p tcp --sport 443 -j ACCEPT # HTTPS (HTTP + SSL/TLS) + /usr/sbin/iptables -A FORWARD -i dsnet -p udp --sport 443 -j ACCEPT # HTTPS (HTTP + SSL/TLS) + /usr/sbin/iptables -A FORWARD -i dsnet -p tcp --sport 465 -j ACCEPT # SMTP (send) + /usr/sbin/iptables -A FORWARD -i dsnet -p tcp --sport 587 -j ACCEPT # SMTP (send) + /usr/sbin/iptables -A FORWARD -i dsnet -p tcp --sport 995 -j ACCEPT # POP3 (receive) + /usr/sbin/iptables -A FORWARD -i dsnet -p tcp --sport 993 -j ACCEPT # IMAP (receive) + /usr/sbin/iptables -t nat -A POSTROUTING -o dsnet -j MASQUERADE +elif [[ "$1" == "stop" ]]; then + /usr/sbin/iptables -D FORWARD -i dsnet -p tcp --sport 80 -j ACCEPT # HTTP + /usr/sbin/iptables -D FORWARD -i dsnet -p tcp --sport 443 -j ACCEPT # HTTPS (HTTP + SSL/TLS) + /usr/sbin/iptables -D FORWARD -i dsnet -p udp --sport 443 -j ACCEPT # HTTPS (HTTP + SSL/TLS) + /usr/sbin/iptables -D FORWARD -i dsnet -p tcp --sport 465 -j ACCEPT # SMTP (send) + /usr/sbin/iptables -D FORWARD -i dsnet -p tcp --sport 587 -j ACCEPT # SMTP (send) + /usr/sbin/iptables -D FORWARD -i dsnet -p tcp --sport 995 -j ACCEPT # POP3 (receive) + /usr/sbin/iptables -D FORWARD -i dsnet -p tcp --sport 993 -j ACCEPT # IMAP (receive) + /usr/sbin/iptables -t nat -D POSTROUTING -o dsnet -j MASQUERADE +fi \ No newline at end of file diff --git a/skato-ansible.sh b/skato-ansible.sh index 927f9fb..72a5e01 100755 --- a/skato-ansible.sh +++ b/skato-ansible.sh @@ -3,21 +3,19 @@ set -euo pipefail # @TODO long-term, turn this simple bash script into more complex Python Click project SKANSIBLE_SCRIPT_PATH=$(dirname "$0") -SKANSIBLE_STAGE=1 -SKANSIBLE_DEBUG=1 -SKANSIBLE_UNIT_TEST=1 -DEFAULT_USER=senpai -DEFAULT_SKANSIBLE_PLAY_HOST=vps -SKANSIBLE_SSH_KEY_COLLECTION=(~/.ssh/ed25519\@staging ~/.ssh/ecdsa\@staging ~/.ssh/ed25519-37851076-sk\@staging ~/.ssh/ecdsa-37851076-sk\@staging) + +export ANSIBLE_FORCE_COLOR=True +SKANSIBLE_STAGE=0 +ANSIBLE_VERBOSITY=0 +SKANSIBLE_UNITTEST=False +SKANSIBLE_MODE=prod if [[ "$1" == "version" ]]; then - echo "0.0.0" + echo "26.07" fi if [[ "$1" == "show-defaults" ]]; then source "${SKANSIBLE_SCRIPT_PATH}/.env/bin/activate" - printf "User: %s\n" "$DEFAULT_USER" - printf "Expected hosts for playbook: %s\n" "$DEFAULT_SKANSIBLE_PLAY_HOST" printf "Private SSH keys available throufh SSH agent: |\n%s\n" "$(ssh-add -l)" fi @@ -26,6 +24,11 @@ if [[ "$1" == "start-agent" ]]; then eval "$(ssh-agent -s)" fi +if [[ "$1" == "list-agent" ]]; then + source "${SKANSIBLE_SCRIPT_PATH}/.env/bin/activate" + ssh-add -l +fi + if [[ "$1" == "populate-agent" ]]; then shift 1 @@ -44,19 +47,23 @@ if [[ "$1" == "populate-agent" ]]; then *) ssh-add "${SKANSIBLE_SSH_KEY}";; esac done - elif [[ "$1" == "select" ]]; then - for key in "${SKANSIBLE_SSH_KEY_COLLECTION[@]}"; do - ssh-add "$key" - done - elif [[ -z "$1" ]]; then + elif [[ "$1" == "staging" ]]; then + SKANSIBLE_SSH_KEY_COLLECTION=(~/.ssh/ed25519\@staging ~/.ssh/ecdsa\@staging ~/.ssh/ed25519-37851076-sk\@staging ~/.ssh/ecdsa-37851076-sk\@staging) + shift 1 + elif [[ "$1" == "prod" ]]; then + SKANSIBLE_SSH_KEY_COLLECTION=(~/.ssh/ed25519\@staging ~/.ssh/ecdsa\@staging ~/.ssh/ed25519-37851076-sk\@staging ~/.ssh/ecdsa-37851076-sk\@staging) + shift 1 + elif [[ -n "$1" ]]; then # @TODO improve by adding fuzzy querying or file finding pror ssh-add "$1" + exit 0 fi -fi -if [[ "$1" == "list-agent" ]]; then - source "${SKANSIBLE_SCRIPT_PATH}/.env/bin/activate" - ssh-add -l + for key in "${SKANSIBLE_SSH_KEY_COLLECTION[@]}"; do + ssh-add "$key" + done + + exit 0 fi if [[ "$1" == "init" ]]; then @@ -64,36 +71,55 @@ if [[ "$1" == "init" ]]; then source "${SKANSIBLE_SCRIPT_PATH}/.env/bin/activate" - while getopts "hsdtu:p:n:" opt; do + if [[ "$1" == "vps" ]]; then + SKANSIBLE_PLAY_HOST="$1" + shift 1 + elif [[ "$1" == "homeserver" ]]; then + SKANSIBLE_PLAY_HOST="$1" + shift 1 + else + echo "A playbook type must be specified" + exit 1 + fi + + while getopts "htm:s:n:v:u:" opt; do case $opt in - h) Help "$1";; - s) SKANSIBLE_STAGE=0;; - d) SKANSIBLE_DEBUG=0;; - t) SKANSIBLE_UNIT_TEST=0;; - u) SKANSIBLE_CONN_USER="$OPTARG";; - n) SKANSIBLE_CONN_HOSTS="$OPTARG";; - p) SKANSIBLE_PLAY_HOSTS="$OPTARG";; + h) Help "init";; + s) SKANSIBLE_STAGE="$OPTARG";; + n) SKANSIBLE_CONN_HOST="$OPTARG";; + v) export ANSIBLE_VERBOSITY="$OPTARG";; + t) SKANSIBLE_UNITTEST=True;; + u) export ANSIBLE_REMOTE_USER="$OPTARG";; + m) SKANSIBLE_MODE="$OPTARG";; *) echo "Err: Invalid option set"; exit 1;; esac done - if [[ "$SKANSIBLE_STAGE" == 0 ]]; then - SKANSIBLE_CONN_HOSTS=${SKANSIBLE_CONN_HOSTS:-${DEFAULT_SKANSIBLE_PLAY_HOST}}_test - fi - - if [[ "$SKANSIBLE_DEBUG" == 0 ]]; then - if [[ "$SKANSIBLE_UNIT_TEST" == 0 ]]; then - sudo ansible-playbook -vvvv --ask-pass --ask-become-pass -i hosts.yml --extra-vars "chosen_host=${SKANSIBLE_CONN_HOSTS}" --extra-vars "chosen_user=${SKANSIBLE_CONN_USER:-root}" "init@${SKANSIBLE_PLAY_HOSTS:-${DEFAULT_SKANSIBLE_PLAY_HOST}}.yml" --check - else - sudo ansible-playbook -vvvv --ask-pass --ask-become-pass -i hosts.yml --extra-vars "chosen_host=${SKANSIBLE_CONN_HOSTS}" --extra-vars "chosen_user=${SKANSIBLE_CONN_USER:-root}" "init@${SKANSIBLE_PLAY_HOSTS:-${DEFAULT_SKANSIBLE_PLAY_HOST}}.yml" + if [ -n "$SKANSIBLE_STAGE" ]; then + # SKANSIBLE_CONN_HOST=staging${SKANSIBLE_STAGE}.test + if [[ "$SKANSIBLE_STAGE" == 0 ]]; then + if [[ "$SKANSIBLE_UNITTEST" == "True" ]]; then + sudo ansible-playbook -CKk -i hosts.yml --extra-vars "chosen_host=${SKANSIBLE_CONN_HOST}" --extra-vars "chosen_user=${ANSIBLE_REMOTE_USER:-root}" --extra-vars "mode=${SKANSIBLE_MODE}" "init@${SKANSIBLE_PLAY_HOST}.yml" + else + sudo ansible-playbook -Kk -i hosts.yml --extra-vars "chosen_host=${SKANSIBLE_CONN_HOST}" --extra-vars "chosen_user=${ANSIBLE_REMOTE_USER:-root}" --extra-vars "mode=${SKANSIBLE_MODE}" "init@${SKANSIBLE_PLAY_HOST}.yml" + fi + elif [[ "$SKANSIBLE_STAGE" == 1 ]]; then + if [[ "$SKANSIBLE_UNITTEST" == "True" ]]; then + sudo ansible-playbook -CK -i hosts.yml --extra-vars "chosen_host=${SKANSIBLE_CONN_HOST}" --extra-vars "chosen_user=${ANSIBLE_REMOTE_USER:-root}" --extra-vars "mode=${SKANSIBLE_MODE}" "init@${SKANSIBLE_PLAY_HOST}.yml" + else + sudo ansible-playbook -K -i hosts.yml --extra-vars "chosen_host=${SKANSIBLE_CONN_HOST}" --extra-vars "chosen_user=${ANSIBLE_REMOTE_USER:-root}" --extra-vars "mode=${SKANSIBLE_MODE}" "init@${SKANSIBLE_PLAY_HOST}.yml" + fi fi else - if [[ "$SKANSIBLE_UNIT_TEST" == 0 ]]; then - sudo ansible-playbook --ask-pass --ask-become-pass -i hosts.yml --extra-vars "chosen_host=${SKANSIBLE_CONN_HOSTS}" --extra-vars "chosen_user=${SKANSIBLE_CONN_USER:-root}" "init@${SKANSIBLE_PLAY_HOSTS:-${DEFAULT_SKANSIBLE_PLAY_HOST}}.yml" --check + if [[ -z "$SKANSIBLE_CONN_HOST" ]]; then + echo "When not doing staging, chosen or preferred host must be made explicit" + exit 1 else - sudo ansible-playbook --ask-pass --ask-become-pass -i hosts.yml --extra-vars "chosen_host=${SKANSIBLE_CONN_HOSTS}" --extra-vars "chosen_user=${SKANSIBLE_CONN_USER:-root}" "init@${SKANSIBLE_PLAY_HOSTS:-${DEFAULT_SKANSIBLE_PLAY_HOST}}.yml" + sudo ansible-playbook -Kk -i hosts.yml --extra-vars "chosen_host=${SKANSIBLE_CONN_HOST}" --extra-vars "chosen_user=${ANSIBLE_REMOTE_USER:-root}" --extra-vars "mode=prod" "init@${SKANSIBLE_PLAY_HOST}.yml" fi fi + + exit 0 fi if [[ "$1" == "bootstrap" ]]; then @@ -101,34 +127,53 @@ if [[ "$1" == "bootstrap" ]]; then source "${SKANSIBLE_SCRIPT_PATH}/.env/bin/activate" - while getopts "hsdtu:p:n:" opt; do + if [[ "$1" == "vps" ]]; then + SKANSIBLE_PLAY_HOST="$1" + shift 1 + elif [[ "$1" == "homeserver" ]]; then + SKANSIBLE_PLAY_HOST="$1" + shift 1 + else + echo "A playbook type must be specified" + exit 1 + fi + + while getopts "htm:s:n:v:u:" opt; do case $opt in - h) Help "$1";; - s) SKANSIBLE_STAGE=0;; - d) SKANSIBLE_DEBUG=0;; - t) SKANSIBLE_UNIT_TEST=0;; - u) SKANSIBLE_CONN_USER="$OPTARG";; - n) SKANSIBLE_CONN_HOSTS="$OPTARG";; - p) SKANSIBLE_PLAY_HOSTS="$OPTARG";; + h) Help "bootstrap";; + s) SKANSIBLE_STAGE="$OPTARG";; + n) SKANSIBLE_CONN_HOST="$OPTARG";; + v) export ANSIBLE_VERBOSITY=4;; + t) SKANSIBLE_UNITTEST=True;; + u) export ANSIBLE_REMOTE_USER="$OPTARG";; + m) SKANSIBLE_MODE="$OPTARG";; *) echo "Err: Invalid option set"; exit 1;; esac done - if [[ "$SKANSIBLE_STAGE" == 0 ]]; then - SKANSIBLE_CONN_HOSTS=${SKANSIBLE_CONN_HOSTS:-${DEFAULT_SKANSIBLE_PLAY_HOST}}_test - fi - - if [[ "$SKANSIBLE_DEBUG" == 0 ]]; then - if [[ "$SKANSIBLE_UNIT_TEST" == 0 ]]; then - ansible-playbook -vvvv --ask-become-pass -i hosts.yml --extra-vars "chosen_host=${SKANSIBLE_CONN_HOSTS}" --extra-vars "chosen_user=${SKANSIBLE_CONN_USER:-${DEFAULT_USER}}" "administrate@${SKANSIBLE_PLAY_HOSTS:-${DEFAULT_SKANSIBLE_PLAY_HOST}}.yml" --check - else - ansible-playbook -vvvv --ask-become-pass -i hosts.yml --extra-vars "chosen_host=${SKANSIBLE_CONN_HOSTS}" --extra-vars "chosen_user=${SKANSIBLE_CONN_USER:-${DEFAULT_USER}}" "administrate@${SKANSIBLE_PLAY_HOSTS:-${DEFAULT_SKANSIBLE_PLAY_HOST}}.yml" + if [ -n "$SKANSIBLE_STAGE" ]; then + # SKANSIBLE_CONN_HOST=staging${SKANSIBLE_STAGE}.test + if [[ "$SKANSIBLE_STAGE" == 0 ]]; then + if [[ "$SKANSIBLE_UNITTEST" == "True" ]]; then + ansible-playbook -CKk -i hosts.yml --extra-vars "chosen_host=${SKANSIBLE_CONN_HOST}" --extra-vars "chosen_user=${ANSIBLE_REMOTE_USER:-senpai}" --extra-vars "mode=${SKANSIBLE_MODE}" "administrate@${SKANSIBLE_PLAY_HOST}.yml" + else + ansible-playbook -Kk -i hosts.yml --extra-vars "chosen_host=${SKANSIBLE_CONN_HOST}" --extra-vars "chosen_user=${ANSIBLE_REMOTE_USER:-senpai}" --extra-vars "mode=${SKANSIBLE_MODE}" "administrate@${SKANSIBLE_PLAY_HOST}.yml" + fi + elif [[ "$SKANSIBLE_STAGE" == 1 ]]; then + if [[ "$SKANSIBLE_UNITTEST" == "True" ]]; then + ansible-playbook -CK -i hosts.yml --extra-vars "chosen_host=${SKANSIBLE_CONN_HOST}" --extra-vars "chosen_user=${ANSIBLE_REMOTE_USER:-senpai}" --extra-vars "mode=${SKANSIBLE_MODE}" "administrate@${SKANSIBLE_PLAY_HOST}.yml" + else + ansible-playbook -K -i hosts.yml --extra-vars "chosen_host=${SKANSIBLE_CONN_HOST}" --extra-vars "chosen_user=${ANSIBLE_REMOTE_USER:-senpai}" --extra-vars "mode=${SKANSIBLE_MODE}" "administrate@${SKANSIBLE_PLAY_HOST}.yml" + fi fi else - if [[ "$SKANSIBLE_UNIT_TEST" == 0 ]]; then - ansible-playbook --ask-become-pass -i hosts.yml --extra-vars "chosen_host=${SKANSIBLE_CONN_HOSTS}" --extra-vars "chosen_user=${SKANSIBLE_CONN_USER:-${DEFAULT_USER}}" "administrate@${SKANSIBLE_PLAY_HOSTS:-${DEFAULT_SKANSIBLE_PLAY_HOST}}.yml" --check + if [[ -z "$SKANSIBLE_CONN_HOST" ]]; then + echo "When not doing staging, chosen or preferred host must be made explicit" + exit 1 else - ansible-playbook --ask-become-pass -i hosts.yml --extra-vars "chosen_host=${SKANSIBLE_CONN_HOSTS}" --extra-vars "chosen_user=${SKANSIBLE_CONN_USER:-${DEFAULT_USER}}" "administrate@${SKANSIBLE_PLAY_HOSTS:-${DEFAULT_SKANSIBLE_PLAY_HOST}}.yml" + ansible-playbook -Kk -i hosts.yml --extra-vars "chosen_host=${SKANSIBLE_CONN_HOST}" --extra-vars "chosen_user=${ANSIBLE_REMOTE_USER:-senpai}" --extra-vars "mode=prod" "administrate@${SKANSIBLE_PLAY_HOST}.yml" fi fi + + exit 0 fi diff --git a/vars/aria_api.yml.example b/vars/aria_api.yml.example deleted file mode 100644 index a09f789..0000000 --- a/vars/aria_api.yml.example +++ /dev/null @@ -1,6 +0,0 @@ -aria: - scheme: http - hostname: localhost - port: "6800" - secret: ~ - credentals: ~ \ No newline at end of file diff --git a/vars/aria_settings.yml b/vars/aria_settings.yml new file mode 100644 index 0000000..28bd7bd --- /dev/null +++ b/vars/aria_settings.yml @@ -0,0 +1,146 @@ +# @TODO use Ansible vault for secret and some credentials values +aria: + containerized: true + rpc: + enabled: false + listen_all: true + scheme: http + hostname: localhost + port: 6800 + secret: ~ + credentials: ~ + # dest: "{{ ansible_user_home.stdout }}/downloads/aria2" + log: warn + alloc: falloc # choices are "falloc", "prealloc", "trunc", or "none" + dcache: 64M + conn: + # netrc: + # path: "{{ ansible_user_home.stdout }}/.netrc" + max: + attempts: 3 + per_server: 3 + split: 6 + proxy: + enabled: true + uri: "localhost:9050" + excluded: + - "127.0.0.1" + - "::1" + dl: + max: + concurrent: 30 + resume: true + overwriting: true + autorenaming: true + # stats: + # path: "{{ ansible_user_home.stdout }}/.aria2/dl.log" + algorithm: adaptive # choices are "inorder", "feedback", "adaptive" + ul: + max: + overall: 5M + per_entry: 0 + http: + gzip: true + cache: false + sustain: true + agent: "Mozilla/5.0 (X11; Linux x86_64; rv:140.0) Gecko/20100101 Firefox/140.0" + ftp: + mode: passive # choices are "passive" or "active" + data_type: binary # choices are "binary" or "ascii" + trnt: + dht: + enabled: true + port: 6881-6999 + entrypoint: ~ + # path: "{{ ansible_user_home.stdout }}/.aria2/dht.dat" + # path6: "{{ ansible_user_home.stdout }}/.aria2/dht6.dat" + local_discovery: true + encrypt: true + peers: + agent: "Deluge 1.3.15" + prefix: "-DE13F0-" + max: 100 + exchange: true + seeding: + ratio: 2.0 + time: 0 + trackers: + - http://1337.abcvg.info:80/announce + - http://bt1.archive.org:6969/announce + - http://ipv4announce.sktorrent.eu:6969/announce + - http://nyaa.tracker.wf:7777/announce + - http://torrentsmd.com:8080/announce + - http://tracker.bt4g.com:2095/announce + - http://tracker.dhitechnical.com:6969/announce + - http://tracker.mywaifu.best:6969/announce + - http://tracker.renfei.net:8080/announce + - http://tracker.waaa.moe:6969/announce + - http://tracker.xn--djrq4gl4hvoi.top:80/announce + - http://www.wareztorrent.com:80/announce + - https://021912.xyz:443/announce + - https://1337.abcvg.info:443/announce + - https://banananetwork.qzz.io:443/announce + - https://orgtgju.org:443/announce + - https://t.213891.xyz:443/announce + - https://torrents.tmtime.dev:443/announce + - https://tr.abiir.top:443/announce + - https://tr.nyacat.pw:443/announce + - https://tr.zukizuki.org:443/announce + - https://tracker.7471.top:443/announce + - https://tracker.anibt.net:443/announce + - https://tracker.gcrenwp.top:443/announce + - https://tracker.kuroy.me:443/announce + - https://tracker.leechshield.link:443/announce + - https://tracker.manager.v6.navy:443/announce + - https://tracker.nekomi.cn:443/announce + - https://tracker.pmman.tech:443/announce + - https://tracker.zhuqiy.com:443/announce + - https://tracker1.520.jp:443/announce + - udp://anime-tracker.aruku.kro.kr:8081/announce + - udp://bittorrent-tracker.e-n-c-r-y-p-t.net:1337/announce + - udp://coeus.torrentonline.cc:42069/announce + - udp://evan.im:6969/announce + - udp://mail.segso.net:6969/announce + - udp://martin-gebhardt.eu:25/announce + - udp://ns575949.ip-51-222-82.net:6969/announce + - udp://open.demonii.com:1337/announce + - udp://open.ftorrent.com:443/announce + - udp://open.stealth.si:80/announce + - udp://open.tracker.ink:6969/announce + - udp://opentor.org:2710/announce + - udp://p4p.arenabg.com:1337/announce + - udp://seedpeer.net:6969/announce + - udp://t.overflow.biz:6969/announce + - udp://torrentclub.online:1984/announce + - udp://tracker-udp.gbitt.info:80/announce + - udp://tracker.004430.xyz:1337/announce + - udp://tracker.aruku.ovh:8081/announce + - udp://tracker.auctor.tv:6969/announce + - udp://tracker.bittor.pw:1337/announce + - udp://tracker.bluefrog.pw:2710/announce + - udp://tracker.breizh.pm:6969/announce + - udp://tracker.corpscorp.online:80/announce + - udp://tracker.dler.com:6969/announce + - udp://tracker.ducks.party:1984/announce + - udp://tracker.gmi.gd:6969/announce + - udp://tracker.hismz.cn:6969/announce + - udp://tracker.opentorrent.top:6969/announce + - udp://tracker.opentrackr.org:1337/announce + - udp://tracker.peerfect.org:6969/announce + - udp://tracker.publictracker.xyz:6969/announce + - udp://tracker.qu.ax:6969/announce + - udp://tracker.skyts.net:6969/announce + - udp://tracker.t-1.org:6969/announce + - udp://tracker.teambelgium.net:6969/announce + - udp://tracker.torrent.eu.org:451/announce + - udp://tracker.trackarr.org:6969/announce + - udp://tracker.tryhackx.org:6969/announce + - udp://tracker.wildkat.net:6969/announce + - udp://yuptracker-eu.gaijinent.com:27022/announce + - udp://zer0day.ch:1337/announce + - wss://tracker.openwebtorrent.com:443/announce + meta: + follow: mem + lang: en + protocol_pref: ftp # choices are "ftp", "http", "https" + locs: [] \ No newline at end of file diff --git a/vars/caddy_settings.yml b/vars/caddy_settings.yml new file mode 100644 index 0000000..12390b4 --- /dev/null +++ b/vars/caddy_settings.yml @@ -0,0 +1,3 @@ +caddy: + containerized: true + scheme: http \ No newline at end of file diff --git a/vars/certbot_settings@homeserver.yml b/vars/certbot_settings@homeserver.yml new file mode 100644 index 0000000..3db1581 --- /dev/null +++ b/vars/certbot_settings@homeserver.yml @@ -0,0 +1,10 @@ +certbot: + mode: "{{ mode | default('prod') }}" + containerized: true + auth_method: webroot + port: ~ + email: ajt95@prole.biz + domains: + - "{{ inventory_hostname }}" + - "*.{{ inventory_hostname }}" + cron: "2 6 24 1 *" \ No newline at end of file diff --git a/vars/certbot_settings@vps.yml b/vars/certbot_settings@vps.yml new file mode 100644 index 0000000..89b7e49 --- /dev/null +++ b/vars/certbot_settings@vps.yml @@ -0,0 +1,10 @@ +certbot: + mode: "{{ mode | default('prod') }}" + containerized: false + auth_method: dns + port: 53 + email: ajt95@prole.biz + domains: + - "{{ inventory_hostname }}" + - "*.{{ inventory_hostname }}" + cron: ~ \ No newline at end of file diff --git a/vars/crowdsec.yml b/vars/crowdsec.yml deleted file mode 100644 index e136969..0000000 --- a/vars/crowdsec.yml +++ /dev/null @@ -1,2 +0,0 @@ -crowdsec: - port: 8181 \ No newline at end of file diff --git a/vars/crowdsec_settings.yml b/vars/crowdsec_settings.yml new file mode 100644 index 0000000..86708fa --- /dev/null +++ b/vars/crowdsec_settings.yml @@ -0,0 +1,9 @@ +crowdsec: + containerized: false + port: 6050 + colls: + - "crowdsecurity/base-http-scenarios" + - "crowdsecurity/proftpd" + parsers: [] + scenarios: [] + postoverflows: [] \ No newline at end of file diff --git a/vars/email_settings.yml b/vars/email_settings.yml new file mode 100644 index 0000000..2841b04 --- /dev/null +++ b/vars/email_settings.yml @@ -0,0 +1,9 @@ +email: + smtp: + auth_meth: login + host: smtp.startmail.com + port: 465 + conn_mode: ssl + username: rika@sukaato.moe + password: "{{ lookup('password', './.tmp/' + inventory_hostname + '-user@email/email.pass', chars=['ascii_lowercase', 'digits'], length=8) }}" + alias: admin@sukaato.moe \ No newline at end of file diff --git a/vars/flexget_dls.yml b/vars/flexget_settings.yml similarity index 66% rename from vars/flexget_dls.yml rename to vars/flexget_settings.yml index 6b9d472..b7101fb 100644 --- a/vars/flexget_dls.yml +++ b/vars/flexget_settings.yml @@ -1,2 +1,3 @@ flexget: + enabled: true download_mode: direct \ No newline at end of file diff --git a/vars/gitea_settings.yml b/vars/gitea_settings.yml new file mode 100644 index 0000000..7e8c382 --- /dev/null +++ b/vars/gitea_settings.yml @@ -0,0 +1,16 @@ +gitea: + containerized: true + subdomain: git + trusted: + proxies: + - "127.0.0.1" + - "::1" + db: + type: mysql + name: "{{ mysql.users.admin.databases.gitea.name }}" + ssh: + port: 2323 + site: + registration: + enabled: true + landing: explore \ No newline at end of file diff --git a/vars/glance_settings.yml b/vars/glance_settings.yml new file mode 100644 index 0000000..2bc5cfd --- /dev/null +++ b/vars/glance_settings.yml @@ -0,0 +1,10 @@ +glance: + containerized: true + port: 8080 + proxied: true + timezone: + id: America/New_York + name: New York, United States of America + weather_loc: Hancock, MD + search: + engine: duckduckgo \ No newline at end of file diff --git a/vars/headscale_settings.yml b/vars/headscale_settings.yml new file mode 100644 index 0000000..4a9471e --- /dev/null +++ b/vars/headscale_settings.yml @@ -0,0 +1,23 @@ +headscale: + users: + admin: + username: admin + dname: Administrator + email: rika@sukaato.moe + pfp: ~ + scheme: http + port: 9191 + # @NOTE https://headscale.net/stable/ref/tls/ + grpc: + expose: false + secure: true + port: 50443 + magic_dns: + domain: "cyberia.net" + nameservers: + - "https://dns.nextdns.io/5a5ac6" + - 9.9.9.9 + clients: + - name: staging1.test + description: "my homelab server" + diff --git a/vars/local_facts.yml b/vars/local_facts.yml new file mode 100644 index 0000000..a83e1fe --- /dev/null +++ b/vars/local_facts.yml @@ -0,0 +1,3 @@ +local_facts: + user_id: rika + user_dir: /home/rika \ No newline at end of file diff --git a/vars/local_facts.yml.example b/vars/local_facts.yml.example deleted file mode 100644 index 1cfb29f..0000000 --- a/vars/local_facts.yml.example +++ /dev/null @@ -1,3 +0,0 @@ -local_facts: - user_id: "" - user_dir: "" \ No newline at end of file diff --git a/vars/mysql_settings.yml b/vars/mysql_settings.yml new file mode 100644 index 0000000..c6b2e8b --- /dev/null +++ b/vars/mysql_settings.yml @@ -0,0 +1,17 @@ +mysql: + containerized: true + password: "{{ lookup('password', './.tmp/' + inventory_hostname + '-root@mysql/mysql.pass', chars=['ascii_lowercase', 'digits'], length=8) }}" + users: + admin: + username: admin + # @TODO see if manual creation of additional databases is necessary for the DBMS server + databases: + init: + name: testdb + nextcloud: + name: nextcloud + gitea: + name: gitea + opengist: + name: opengist + password: "{{ lookup('password', './.tmp/' + inventory_hostname + '-user@mysql/mysql.pass', chars=['ascii_lowercase', 'digits'], length=8) }}" diff --git a/vars/nextcloud_settings.yml b/vars/nextcloud_settings.yml new file mode 100644 index 0000000..97000fb --- /dev/null +++ b/vars/nextcloud_settings.yml @@ -0,0 +1,12 @@ +nextcloud: + containerized: true + subdomain: cloud + rewrite_ip: false + trusted: + proxies: + - "127.0.0.1" + - "::1" + db: + type: mysql + name: "{{ mysql.users.admin.databases.nextcloud.name }}" + diff --git a/vars/opengist_settings.yml b/vars/opengist_settings.yml new file mode 100644 index 0000000..a909323 --- /dev/null +++ b/vars/opengist_settings.yml @@ -0,0 +1,15 @@ +gist: + containerized: true + subdomain: gist + ssh: + port: 2323 + search: + priority: + - content + - description + - filename + - topic + - title + db: + type: mysql + name: "{{ mysql.users.admin.databases.opengist.name }}" diff --git a/vars/podpose_settings.yml b/vars/podpose_settings.yml new file mode 100644 index 0000000..45512e7 --- /dev/null +++ b/vars/podpose_settings.yml @@ -0,0 +1,24 @@ +compose: + mode: "{{ mode | default('prod') }}" + containers: + vpn: + name: wgclient + webserver: + name: revproxy0 + ssl: + name: sslcerts + cache: + name: cache0 + db: + name: db0 + cloud: + name: cloud + forge: + name: forge + pastebin: + name: gist + tail: + name: tailclient + dash: + name: dash + diff --git a/vars/redis_settings.yml b/vars/redis_settings.yml new file mode 100644 index 0000000..cf88b43 --- /dev/null +++ b/vars/redis_settings.yml @@ -0,0 +1,3 @@ +redis: + containerized: true + password: "{{ lookup('password', './.tmp/' + inventory_hostname + '-redis/redis.pass', chars=['ascii_lowercase', 'digits'], length=8) }}" \ No newline at end of file diff --git a/vars/source_code.yml b/vars/source_code.yml new file mode 100644 index 0000000..7f5bfec --- /dev/null +++ b/vars/source_code.yml @@ -0,0 +1,33 @@ +source_code: + ssh_user: git + # host: "50.116.54.76:3000" + host: git.sukaato.moe + user: admin + http_password: !vault | + $ANSIBLE_VAULT;1.1;AES256 + 63313633623936623132356235636366303065653261386165363437623163376566366463353266 + 3130646239623865366231646437353632303864386563660a636332653338303334396332626539 + 38626166326132333663313264326364643537373535626138363265626130613332303363643338 + 6535623863346530370a393638653135623964346262353838626137663130363437366533333431 + 35366261616561303632346462643239333665323366333032626532623039323030336130383234 + 6633343964386431326335383564653937343330613232313637 + repos: + compose: + name: "skato-compose" + rpath: /dependent + run: true + # @TODO turn skato-quartz 'content' or 'content/Research' subdirectory into separate archive + # @TODO turn skato-blog 'themes/sukaato' subdirectory into git submodule for hugo static site + # @TODO turn skato-blog 'content' into separate archive + blog_theme: + name: "skato-blog-theme" + run: false + blog: + name: "skato-blog" + run: true + cli: + name: "skato-cli" + run: false + site: + name: sukaato + run: false \ No newline at end of file diff --git a/vars/sox_prox.yml b/vars/sox_prox.yml deleted file mode 100644 index 8e9e731..0000000 --- a/vars/sox_prox.yml +++ /dev/null @@ -1,3 +0,0 @@ -sox: - hostname: localhost - port: "9050" \ No newline at end of file diff --git a/vars/surge_settings.yml b/vars/surge_settings.yml new file mode 100644 index 0000000..45d4e36 --- /dev/null +++ b/vars/surge_settings.yml @@ -0,0 +1,4 @@ +surge: + containerized: true + service: + enabled: false \ No newline at end of file diff --git a/vars/tail_net.yml.example b/vars/tail_net.yml.example deleted file mode 100644 index 563f63e..0000000 --- a/vars/tail_net.yml.example +++ /dev/null @@ -1,18 +0,0 @@ -tail: - users: - - username: "" - dname: "" - email: "" - pfp: ~ - scheme: https - domain: localhost - port: ":8080" - grpc: - expose: false - secure: true - port: ":50443" - magic_dns: - domain: "" - nameservers: - - 9.9.9.9 - diff --git a/vars/tailscale_settings.yml b/vars/tailscale_settings.yml new file mode 100644 index 0000000..de8ade8 --- /dev/null +++ b/vars/tailscale_settings.yml @@ -0,0 +1,3 @@ +tailscale: + containerized: true + scheme: http \ No newline at end of file diff --git a/vars/tor_settings.yml b/vars/tor_settings.yml new file mode 100644 index 0000000..322bcbf --- /dev/null +++ b/vars/tor_settings.yml @@ -0,0 +1,4 @@ +tor: + proxy: + hostname: localhost + port: "9050" \ No newline at end of file diff --git a/vars/vpn_server.yml.example b/vars/vpn_server.yml.example deleted file mode 100644 index cf3ab75..0000000 --- a/vars/vpn_server.yml.example +++ /dev/null @@ -1,17 +0,0 @@ -vpn_server: - driver: - name: dsnet - version: "v0.8.1" - interface: dsnet - forwards: - - [tcp,"80"] # HTTP - - [tcp,"443"] # HTTPS - - [tcp,"465"] # SMTP - - [tcp,"587"] # SMTP - - [tcp,"995"] # POP3 - - [tcp,"110"] # POP3 - - [tcp,"143"] # IMAP - - [tcp,"993"] # IMAP - clients: - - name: "" - desc: "my homelab server" diff --git a/vars/vpn_settings.yml b/vars/vpn_settings.yml new file mode 100644 index 0000000..00905d7 --- /dev/null +++ b/vars/vpn_settings.yml @@ -0,0 +1,17 @@ +vpn: + server: + driver: + name: dsnet + interface: dsnet + forwards: + - [tcp,"80"] # HTTP + - [tcp,"443"] # HTTPS + - [tcp,"465"] # SMTP + - [tcp,"587"] # SMTP + - [tcp,"995"] # POP3 + - [tcp,"110"] # POP3 + - [tcp,"143"] # IMAP + - [tcp,"993"] # IMAP + clients: + - name: staging1.test + desc: "my homelab server" diff --git a/vars/wireguard_settings.yml b/vars/wireguard_settings.yml new file mode 100644 index 0000000..35e855b --- /dev/null +++ b/vars/wireguard_settings.yml @@ -0,0 +1,3 @@ +wireguard: + debug: false + ip_forward: false \ No newline at end of file