created major large-scale changes

This commit is contained in:
2026-07-12 15:27:58 -04:00
parent e8b29bb8e8
commit e53d6255e0
99 changed files with 4183 additions and 2093 deletions

12
.gitignore vendored
View File

@@ -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/**

View File

@@ -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

View File

@@ -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

View File

@@ -1,690 +0,0 @@
# @TODO create inventory group variables akin to structure of sukaato group's for homeserver
# <str<vault>> representing password for Linux root user account of VPS
password: ""
# <str> representing hostname for LAN server; same as host or group variable name
instance: armitage
# <str<enum>> representing Linux distro or OS image to be used for VPS
# operating_system: "tftp://hikiki.local:69/debian.iso"
operating_system: ""
# <list[<str>]> of control node or local SSH key basenames
ssh_keys: []
# <list<dict>> list of administrative users (in Linux, users that can use "sudo")
admins:
- username: senpai # <str> arbitrary valid user name
services: "" # <list[<str>]> if linux system user, assocated servce
# <list[<str>]> list of control node or local SSH key basenames for this user
ssh_keys: []
# <str<vault?>> hashed (and maybe salted) password
password: ""
# <dict[<str>:<dict>]> package groups
pkgs:
# <dict[<str>:<dict>]> representing package groups installed by package manager via repositories
mngr:
# <list[<dict>]> 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: ~
# <dict[<str>:<dict>]> representing package groups installed by shell scripts
script:
# <list[<dict>]> 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
# <dict[<str>:<dict>]> representing package groups installed from source archives
archive:
# <list[<dict>]> 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
# <dict[<str>:<dict>]> 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

View File

@@ -1,550 +0,0 @@
# <str<vault>> representing password for Linux root user account of VPS
password: "{{ lookup('password', './.tmp/sukaato_test.pass', seed='sukaato_test', encrypt='sha512_crypt') }}"
# <str<vault>> representing API token for VPS cloud service
token: ~
# <str> representing name and hostname of VPS to be made in VPS cloud service
instance: sukaato
# <str<enum>> representing region options from or for given VPS cloud service
origin: us-east
# <str<enum>> representing Linux distro or OS image available in VPS service to be used for VPS
operating_system: linode/debian13
# <list[<str>]> list of control node or local SSH key basenames for root user
ssh_keys:
- ed25519@staging
- ecdsa@staging
# <list<dict>> list of administrative users (in Linux, users that can use "sudo")
admins:
- username: senpai # <str> arbitrary valid user name
services: ~ # <list[<str>]> if linux system user, assocated servce
# <list[<str>]> 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
# <str<vault?>> hashed (and maybe salted) password
password: "{{ lookup('password', './.tmp/senpai@sukaato_test.pass', seed='senpai:sukaato_test', encrypt='sha512_crypt') }}"
# <dict[<str>:<dict>]> package groups
pkgs:
# <dict[<str>:<dict>]> representing package groups installed by package manager via repositories
mngr:
# <list[<dict>]> 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: ~
# <dict[<str>:<dict>]> representing package groups installed by shell scripts
script:
# <list[<dict>]> 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
# <dict[<str>:<dict>]> representing package groups installed from source archives
archive:
# <list[<dict>]> 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
# <dict[<str>:<dict>]> 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

View File

@@ -1,77 +1,48 @@
# <str<vault>> representing password for Linux root user account of VPS
password: ""
password: "{{ lookup('password', './.tmp/' + inventory_hostname + '.pass', seed=inventory_hostname, encrypt='sha512_crypt') }}"
# <str<vault>> representing API token for VPS cloud service
token: ""
# <str> representing name and hostname of VPS to be made in VPS cloud service
instance: sukaato
token: ~
# <str<enum>> representing region options from or for given VPS cloud service
origin: us-east
# <str<enum>> representing Linux distro or OS image available in VPS service to be used for VPS
operating_system: linode/debian13
# <list[<str>]> list of control node or local SSH key basenames for root user
ssh_keys: []
ssh_keys:
- ed25519@staging
- ecdsa@staging
# <list<dict>> list of administrative users (in Linux, users that can use "sudo")
admins:
- username: senpai # <str> arbitrary valid user name
services: ~ # <list[<str>]> if linux system user, assocated servce
# <list[<str>]> 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
# <str<vault?>> hashed (and maybe salted) password
password: ""
password: "{{ lookup('password', './.tmp/senpai@' + inventory_hostname + '.pass', seed='senpai@' + inventory_hostname, encrypt='sha512_crypt') }}"
# <dict[<str>:<dict>]> package groups
pkgs:
# <dict[<str>:<dict>]> representing package groups installed by package manager via repositories
mngr:
# <list[<dict>]> 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
# <dict[<str>:<dict>]> representing package groups installed by shell scripts
script:
# <list[<dict>]> 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:
# <list[<dict>]> 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: ~
# handler: default
binaries:
core:
- name: dsnet
src: "https://github.com/naggie/dsnet/releases/download/v0.8.1/dsnet-linux-amd64"
handler: dsnet

View File

@@ -1,8 +1,6 @@
# @TODO create inventory group variables akin to structure of sukaato group's for homeserver
# <str<vault>> representing password for Linux root user account of VPS
password: "{{ lookup('password', '../.tmp/armitage_test.pass', seed='armitage_test', encrypt='sha512_crypt') }}"
# <str> 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') }}"
# <str<enum>> 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
# <str<vault?>> 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') }}"
# <dict[<str>:<dict>]> package groups
pkgs:
# <dict[<str>:<dict>]> representing package groups installed by package manager via repositories
mngr:
# <list[<dict>]> 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
# <dict[<str>:<dict>]> representing package groups installed by shell scripts
script:
# <list[<dict>]> 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:
# <list[<dict>]> 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
# <dict[<str>:<dict>]> 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

View File

@@ -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:

View File

@@ -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

View File

@@ -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
test_command: ~

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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"

View File

@@ -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

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

View File

@@ -0,0 +1,139 @@
<!DOCTYPE html>
<html>
<head>
<title>{{.Host}}: {{ph "http.request.uri.path"}}</title>
<style>
body {
background-image: url(./dark-matter.png);
animation: 7s infinite ease-in-out day-cycle-bg;
}
@keyframes day-cycle-bg {
0% {
background-color: #000;
}
15% {
background-color: #121212;
}
75% {
background-color: #121212;
}
100% {
background-color: #000;
}
}
img {
display: block;
margin: 3vh auto;
max-width: 25vw;
animation: 7s infinite alternate day-cycle-filter;
}
@keyframes day-cycle-filter {
0% {
filter: brightness(1.00) contrast(0.66) grayscale(0.75);
}
15% {
filter: brightness(1.33) contrast(1.00) grayscale(0.66);
}
75% {
filter: brightness(1.33) contrast(1.10) grayscale(0.66);
}
100% {
filter: brightness(1.00) contrast(0.66) grayscale(0.75);
}
}
#sun {
display: block;
content: "";
margin: 0 auto;
height: 10vw;
max-width: 100vw;
background-color: #993333;
box-shadow: 0 0 10px 5px #000 inset;
position: relative;
top: 3vh;
transform: rotateX(180deg) rotateY(180deg);
animation: 7s infinite linear day-cycle-celestial;
}
@keyframes day-cycle-celestial {
0% {
clip-path: circle(33px at 100% 0%);
}
25% {
clip-path: circle(33px at 75% 25%);
}
50% {
clip-path: circle(33px at center 66%);
}
75% {
clip-path: circle(33px at 25% 25%);
}
100% {
clip-path: circle(33px at 0% 0%);
}
}
#err-message, #err-trace {
display: block;
margin: 50px auto;
}
#err {
margin: 2vh auto;
max-width: 75vw;
color: #fff;
background-color: #000;
border-radius: 10px;
padding: 3%;
position: relative;
top: -50px;
z-index: -1;
animation: 7s infinite ease-in-out day-cycle-bxsh;
}
@keyframes day-cycle-bxsh {
0% {
box-shadow: 0 0 25px 15px #000 inset;
}
15% {
box-shadow: 0 0 25px 15px #121212 inset;
}
75% {
box-shadow: 0 0 25px 15px #121212 inset;
}
100% {
box-shadow: 0 0 25px 15px #000 inset;
}
}
#err-message {
max-width: 66%;
text-align: justify;
}
#err-trace {
max-width: 50%;
}
#err-summary {
text-align: center;
color: #993333;
}
</style>
</head>
<body>
<div id="sun"></div>
<img src="mythe-sisyphus-klein.png" alt="Sisyphus carrying a boulder" srcset="https://kariannekirsten.com/wp-content/uploads/2022/12/mythe-klein.png"/>
<main>
<article id="err">
<section id="err-summary" class="post frontmatter">
<h1>Under Construction</h1>
<h2>Err. {{ph "http.error.status_code"}}: {{ph "http.error.status_text"}}</h2>
</section>
<section id="err-body" class="post body">
<p id="err-message" class="message">{{ph "http.error.message"}}</p>
<code id="err-trace" class="trace http">
{{ph "http.error.trace"}}
</code>
</section>
</article>
</main>
</body>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 121 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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: []

View File

@@ -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
- 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

View File

@@ -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 }}"

View File

@@ -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
comment: Open up port 51820
loop:
- udp
- tcp

View File

@@ -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
- 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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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
- 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

View File

@@ -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"

View File

@@ -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 }}"

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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)

View File

@@ -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

View File

@@ -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
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

View File

@@ -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 }}"

View File

@@ -37,6 +37,7 @@
force: true
mode: "644"
follow_redirects: safe
timeout: 300
- name: Configuring ViM
become: true
become_user: "{{ current_user.stdout }}"

View File

@@ -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

View File

@@ -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([])) }}"

View File

@@ -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"

View File

@@ -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

View File

@@ -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([])) }}"

View File

@@ -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.

View File

@@ -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 %}

View File

@@ -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 }}

View File

@@ -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 %}

View File

@@ -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
}

View File

@@ -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"

View File

@@ -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

View File

@@ -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" }}

View File

@@ -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 %>
}
}

View File

@@ -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 %}

View File

@@ -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

View File

@@ -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 %}

View File

@@ -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.

View File

@@ -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.

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

View File

@@ -0,0 +1,3 @@
MYSQL_DB_HOST=localhost
MYSQL_DB_USER={{ mysql.users.admin.username }}
MYSQL_DB_NAME={{ mysql.users.admin.databases.init.name }}

View File

@@ -0,0 +1,3 @@
machine {{ source_code.host }}
login {{ source_code.user }}
password {{ source_code.http_password }}

View File

@@ -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 %}

View File

@@ -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

View File

@@ -0,0 +1 @@
REDIS_PARAMS={{ "--requirepass " + redis.password + " --appendonly yes" }}

View File

@@ -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.

View File

@@ -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

View File

@@ -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

View File

@@ -1,6 +0,0 @@
aria:
scheme: http
hostname: localhost
port: "6800"
secret: ~
credentals: ~

146
vars/aria_settings.yml Normal file
View File

@@ -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: []

3
vars/caddy_settings.yml Normal file
View File

@@ -0,0 +1,3 @@
caddy:
containerized: true
scheme: http

View File

@@ -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 *"

View File

@@ -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: ~

View File

@@ -1,2 +0,0 @@
crowdsec:
port: 8181

View File

@@ -0,0 +1,9 @@
crowdsec:
containerized: false
port: 6050
colls:
- "crowdsecurity/base-http-scenarios"
- "crowdsecurity/proftpd"
parsers: []
scenarios: []
postoverflows: []

9
vars/email_settings.yml Normal file
View File

@@ -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

View File

@@ -1,2 +1,3 @@
flexget:
enabled: true
download_mode: direct

16
vars/gitea_settings.yml Normal file
View File

@@ -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

10
vars/glance_settings.yml Normal file
View File

@@ -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

View File

@@ -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"

3
vars/local_facts.yml Normal file
View File

@@ -0,0 +1,3 @@
local_facts:
user_id: rika
user_dir: /home/rika

View File

@@ -1,3 +0,0 @@
local_facts:
user_id: ""
user_dir: ""

17
vars/mysql_settings.yml Normal file
View File

@@ -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) }}"

View File

@@ -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 }}"

View File

@@ -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 }}"

24
vars/podpose_settings.yml Normal file
View File

@@ -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

3
vars/redis_settings.yml Normal file
View File

@@ -0,0 +1,3 @@
redis:
containerized: true
password: "{{ lookup('password', './.tmp/' + inventory_hostname + '-redis/redis.pass', chars=['ascii_lowercase', 'digits'], length=8) }}"

33
vars/source_code.yml Normal file
View File

@@ -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

View File

@@ -1,3 +0,0 @@
sox:
hostname: localhost
port: "9050"

4
vars/surge_settings.yml Normal file
View File

@@ -0,0 +1,4 @@
surge:
containerized: true
service:
enabled: false

View File

@@ -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

View File

@@ -0,0 +1,3 @@
tailscale:
containerized: true
scheme: http

4
vars/tor_settings.yml Normal file
View File

@@ -0,0 +1,4 @@
tor:
proxy:
hostname: localhost
port: "9050"

View File

@@ -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"

17
vars/vpn_settings.yml Normal file
View File

@@ -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"

View File

@@ -0,0 +1,3 @@
wireguard:
debug: false
ip_forward: false