41 Commits
Author SHA1 Message Date
Alex Tavarez 1accba1566 added more documentation links 2026-07-14 16:00:29 -04:00
Alex Tavarez 101c1cc0aa added a link 2026-07-14 15:17:07 -04:00
Alex Tavarez a367b3c5e4 fixed typo in documentation 2026-07-14 15:13:39 -04:00
Alex Tavarez 673e318824 changed shell script examples to reflect added fully qualified domain name optional argument for subcommands running playbooks 2026-07-14 15:05:51 -04:00
Alex Tavarez 71261e4017 added option to script subcommand for specifying a fully qualified domain name 2026-07-14 15:04:45 -04:00
Alex Tavarez 9fb64cef30 changed script to reflect change in Python envirohnment path 2026-07-14 14:45:24 -04:00
Alex Tavarez 29d4f33a46 inserted 'fqdn' variable so use of inventory hostname as a fully qualified domain name for managed node or target host services could be overridden 2026-07-14 14:43:49 -04:00
Alex Tavarez 80fd0ebb09 edited documentation so installation section reflects changes in dependency management package use 2026-07-14 14:41:57 -04:00
Alex Tavarez a4d46ada94 changed pip freeze method of dependency management to uv based method for Python 2026-07-14 14:41:17 -04:00
Alex Tavarez e04ed6f273 excluding uv Python dependency manager from version control 2026-07-14 14:39:48 -04:00
Alex Tavarez d44c67df42 added passlib library as a requirement for auto-generation of passwords by Ansible 2026-07-14 14:18:58 -04:00
Alex Tavarez 7574b8f9b4 added installation instructions; clarified how FQDN assignment for managed nodes works and its relevant for a given use-case 2026-07-14 14:15:03 -04:00
Alex Tavarez aa590effb2 added missing step or assurance 2026-07-14 12:54:34 -04:00
Alex Tavarez 5d1e073470 added clarity to a callout/alert in the documentation 2026-07-14 09:30:38 -04:00
Alex Tavarez c7b1d2d30b added more shell script examples, this time showing how to use the shell script in this repo 2026-07-14 09:28:38 -04:00
Alex Tavarez ba7283b583 added SSH-related auth details as defaults when no HTTP auth available 2026-07-14 09:00:08 -04:00
Alex Tavarez 1060724cf8 added some documentation for configuring and using this Ansible project 2026-07-14 08:57:49 -04:00
Alex Tavarez aae7b50c8d wrapped package names in quotes as convention 2026-07-13 13:13:16 -04:00
Alex Tavarez 36b293f923 added a soulseek-cli installation 2026-07-13 13:03:57 -04:00
Alex Tavarez 7e1c8c3f46 enabled julia installation and added virtualization packages for staging hosts 2026-07-13 10:21:22 -04:00
Alex Tavarez c9ceb8e9cf added port forwarding to Vagrant VMs and changed their SSH defaults 2026-07-13 07:13:16 -04:00
Alex Tavarez 26eb7b38b9 changed networking options in Vagrantfiles 2026-07-12 16:56:35 -04:00
Alex Tavarez 35a2f98fc0 added some Vagrantfiles to the repository 2026-07-12 16:37:24 -04:00
Alex Tavarez e53d6255e0 created major large-scale changes 2026-07-12 15:27:58 -04:00
Alex Tavarez e8b29bb8e8 added systemd unit for setting iptables rules using added script, added DSNet systemd unit 2026-06-19 19:22:21 -04:00
Alex Tavarez aa8d61aa09 added attribute to reboot task to ignore errors; included variables file for configuring VPN, i.e. DSNet, service configuration 2026-06-19 19:21:09 -04:00
Alex Tavarez 2d6dcd3dab added attribute to reboot task to ignore errors; included variables file needed for VPN, i.e. DSNet, service configuration 2026-06-19 19:18:54 -04:00
Alex Tavarez 2c66c3bd43 removed tasks that were instead migrated to a role task included by a role handler 2026-06-19 19:17:24 -04:00
Alex Tavarez 20d1cd21a3 removed an empty line 2026-06-19 19:16:29 -04:00
Alex Tavarez 83fa171341 added task for grabbng software binary as software installation 2026-06-19 19:15:38 -04:00
Alex Tavarez 240efbb713 changed hardlink or actual destnation paths for software binaries, and used relative path for fetched secrets 2026-06-19 19:10:39 -04:00
Alex Tavarez bcf9eaebc9 removed unnecessary copy task for a source file in managed node 2026-06-19 19:06:55 -04:00
Alex Tavarez 125ec09c8f migrated DSNet tasks to own task file in role, as opposed to having it in relevant playbook 2026-06-19 19:04:54 -04:00
Alex Tavarez b784b781d3 added a DSNet handler including tasks for post-installation 2026-06-19 19:03:52 -04:00
Alex Tavarez 909682d74e moved burp and rsync installations, and added a new package group for direct software binaries, with dsnet listed in it 2026-06-19 19:02:29 -04:00
Alex Tavarez bd3029b914 made sure that handlers run prior to hostname change as well as a reboot in which the server is rendered inaccessible 2026-06-18 19:20:56 -04:00
Alex Tavarez 57a3e876b8 added task informing user of needed actions to take advantage of now-avaialble vim plugins 2026-06-18 19:19:23 -04:00
Alex Tavarez 1ce6879abf fixed typo in a line substitution, added SystemD restart tasks for service to abide by configuration changes 2026-06-18 19:18:26 -04:00
Alex Tavarez 9ea7fb37b0 fixed missing loop variable for headscale user registration task 2026-06-18 19:17:16 -04:00
Alex Tavarez 7584027890 moved VIM and Crowdsec setup handler listener, former due to now being userspace package group installation, latter due to needing to precede headscale handler tasks 2026-06-18 19:16:26 -04:00
Alex Tavarez a78613920c moved vim to userspace package group, referenced crowdsec handler, added password hashing/encryption 2026-06-18 19:14:14 -04:00
107 changed files with 4934 additions and 2328 deletions
+4 -9
View File
@@ -4,17 +4,10 @@
/hosts.yml /hosts.yml
/hosts.yaml /hosts.yaml
/hosts.json /hosts.json
*.bak uv.lock
/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 # Ansible runtime and backups
*.bak
*.original *.original
*.tmp *.tmp
/.tmp/ /.tmp/
@@ -27,12 +20,14 @@
/.devcontainer/ /.devcontainer/
.lock .lock
/.cache/ /.cache/
/roles/**/files/user/wg/containerized/*.conf
# Try tyo avoid any plain-text passwords # Try tyo avoid any plain-text passwords
*pwd* *pwd*
*pass* *pass*
*password* *password*
*secret* *secret*
*.key
roles/**/vars/* roles/**/vars/*
roles/**/vars/** roles/**/vars/**
+229
View File
@@ -0,0 +1,229 @@
# SKATO ANSIBLE
## Installation
Make sure you have `git`, `venv`, and `uv` installed. On GNU/Linux Debian-based distros with pre-installed `apt` package manager, the corresponding packages are:
- `git`
- `python3-venv`
- [Follow this guide](https://docs.astral.sh/uv/getting-started/installation/) for installing `uv`
Ansible must also be installed on your system (see [this guide](https://docs.ansible.com/projects/ansible/latest/installation_guide/index.html)). Then, in your interactive bash shell session, run the following in order:
```bash
git clone https://git.sukaato.moe/admin/skato-ansible.git
cd ./skato-ansible
uv venv .venv
uv sync
source .venv/bin/activate
ansible-galaxy collections install -r ./collections/requirements.yml
```
## Essential Background
### Software Management
The standard use-case, which we call the container routing case, of this Ansible library is to run its playbooks in such a way that one host ends up acting as a router (via VPN service) to services on another host.
In the container routing case these services are defined by a repository declared in `${ANSIBLE_PROJECT_ROOT}/vars/source_code.yml`, via setting `source_code.repos.compose.name` and `source_code.repos.compose.rpath`, respectively, to the name of a version-controlled source repository and to a desired path within that repository (that path written such that it treats the repository path as root, i.e. as `/`).
As can then be noted, the `source_code` dictionary holds an attribute `repos` with itself attributes of fixed name representing various services or utilities, each of whom must have a `name` attribute defined that represents the name of the corresponding version-controlled source repository for that service or utility.
The point of this set-up is to allow the repository name at its endpoint to change without requiring manual changes in the code using or deploying that repository as consequence. One unfortunate result of this is that adding a service or utiltiy from one's git bare repositories means making manual corresponding changes in `pkgs` software object groups in relevant [host variable files](https://docs.ansible.com/projects/ansible/latest/inventory_guide/intro_inventory.html#organizing-host-and-group-variables), in `${ANSIBLE_PROJECT_ROOT}/roles/init-server/handlers/{core,userspace}.yml` for calling installation or post-installation actions, and in `${ANSIBLE_PROJECT_ROOT}/roles/init-server/tasks/contingent/pkg/${SOFTWARE_NAME}.yml` for executing those actions. The convention is for [handler](https://docs.ansible.com/projects/ansible/latest/inventory_guide/intro_inventory.html#host-variables) [notifiers](https://docs.ansible.com/projects/ansible/latest/playbook_guide/playbooks_handlers.html#notifying-handlers), [handler](https://docs.ansible.com/projects/ansible/latest/inventory_guide/intro_inventory.html#host-variables) [listeners](https://docs.ansible.com/projects/ansible/latest/playbook_guide/playbooks_handlers.html#notifying-handlers) and software names to all be equivalent, though the software name can deviate from this relational pattern.
Importantly, the following top-level attributes of the `source_code` variable or dictionary are necessary if your version-controlled source repository source requires authentication:
- `host`
- `user`/`ssh_user`
- `http_password`/`ssh_password`
If you wish to be able to use both SSH and HTTP authentication methods for the version-controlled source repository or change the default preference for HTTP credential use, you may edit `${ANSIBLE_PROJECT_ROOT}/roles/init-server/templates/user/netrc.j2`. See [the CURL docuemntation for more information on the NetRC file format](https://everything.curl.dev/usingcurl/netrc.html).
The point of the `source_code` dictionary is that it allows plugging in and executing custom code from one's own source repositories.
All other software is simply handled through the aforementioned patttern of adding an entry to any of the following in a given [host variables file](https://docs.ansible.com/projects/ansible/latest/inventory_guide/intro_inventory.html#organizing-host-and-group-variables):
- `pkgs.mngr.core` or `pkgs.mngr.userspace` (software installed by package manager--in this case, `apt` as most tasks assume a Linux Debian system at Ansible's managed node)
- `pkgs.script.core` or `pkgs.script.userspace` (since different installation shell scripts allow for different parameters, entries for installation shell scripts here are downloaded--for actual installation, the script has to be ran in a set of tasks specified in a YAML file under `${ANSIBLE_PROJECT_ROOT}/roles/init-server/tasks/contingent/pkg/`)
- `pkgs.archive.core` or `pkgs.archive.userspace` (similar as before, except things like path movement or specification, building/compilation, etc., are what take place via the set of tasks specified under the YAML file under `${ANSIBLE_PROJECT_ROOT}/roles/init-server/tasks/contingent/pkg/`)
- `pkgs.git_repos.core` or `pkgs.git_repos.userspace` (similar as before, fulfilling any arbitrary set of specified tasks for the pulled git source repository--you get the point)
Each entry item must have a `handler` attribute whose value will be used to [notify](https://docs.ansible.com/projects/ansible/latest/playbook_guide/playbooks_handlers.html#notifying-handlers) a [handler](https://docs.ansible.com/projects/ansible/latest/inventory_guide/intro_inventory.html#host-variables) [listener](https://docs.ansible.com/projects/ansible/latest/playbook_guide/playbooks_handlers.html#notifying-handlers), whose `listen` attribute has that same value, that then includes tasks found in a YAML file under `${ANSIBLE_PROJECT_ROOT}/roles/init-server/tasks/contingent/pkg/` whose basename, conventionally, is the same as those `handler` and `listen` attribute values. All of which, again, also conventionally share the same value as the `name` attribute of the entry item.
The structure of entries within each `pkgs.${SOFTWARE_GROUP}.core`/`pkgs.${SOFTWARE_GROUP}.userspace` depends on `$SOFTWARE_GROUP` because it changes the semantics of installation. All entries are dictionary items.
> [!NOTE]
> A table will be added at a later date, covering the attributes of the dictionary items for each `$SOFTWARE_GROUP`. For now, the [host variable files](https://docs.ansible.com/projects/ansible/latest/inventory_guide/intro_inventory.html#organizing-host-and-group-variables) for the staging hosts found in the [YAML inventory file](https://docs.ansible.com/projects/ansible/latest/inventory_guide/intro_inventory.html) can be used as reference.
### Configuration Management
#### System Configuration
The most important configuration is that needed for each host. This involves software installation, though [that is already covered in the above section](#software-management). Other important [host variables](https://docs.ansible.com/projects/ansible/latest/inventory_guide/intro_inventory.html#host-variables) for any given [host variable file](https://docs.ansible.com/projects/ansible/latest/inventory_guide/intro_inventory.html#organizing-host-and-group-variables) are:
variable name | type | default | semantics
--- | --- | --- | ---
`password` | `str` | auto-generated | the hashed password for the root user if the managed node had not spawned prior to playbook run
`ssh_keys` | `list` | `["ed25519@staging", "ecdsa@staging"]` | the basenames of the SSH key pairs for the root user
`admins` | `list` | `[{"username": "senpai", "services": None, "ssh_keys": ["ed25519@staging", "ecdsa@staging"], "password": ""} for d in admins]` | the list of Linux superusers, i.e. administrators, to exist
`token` | `str` | `None` | API key for cloud hosting account to spawn a VPS
`origin` | `str` | `us-east` | region or location of the VPS to determine timezones and locale; useful for Akamai Linode cloud hosting
`operating_system` | `str` | `None` | name or path to operating system for cloud hosted VPS or a VM / bare metal system
#### Software Configuration
Other configuration involves Ansible role templates or files, e.g. those found in `${ANSIBLE_PROJECT_ROOT}/roles/init-server/{templates,files}`. Generally, these Ansible role templates or files are sent over to the Ansible managed node by tasks provided by that same role, and referred to by tasks in the [playbooks](https://docs.ansible.com/projects/ansible/latest/playbook_guide/playbooks_intro.html).
The convention for templates is to set some desired though non- software native "defaults" and leave some settings or values to variables, grouped by the software for which they are relevant into variable files in `${ANSIBLE_PROJECT_ROOT}/vars/`, or what we may call the [playbook variable files](https://docs.ansible.com/projects/ansible/latest/playbook_guide/playbooks_variables.html#defining-variables-in-included-files-and-roles). These YAML variable files by convention have as their basename `${SOFTWARE_NAME}_settings` (with some exceptions), and must be listed (as paths relative to `$ANSIBLE_PROJECT_ROOT`) under `vars_files` on the [playbook](https://docs.ansible.com/projects/ansible/latest/playbook_guide/playbooks_intro.html) that will be running the tasks/[handlers](https://docs.ansible.com/projects/ansible/latest/inventory_guide/intro_inventory.html#host-variables), native to itself or taken from a role, that send the respective files or (after processing) templates over to the managed Ansible node(s). These kinds of files shall be called "settings files."
Inside each such settings file, the convention is for there to be a top-level variable (i.e., a single variable that takes a dictionary value) with a name of `$SOFTWARE_NAME`, whose value has attributes representing configuration options for the given software.
Some common, shared attributes for settings files are:
attribute name | type | default value | required? | semantics
--- | --- | --- | --- | ---
`containerized` | `bool` | `True` | only for services or software that is service-capable | determines whether the configuration is for a containerized or base system install
`mode` | `str` | "prod" | no | usefully allows for setting the mode for an individual piece of software rather than having it automatically agree with [the playbook mode](#essential-usage) or having it assume production mode
Other common ones, especially for services, are `port` (which can be an integer or string) and--for web servers--`scheme` (which can be either string "http" or "https", serving to toggle SSL/TLS DNS authentication for HTTP connections). These can exist at any nesting level under the top-level dictionary, based on the feature scope of the given software.
## Essential Usage
Before running any Ansible [playbooks](https://docs.ansible.com/projects/ansible/latest/playbook_guide/playbooks_intro.html) in either development or production mode, make sure to specify the username and the home directory path of the user on the system you are currently using in `{ANSIBLE_PROJECT_ROOT}/vars/local_facts.yml`.
### Development Mode
For development purposes in the container routing case, either first manually set up two Debian virtual machines, or (**recommended**) change into the `${ANSIBLE_PROJECT_ROOT}/staging0.test/` directory then `${ANSIBLE_PROJECT_ROOT}/staging1.test/` directory, running `vagrant up` for each. Running the [playbooks](https://docs.ansible.com/projects/ansible/latest/playbook_guide/playbooks_intro.html) in development mode also requires supplying "dev" as an argument for the extra `mode` parameter.
> [!WARNING]
> Vagrantfiles for neither staging host has yet been tested. Proceed by your own discretion.
If you intend to run the [playbooks](https://docs.ansible.com/projects/ansible/latest/playbook_guide/playbooks_intro.html) in production, the argument for this extra parameter should be "prod" (skip to the [Production Mode](#production-mode) section). The additional extra parameter of `chosen_host` should be adjusted to reflect the name of the host enlisted in the [YAML inventory file](https://docs.ansible.com/projects/ansible/latest/inventory_guide/intro_inventory.html) for production purposes.
> [!IMPORTANT]
> The names of hosts should be equivalent to their intended final domain name for services on any given host for the [playbook](https://docs.ansible.com/projects/ansible/latest/playbook_guide/playbooks_intro.html) to work correctly.
Anyway, for *any* mode double-check that the correct values are set for `chosen_user`. The first playbook you run for each host or IP in each pair of `ansible-playbook` commands in the upcoming shell script should always have `chosen_user` as "root". The extra parameter `chosen_user` for the second `ansible-playbook` command of each pair of `ansible-playbook` commands shown below should take an argument whose value is the same as that of the `username` attribute of any of the items in the `admins` list in the [host variables file](https://docs.ansible.com/projects/ansible/latest/inventory_guide/intro_inventory.html#organizing-host-and-group-variables) for the given host. With that in mind, execute the below for development mode for container routing case while in the `$ANSIBLE_PROJECT_ROOT` directory:
```bash
#!/bin/bash
set -euo pipefail
SSH_KEYS=()
sudo ansible-playbook -Kk -i hosts.yml --extra-vars "chosen_host=staging0.test" --extra-vars "chosen_user=root" --extra-vars "mode=dev" init\@vps.yml
$SSH_KEYS | xargs -I %k ssh-add %k # ADD NEEDED SSH KEY FILEPATHS
ansible-playbook -Kk -i hosts.yml --extra-vars "chosen_host=staging0.test" --extra-vars "chosen_user=senpai" --extra-vars "mode=dev" administrate\@vps.yml
sudo ansible-playbook -Kk -i hosts.yml --extra-vars "chosen_host=staging1.test" --extra-vars "chosen_user=root" --extra-vars "mode=dev" init\@homeserver.yml
# UNCOMMENT BELOW TO REASSIGN ENVIRONMENT VARIABLE FOR NEW ARRAY OF SSH KEYPAIR FILEPATHS
# SSH_KEYS=()
# UNCOMMENT BELOW TO ADD UPDATED SSH KEY PAIR FILEPATHS TO SSH_AGENT
# $SSH_KEYS | xargs -I %k ssh-add %k
ansible-playbook -Kk -i hosts.yml --extra-vars "chosen_host=staging1.test" --extra-vars "chosen_user=senpai" --extra-vars "mode=dev" administrate\@homeserver.yml
```
> [!WARNING]
> In the container routing case, development mode may not supply an accurate test of the intended networking result if the virtual machines for staging were manually created, but the [playbook](https://docs.ansible.com/projects/ansible/latest/playbook_guide/playbooks_intro.html) should run successfully. This is because apppropriate networking must be set for the virtual machine itself for VPN client containers in one virtual machine to "speak" with the VPN server in another virtual machine. The supplied Vagrantfiles are a WIP.
### Production Mode
Its important to note that the above shell script example for development mode would have to be modified in production mode for the container routing case such that every `ansible-playbook` call instance has its extra parameter `chosen_host` share the same value throughout. This is due to the combination of how SSL/TLS and domain names are set up in the [playbook](https://docs.ansible.com/projects/ansible/latest/playbook_guide/playbooks_intro.html) and the requirements of the container routing case. Namely, the former treats the inventory hostname used for the [playbook](https://docs.ansible.com/projects/ansible/latest/playbook_guide/playbooks_intro.html) as the [fully qualified domain name](https://en.wikipedia.org/wiki/Fully_qualified_domain_name) of that server host, while the container routing case requires that both server hosts share that [fully qualified domain name](https://en.wikipedia.org/wiki/Fully_qualified_domain_name).
This means that `chosen_host`'s value being the same across all `ansible-playbook` commands does not mean that value should represent the same managed node or host [IP](https://en.wikipedia.org/wiki/IP_address) throughout. Whether it does so is of course determined by whatever is in the [YAML inventory file](https://docs.ansible.com/projects/ansible/latest/inventory_guide/intro_inventory.html), so that would need to be changed when running [playbooks](https://docs.ansible.com/projects/ansible/latest/playbook_guide/playbooks_intro.html) against the second chosen host in the container routing case.
To drive all that home, in production we may instead need something like the following (again, executed while in the `$ANSIBLE_PROJECT_ROOT` directory):
```bash
#!/bin/bash
set -euo pipefail
SSH_KEYS=()
HOST_FQDN=web.site # a fully qualified domain name you own
CURRENT_IP= # whatever the current IP of the host $HOST_FQDN is
UPDATED_IP= # the desired new IP for the host $HOST_FQDN
sudo ansible-playbook -Kk -i hosts.yml --extra-vars "chosen_host=${HOST_FQDN}" --extra-vars "chosen_user=root" --extra-vars "mode=prod" init\@vps.yml
$SSH_KEYS | xargs -I %k ssh-add %k # ADD NEEDED SSH KEY PAIR FILEPATHS TO SSH_AGENT
ansible-playbook -Kk -i hosts.yml --extra-vars "chosen_host=${HOST_FQDN}" --extra-vars "chosen_user=senpai" --extra-vars "mode=prod" administrate\@vps.yml
sed '/'"$HOST_FQDN"':{N;s/'"$HOST_FQDN"':\n {6}ansible_host: '"$CURRENT_IP"'/'"$HOST_FQDN"':\n ansible_host: '"$NEW_IP"'/g}' hosts.yml
sudo ansible-playbook -Kk -i hosts.yml --extra-vars "chosen_host=${HOST_FQDN}" --extra-vars "chosen_user=root" --extra-vars "mode=prod" init\@homeserver.yml
# UNCOMMENT BELOW TO REASSIGN ENVIRONMENT VARIABLE FOR NEW ARRAY OF SSH KEYPAIR FILEPATHS
# SSH_KEYS=()
# UNCOMMENT BELOW TO ADD UPDATED SSH KEY PAIR FILEPATHS TO SSH_AGENT
# $SSH_KEYS | xargs -I %k ssh-add %k
ansible-playbook -Kk -i hosts.yml --extra-vars "chosen_host=${HOST_FQDN}" --extra-vars "chosen_user=senpai" --extra-vars "mode=prod" administrate\@homeserver.yml
```
**There *is* a way to avoid reassigning the IP address of the shared inventory hostname for each host the pair of playbooks is being run against in the container routing case under production.** This involves defining `fqdn` as a playbook variable or as an extra parameter for all `ansible-playbook` commands in the shell script, resulting in a shell script that looks more similar to our [development mode shell script](#development-mode):
```bash
#!/bin/bash
set -euo pipefail
SSH_KEYS=()
sudo ansible-playbook -Kk -i hosts.yml --extra-vars "chosen_host=staging0.test" --extra-vars "chosen_user=root" --extra-vars "mode=dev" --extra-vars "fqdn=web.site" init\@vps.yml
$SSH_KEYS | xargs -I %k ssh-add %k # ADD NEEDED SSH KEY FILEPATHS
ansible-playbook -Kk -i hosts.yml --extra-vars "chosen_host=staging0.test" --extra-vars "chosen_user=senpai" --extra-vars "mode=dev" --extra-vars "fqdn=web.site" administrate\@vps.yml
sudo ansible-playbook -Kk -i hosts.yml --extra-vars "chosen_host=staging1.test" --extra-vars "chosen_user=root" --extra-vars "mode=dev" --extra-vars "fqdn=web.site" init\@homeserver.yml
# UNCOMMENT BELOW TO REASSIGN ENVIRONMENT VARIABLE FOR NEW ARRAY OF SSH KEYPAIR FILEPATHS
# SSH_KEYS=()
# UNCOMMENT BELOW TO ADD UPDATED SSH KEY PAIR FILEPATHS TO SSH_AGENT
# $SSH_KEYS | xargs -I %k ssh-add %k
ansible-playbook -Kk -i hosts.yml --extra-vars "chosen_host=staging1.test" --extra-vars "chosen_user=senpai" --extra-vars "mode=dev" --extra-vars "fqdn=web.site" administrate\@homeserver.yml
```
> [!TIP]
> Adding the extra parameter here to the `ansible-playbook` commands of the development mode execution for the container routing use-case may also improve the realism of its execution and final state, virtual machine network configurations notwithstanding. Consider doing so for more realistic networking tests under the container routing case.
### Custom Playbooks
As long as you are matching the appropriate set of [playbook variable files](https://docs.ansible.com/projects/ansible/latest/playbook_guide/playbooks_variables.html#defining-variables-in-included-files-and-roles) or settings files with the [playbook](https://docs.ansible.com/projects/ansible/latest/playbook_guide/playbooks_intro.html) according to its need of those variable definitions/declarations, mostly determined by [the intended targeted hosts' own variables](https://docs.ansible.com/projects/ansible/latest/inventory_guide/intro_inventory.html#host-variables) together with role [handlers](https://docs.ansible.com/projects/ansible/latest/inventory_guide/intro_inventory.html#host-variables), and as long as you have appropriately set up software installations, (see [Software Management](#software-management)) creating new/custom [playbooks](https://docs.ansible.com/projects/ansible/latest/playbook_guide/playbooks_intro.html) should be relatively easy.
Depending on what you are trying to do with a new [playbook](https://docs.ansible.com/projects/ansible/latest/playbook_guide/playbooks_intro.html), the best approach may be to just copy/duplicate the extant [playbook files](https://docs.ansible.com/projects/ansible/latest/playbook_guide/playbooks_intro.html) and then edit them, as this allows one to mitigate errors as well as have a reliable reference point for changes.
### CLI Tool
As an alternative, you can use the `skato-ansible` shell script in `$ANSIBLE_PROJECT_ROOT` as an abstraction of the `ansible-playbook` commands for the container routing case. I plan to replace it with a CLI app covering more intended use-cases.
When using the `skato-ansible.sh` script in development mode for the container routing use case:
```bash
#!/bin/bash
set -euo pipefail
./skato-ansible.sh init vps -v 3 -m dev -n staging0.test
./skato-ansible.sh populate-agent staging
./skato-ansible.sh bootstrap vps -s 1 -v 3 -m dev -n staging0.test
./skato-ansible.sh init homeserver -v 3 -m dev -n staging1.test
# BELOW ONLY IF $SKANSIBLE_SSH_KEY ALTERED IN THE SHELL SCRIPT
# ./skato-ansible.sh populate-agent staging
./skato-ansible.sh bootstrap vps -s 1 -v 3 -m dev -n staging1.test
```
Otherwise, in production mode:
```bash
#!/bin/bash
set -euo pipefail
INVENTORY_HOSTNAMES=(web1 web2)
FQDN=web.site
./skato-ansible.sh init vps -v 3 -n "${INVENTORY_HOSTNAMES[0]}" -d "$FQDN"
./skato-ansible.sh populate-agent staging
./skato-ansible.sh bootstrap vps -s 1 -v 3 -n "${INVENTORY_HOSTNAMES[0]}" -d "$FQDN"
./skato-ansible.sh init homeserver -v 3 -n "${INVENTORY_HOSTNAMES[1]}" -d "$FQDN"
# BELOW ONLY IF $SKANSIBLE_SSH_KEY ALTERED IN THE SHELL SCRIPT
# ./skato-ansible.sh populate-agent staging
./skato-ansible.sh bootstrap vps -s 1 -v 3 -n "${INVENTORY_HOSTNAMES[1]}" -d "$FQDN"
```
> [!IMPORTANT]
> If you have different SSH keypairs for staging, make sure to change the value of `SKANSIBLE_SSH_KEYS` environment variable in the `${ANSIBLE_PROJECT_ROOT}/skato-ansible.sh` shell script before running the above shell scripts from `$ANSIBLE_PROJECT_ROOT`.
+74 -9
View File
@@ -1,13 +1,34 @@
- name: Initialize homeserver - name: Initialize homeserver
hosts: "{{ chosen_host | default('armitage') }}" hosts: "{{ chosen_host | default('staging1.test') }}"
remote_user: "{{ chosen_user | default('senpai') }}" remote_user: "{{ chosen_user | default('senpai') }}"
vars_files: 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/git_aliases.yml # REQUIRED
- vars/sox_prox.yml # REQUIRED - vars/vim_settings.yml # REQUIRED
- vars/flexget_dls.yml # REQUIRED - vars/tor_settings.yml # REQUIRED
- vars/aria_api.yml # REQUIRED
- vars/config@{{ inventory_hostname | default('homeserver') }}.yml - vars/config@{{ inventory_hostname | default('homeserver') }}.yml
tasks: 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 - name: Installing requisite packages
ansible.builtin.include_role: ansible.builtin.include_role:
name: init-server name: init-server
@@ -39,19 +60,19 @@
- disable_root_login - disable_root_login
- name: Reorganizing userspace package groups into single list - name: Reorganizing userspace package groups into single list
ansible.builtin.set_fact: 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 - name: Reorganizing core package groups into single list
ansible.builtin.set_fact: 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 - 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: community.general.git_config:
name: "alias.{{ item[0] }}" name: "alias.{{ item[0] }}"
scope: global scope: global
value: "{{ item[1] }}" value: "{{ item[1] }}"
loop: "{{ git_aliases }}" loop: "{{ git_aliases }}"
- name: Checking presence of dependency for flexget - name: Checking presence of dependency for flexget
when: "'uv' in all_core_pkgs" when: "'uv' in all_core_pkgs and flexget.enabled"
block: block:
- name: Installing flexget - name: Installing flexget
become: true become: true
@@ -139,6 +160,7 @@
group: "{{ ansible_user }}" group: "{{ ansible_user }}"
force: true force: true
backup: true backup: true
# validate: "flexget check"
- name: Creating a CRON job for flexget - name: Creating a CRON job for flexget
ansible.builtin.cron: ansible.builtin.cron:
name: Run flexget name: Run flexget
@@ -146,4 +168,47 @@
hour: "4-15" hour: "4-15"
weekday: "1-5" weekday: "1-5"
job: "{{ ansible_user_home.stdout }}/.local/bin/flexget --cron execute" job: "{{ ansible_user_home.stdout }}/.local/bin/flexget --cron execute"
- name: Checking presence of dependency
when: "'nvm' in all_core_pkgs or 'nvm' in all_userspace_pkgs"
block:
- name: Installing SoulSeek CLI
community.general.npm:
name: "soulseek-cli"
global: true
state: present
- 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
+36 -125
View File
@@ -1,9 +1,12 @@
- name: Initialize VPS - name: Initialize VPS
hosts: "{{ chosen_host | default('sukaato') }}" hosts: "{{ chosen_host | default('staging0.test') }}"
remote_user: "{{ chosen_user | default('senpai') }}" remote_user: "{{ chosen_user | default('senpai') }}"
vars_files: vars_files:
- vars/surge_settings.yml
- vars/git_aliases.yml # REQUIRED - vars/git_aliases.yml # REQUIRED
- vars/vpn_server.yml # REQUIRED - vars/vim_settings.yml # REQUIRED
- vars/podpose_settings.yml # REQUIRED
- vars/certbot_settings.yml # REQUIRED
- vars/config@{{ inventory_hostname | default('vps') }}.yml - vars/config@{{ inventory_hostname | default('vps') }}.yml
tasks: tasks:
- name: Installing requisite packages - name: Installing requisite packages
@@ -11,16 +14,6 @@
name: init-server name: init-server
tasks_from: userspace@install-pkgs tasks_from: userspace@install-pkgs
handlers_from: userspace handlers_from: userspace
- 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: Disabling root user shell login - name: Disabling root user shell login
become: true become: true
ansible.builtin.user: ansible.builtin.user:
@@ -53,121 +46,39 @@
scope: global scope: global
value: "{{ item[1] }}" value: "{{ item[1] }}"
loop: "{{ git_aliases }}" loop: "{{ git_aliases }}"
- name: Creating Wireguard VPS VPN service - name: Opening port 51820
block:
- name: Ensuring IP forwarding is allowed
become: true
ansible.posix.sysctl:
name: "net.{{ item }}.conf.all.forwarding"
value: "1"
sysctl_set: true
state: present
loop:
- ipv4
- ipv6
- name: Creating a directory to house VPN service client configurations
ansible.builtin.file:
path: "{{ ansible_user_home.stdout }}/.wg/authorized_clients.d"
recurse: true
owner: "{{ ansible_user }}"
group: "{{ ansible_user }}"
mode: "755"
state: directory
- name: Get the current hostname of the machine
ansible.builtin.shell:
cmd: "echo $(hostname)"
register: current_hostname
- name: Starting DSNet-based Wireguard VPN service configuration
when: vpn_server.driver.name == "dsnet"
block:
- name: Getting DSNet binary application
become: true
ansible.builtin.get_url:
url: "https://github.com/naggie/dsnet/releases/download/{{ vpn_server.driver.version }}/dsnet-linux-amd64"
dest: /usr/bin/dsnet
owner: root
group: root
mode: "744"
force: true
backup: true
- name: Initializing DSNet
become: true
ansible.builtin.command:
cmd: dsnet init
- name: Running DSNet VPN service interface
become: true
ansible.builtin.command:
cmd: dsnet up
- name: Adding peer device for DSNet VPN service interface
become: true
ansible.builtin.shell:
cmd: "dsnet add {{ item.name }}{{ idx }} --owner {{ current_user.stdout }} --description 'For {{ current_hostname.stdout }}--{{ 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_control:
index_var: idx
- name: Changing ownership of consequent DSNet VPN service client configurations
become: true
ansible.builtin.file:
path: "{{ ansible_user_home.stdout }}/.wg/authorized_clients.d/{{ item.name }}{{ (idx | string) }}.conf"
owner: "{{ ansible_user }}"
group: "{{ ansible_user }}"
state: file
loop: "{{ vpn_server.clients }}"
loop_control:
index_var: idx
- 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: Presenting DSNet VPN service client configuration files to control node for copying
when: data_method.user_input == "show"
block:
- 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_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 }}"
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: 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: "/var/tmp/{{ inventory_hostname }}/wg/"
flat: true
loop: "{{ vpn_server.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."
- name: Giving control node user time to read the aforementiioned message
ansible.builtin.pause:
seconds: 30
# @TODO create tasks for registering and presenting contents of just created files
- name: Forwarding network traffic on certain ports to Wireguard VPS service interface
become: true become: true
ansible.builtin.iptables: ansible.builtin.iptables:
chain: FORWARD chain: INPUT
protocol: "{{ item[0][0] }}" protocol: "{{ item }}"
source_port: "{{ item[0][1] }}" destination_port: 51820
in_interface: "{{ item[1] }}"
jump: ACCEPT jump: ACCEPT
loop: "{{ vpn_server.forwards | product([vpn_server.interface]) }}" comment: Open up port 51820
- name: Forwarding network traffic on certain ports to Wireguard VPS service interface loop:
- udp
- tcp
- name: Opening port 443
become: true become: true
ansible.builtin.iptables: ansible.builtin.iptables:
table: nat chain: INPUT
chain: POSTROUTING protocol: "{{ item }}"
out_interface: "{{ vpn_server.interface }}" destination_port: 443
jump: MASQUERADE 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
-690
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
-545
View File
@@ -1,545 +0,0 @@
# <str<vault>> representing password for Linux root user account of VPS
password: "{{ lookup('password', '../.tmp/sukaato_test.pass', seed='sukaato_test') }}"
# <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/sukaato_test.pass', seed='senpai:sukaato_test') }}"
# <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: vim
uri: ~
sources: ~
sigkey: ~
types: ~
suites: ~
comps: ~
handler: vim
- 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: ~
- 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: 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: ~
- 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: 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: ~
# <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: ~
+187 -276
View File
@@ -1,77 +1,48 @@
# <str<vault>> representing password for Linux root user account of VPS # <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 # <str<vault>> representing API token for VPS cloud service
token: "" 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 # <str<enum>> representing region options from or for given VPS cloud service
origin: us-east origin: us-east
# <str<enum>> representing Linux distro or OS image available in VPS service to be used for VPS # <str<enum>> representing Linux distro or OS image available in VPS service to be used for VPS
operating_system: linode/debian13 operating_system: linode/debian13
# <list[<str>]> list of control node or local SSH key basenames for root user # <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") # <list<dict>> list of administrative users (in Linux, users that can use "sudo")
admins: admins:
- username: senpai # <str> arbitrary valid user name - username: senpai # <str> arbitrary valid user name
services: ~ # <list[<str>]> if linux system user, assocated servce services: ~ # <list[<str>]> if linux system user, assocated servce
# <list[<str>]> list of control node or local SSH key basenames for this user # <list[<str>]> list of control node or local SSH key basenames for this user
ssh_keys: [] ssh_keys:
# @TODO add secondary and teriary Yubikeys
- ed25519@staging
- ecdsa@staging
# <str<vault?>> hashed (and maybe salted) password # <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 # <dict[<str>:<dict>]> package groups
pkgs: pkgs:
# <dict[<str>:<dict>]> representing package groups installed by package manager via repositories # <dict[<str>:<dict>]> representing package groups installed by package manager via repositories
mngr: mngr:
# <list[<dict>]> representing system-level or essential packages # <list[<dict>]> representing system-level or essential packages
core: core:
- name: sudo - name: "zfsutils-linux"
uri: ~ uri: ~
sigkey: ~ sigkey: ~
sources: ~ sources: ~
types: ~ types: ~
suites: ~ suites: ~
comps: ~ comps: ~
handler: ~ handler: default
- name: xz-utils - name: "zfs-dkms"
uri: ~ uri: ~
sigkey: ~ sigkey: ~
sources: ~ sources: ~
types: ~ types: ~
suites: ~ suites: ~
comps: ~ comps: ~
handler: ~ handler: default
- 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 - name: cron
uri: ~ uri: ~
sigkey: ~ sigkey: ~
@@ -79,47 +50,143 @@ pkgs:
types: ~ types: ~
suites: ~ suites: ~
comps: ~ comps: ~
handler: ~ handler: default
- name: cron-daemon-common - name: "cron-daemon-common"
uri: ~ uri: ~
sigkey: ~ sigkey: ~
sources: ~ sources: ~
types: ~ types: ~
suites: ~ suites: ~
comps: ~ comps: ~
handler: ~ handler: default
- name: qemu-kvm - name: "python3-certbot"
uri: ~ uri: ~
sigkey: ~ sigkey: ~
sources: ~ sources: ~
types: ~ types: ~
suites: ~ suites: ~
comps: ~ comps: ~
handler: ~ handler: default
- name: bridge-utils - name: "python3-certbot-dns-standalone"
uri: ~ uri: ~
sigkey: ~ sigkey: ~
sources: ~ sources: ~
types: ~ types: ~
suites: ~ suites: ~
comps: ~ comps: ~
handler: ~ handler: certbot
- name: libvirt-clients - name: sudo
uri: ~ uri: ~
sigkey: ~ sigkey: ~
sources: ~ sources: ~
types: ~ types: ~
suites: ~ suites: ~
comps: ~ comps: ~
handler: ~ handler: default
- name: libvirt-daemon-system - name: "xz-utils"
uri: ~ uri: ~
sigkey: ~ sigkey: ~
sources: ~ sources: ~
types: ~ types: ~
suites: ~ suites: ~
comps: ~ comps: ~
handler: ~ 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: "vagrant-libvirt"
uri: ~
sigkey: ~
sources: ~
types: ~
suites: ~
comps: ~
handler: default
- name: "qemu-system"
uri: ~
sigkey: ~
sources: ~
types: ~
suites: ~
comps: ~
handler: default
- name: "qemu-kvm"
uri: ~
sigkey: ~
sources: ~
types: ~
suites: ~
comps: ~
handler: default
- name: "bridge-utils"
uri: ~
sigkey: ~
sources: ~
types: ~
suites: ~
comps: ~
handler: default
- name: libvirt
uri: ~
sigkey: ~
sources: ~
types: ~
suites: ~
comps: ~
handler: default
- name: "libvirt-clients"
uri: ~
sigkey: ~
sources: ~
types: ~
suites: ~
comps: ~
handler: default
- name: "libvirt-daemon-system"
uri: ~
sigkey: ~
sources: ~
types: ~
suites: ~
comps: ~
handler: default
- name: "virt-install"
uri: ~
sigkey: ~
sources: ~
types: ~
suites: ~
comps: ~
handler: default
- name: "virt-viewer"
uri: ~
sigkey: ~
sources: ~
types: ~
suites: ~
comps: ~
handler: default
- name: gcc - name: gcc
uri: ~ uri: ~
sigkey: ~ sigkey: ~
@@ -127,23 +194,23 @@ pkgs:
types: ~ types: ~
suites: ~ suites: ~
comps: ~ comps: ~
handler: ~ handler: default
- name: git-doc - name: "git-doc"
uri: ~ uri: ~
sigkey: ~ sigkey: ~
sources: ~ sources: ~
types: ~ types: ~
suites: ~ suites: ~
comps: ~ comps: ~
handler: ~ handler: default
- name: git-delta - name: "git-delta"
uri: ~ uri: ~
sigkey: ~ sigkey: ~
sources: ~ sources: ~
types: ~ types: ~
suites: ~ suites: ~
comps: ~ comps: ~
handler: ~ handler: default
- name: fastfetch - name: fastfetch
uri: ~ uri: ~
sigkey: ~ sigkey: ~
@@ -151,15 +218,7 @@ pkgs:
types: ~ types: ~
suites: ~ suites: ~
comps: ~ comps: ~
handler: ~ handler: default
- name: vim
uri: ~
sources: ~
sigkey: ~
types: ~
suites: ~
comps: ~
handler: vim
- name: git - name: git
uri: ~ uri: ~
sources: ~ sources: ~
@@ -175,15 +234,7 @@ pkgs:
types: ~ types: ~
suites: ~ suites: ~
comps: ~ comps: ~
handler: ~ handler: default
- name: crowdsec
uri: ~
sources: ~
sigkey: ~
types: ~
suites: ~
comps: ~
handler: ~
- name: glow - name: glow
uri: ~ uri: ~
sigkey: "https://repo.charm.sh/apt/gpg.key" sigkey: "https://repo.charm.sh/apt/gpg.key"
@@ -191,39 +242,7 @@ pkgs:
types: deb types: deb
suites: "*" suites: "*"
comps: "*" comps: "*"
handler: ~ handler: default
- 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 - name: whois
uri: ~ uri: ~
sigkey: ~ sigkey: ~
@@ -231,7 +250,7 @@ pkgs:
types: ~ types: ~
suites: ~ suites: ~
comps: ~ comps: ~
handler: ~ handler: default
# @TODO make sure to create handler inclusion of tasks in file under/at `tasks/contingent/pkg` for below # @TODO make sure to create handler inclusion of tasks in file under/at `tasks/contingent/pkg` for below
- name: iptables - name: iptables
uri: ~ uri: ~
@@ -240,31 +259,7 @@ pkgs:
types: ~ types: ~
suites: ~ suites: ~
comps: ~ comps: ~
handler: ~ handler: default
- 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: ~
- name: gnupg - name: gnupg
uri: ~ uri: ~
sigkey: ~ sigkey: ~
@@ -272,31 +267,15 @@ pkgs:
types: ~ types: ~
suites: ~ suites: ~
comps: ~ comps: ~
handler: ~ handler: default
- name: gnupg-agent - name: "gnupg-agent"
uri: ~ uri: ~
sigkey: ~ sigkey: ~
sources: ~ sources: ~
types: ~ types: ~
suites: ~ suites: ~
comps: ~ comps: ~
handler: ~ handler: default
- name: gocryptfs
uri: ~
sigkey: ~
sources: ~
types: ~
suites: ~
comps: ~
handler: ~
- name: cryfs
uri: ~
sigkey: ~
sources: ~
types: ~
suites: ~
comps: ~
handler: ~
- name: tmux - name: tmux
uri: ~ uri: ~
sigkey: ~ sigkey: ~
@@ -304,15 +283,15 @@ pkgs:
types: ~ types: ~
suites: ~ suites: ~
comps: ~ comps: ~
handler: ~ handler: default
- name: cpu-checker - name: "cpu-checker"
uri: ~ uri: ~
sigkey: ~ sigkey: ~
sources: ~ sources: ~
types: ~ types: ~
suites: ~ suites: ~
comps: ~ comps: ~
handler: ~ handler: default
- name: libpam-doc - name: libpam-doc
uri: ~ uri: ~
sigkey: ~ sigkey: ~
@@ -320,7 +299,7 @@ pkgs:
types: ~ types: ~
suites: ~ suites: ~
comps: ~ comps: ~
handler: ~ handler: default
- name: headscale - name: headscale
uri: "https://github.com/juanfont/headscale/releases/download/v0.28.0/headscale_0.28.0_linux_amd64.deb" uri: "https://github.com/juanfont/headscale/releases/download/v0.28.0/headscale_0.28.0_linux_amd64.deb"
sigkey: ~ sigkey: ~
@@ -330,6 +309,38 @@ pkgs:
comps: ~ comps: ~
handler: headscale handler: headscale
userspace: 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 - name: neovim
uri: ~ uri: ~
sigkey: ~ sigkey: ~
@@ -345,79 +356,15 @@ pkgs:
types: ~ types: ~
suites: ~ suites: ~
comps: ~ comps: ~
handler: ~ handler: default
- name: proftpd-core - name: smartmontools
uri: ~ uri: ~
sigkey: ~ sigkey: ~
sources: ~ sources: ~
types: ~ types: ~
suites: ~ suites: ~
comps: ~ comps: ~
handler: ~ handler: default
- 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 - name: python3.13
uri: ~ uri: ~
sigkey: ~ sigkey: ~
@@ -425,23 +372,23 @@ pkgs:
types: ~ types: ~
suites: ~ suites: ~
comps: ~ comps: ~
handler: ~ handler: default
- name: python3-venv - name: "python3-venv"
uri: ~ uri: ~
sigkey: ~ sigkey: ~
sources: ~ sources: ~
types: ~ types: ~
suites: ~ suites: ~
comps: ~ comps: ~
handler: ~ handler: default
- name: python3-pip - name: "python3-pip"
uri: ~ uri: ~
sigkey: ~ sigkey: ~
sources: ~ sources: ~
types: ~ types: ~
suites: ~ suites: ~
comps: ~ comps: ~
handler: ~ handler: default
- name: golang - name: golang
uri: ~ uri: ~
sigkey: ~ sigkey: ~
@@ -449,39 +396,15 @@ pkgs:
types: ~ types: ~
suites: ~ suites: ~
comps: ~ comps: ~
handler: ~ handler: default
- name: yt-dlp - name: "golang-doc"
uri: ~ uri: ~
sigkey: ~ sigkey: ~
sources: ~ sources: ~
types: ~ types: ~
suites: ~ suites: ~
comps: ~ comps: ~
handler: ~ handler: default
- 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: ~
# <dict[<str>:<dict>]> representing package groups installed by shell scripts # <dict[<str>:<dict>]> representing package groups installed by shell scripts
script: script:
# <list[<dict>]> representing user-level or supplemental shell script installations # <list[<dict>]> representing user-level or supplemental shell script installations
@@ -496,11 +419,6 @@ pkgs:
pre: ~ pre: ~
post: ~ post: ~
handler: rustup handler: rustup
- name: julia
src: "https://install.julialang.org"
pre: ~
post: ~
handler: julia
- name: uv - name: uv
src: "https://astral.sh/uv/install.sh" src: "https://astral.sh/uv/install.sh"
pre: ~ pre: ~
@@ -510,18 +428,6 @@ pkgs:
archive: archive:
# <list[<dict>]> representing user-level or supplemental source archives # <list[<dict>]> representing user-level or supplemental source archives
userspace: 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 - name: difftastic
src: "https://github.com/Wilfred/difftastic/releases/download/0.69.0/difft-x86_64-unknown-linux-gnu.tar.gz" src: "https://github.com/Wilfred/difftastic/releases/download/0.69.0/difft-x86_64-unknown-linux-gnu.tar.gz"
deploy: ~ deploy: ~
@@ -537,4 +443,9 @@ pkgs:
# deploy: ~ # deploy: ~
# pre: ~ # pre: ~
# post: ~ # post: ~
# handler: ~ # handler: default
binaries:
core:
- name: dsnet
src: "https://github.com/naggie/dsnet/releases/download/v0.8.1/dsnet-linux-amd64"
handler: dsnet
@@ -1,8 +1,6 @@
# @TODO create inventory group variables akin to structure of sukaato group's for homeserver # @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 # <str<vault>> representing password for Linux root user account of VPS
password: "{{ lookup('password', '../.tmp/armitage_test.pass', seed='armitage_test') }}" password: "{{ lookup('password', './.tmp/' + inventory_hostname + '.pass', seed=inventory_hostname, encrypt='sha512_crypt') }}"
# <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 # <str<enum>> representing Linux distro or OS image to be used for VPS
# operating_system: "tftp://hikiki.local:69/debian.iso" # operating_system: "tftp://hikiki.local:69/debian.iso"
operating_system: ~ operating_system: ~
@@ -17,24 +15,56 @@ admins:
# <list[<str>]> list of control node or local SSH key basenames for this user # <list[<str>]> list of control node or local SSH key basenames for this user
ssh_keys: ssh_keys:
# @TODO add secondary and teriary Yubikeys # @TODO add secondary and teriary Yubikeys
- ecdsa-37851076-sk@staging - ed25519@staging
- ed25519-37851076-sk@staging - ecdsa@staging
# <str<vault?>> hashed (and maybe salted) password # <str<vault?>> hashed (and maybe salted) password
password: "{{ lookup('password', '../.tmp/armitage_test.pass', seed='senpai:armitage_test') }}" password: "{{ lookup('password', './.tmp/senpai@' + inventory_hostname + '.pass', seed='senpai@' + inventory_hostname, encrypt='sha512_crypt') }}"
# <dict[<str>:<dict>]> package groups # <dict[<str>:<dict>]> package groups
pkgs: pkgs:
# <dict[<str>:<dict>]> representing package groups installed by package manager via repositories # <dict[<str>:<dict>]> representing package groups installed by package manager via repositories
mngr: mngr:
# <list[<dict>]> representing system-level or essential packages # <list[<dict>]> representing system-level or essential packages
core: core:
- name: xz-utils - name: "zfsutils-linux"
uri: ~ uri: ~
sigkey: ~ sigkey: ~
sources: ~ sources: ~
types: ~ types: ~
suites: ~ suites: ~
comps: ~ comps: ~
handler: ~ 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: ~
sources: ~
types: ~
suites: ~
comps: ~
handler: default
- name: wireguard - name: wireguard
uri: ~ uri: ~
sigkey: ~ sigkey: ~
@@ -42,15 +72,95 @@ pkgs:
types: ~ types: ~
suites: ~ suites: ~
comps: ~ comps: ~
handler: ~ handler: wireguard
- name: wireguard-tools - name: "wireguard-tools"
uri: ~ uri: ~
sigkey: ~ sigkey: ~
sources: ~ sources: ~
types: ~ types: ~
suites: ~ suites: ~
comps: ~ comps: ~
handler: ~ handler: default
- name: vagrant
uri: ~
sigkey: ~
sources: ~
types: ~
suites: ~
comps: ~
handler: default
- name: "vagrant-libvirt"
uri: ~
sigkey: ~
sources: ~
types: ~
suites: ~
comps: ~
handler: default
- name: "qemu-system"
uri: ~
sigkey: ~
sources: ~
types: ~
suites: ~
comps: ~
handler: default
- name: "qemu-kvm"
uri: ~
sigkey: ~
sources: ~
types: ~
suites: ~
comps: ~
handler: default
- name: "bridge-utils"
uri: ~
sigkey: ~
sources: ~
types: ~
suites: ~
comps: ~
handler: default
- name: libvirt
uri: ~
sigkey: ~
sources: ~
types: ~
suites: ~
comps: ~
handler: default
- name: "libvirt-clients"
uri: ~
sigkey: ~
sources: ~
types: ~
suites: ~
comps: ~
handler: default
- name: "libvirt-daemon-system"
uri: ~
sigkey: ~
sources: ~
types: ~
suites: ~
comps: ~
handler: default
- name: "virt-install"
uri: ~
sigkey: ~
sources: ~
types: ~
suites: ~
comps: ~
handler: default
- name: "virt-viewer"
uri: ~
sigkey: ~
sources: ~
types: ~
suites: ~
comps: ~
handler: default
- name: sudo - name: sudo
uri: ~ uri: ~
sigkey: ~ sigkey: ~
@@ -58,15 +168,15 @@ pkgs:
types: ~ types: ~
suites: ~ suites: ~
comps: ~ comps: ~
handler: ~ handler: default
- name: kitty-terminfo - name: "kitty-terminfo"
uri: ~ uri: ~
sigkey: ~ sigkey: ~
sources: ~ sources: ~
types: ~ types: ~
suites: ~ suites: ~
comps: ~ comps: ~
handler: ~ handler: default
- name: whois - name: whois
uri: ~ uri: ~
sigkey: ~ sigkey: ~
@@ -74,7 +184,7 @@ pkgs:
types: ~ types: ~
suites: ~ suites: ~
comps: ~ comps: ~
handler: ~ handler: default
- name: smartmontools - name: smartmontools
uri: ~ uri: ~
sigkey: ~ sigkey: ~
@@ -82,39 +192,7 @@ pkgs:
types: ~ types: ~
suites: ~ suites: ~
comps: ~ comps: ~
handler: ~ handler: default
- 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 - name: snapd
uri: ~ uri: ~
sources: ~ sources: ~
@@ -122,7 +200,7 @@ pkgs:
types: ~ types: ~
suites: ~ suites: ~
comps: ~ comps: ~
handler: ~ handler: default
- name: git - name: git
uri: ~ uri: ~
sources: ~ sources: ~
@@ -131,30 +209,30 @@ pkgs:
suites: ~ suites: ~
comps: ~ comps: ~
handler: git handler: git
- name: git-delta - name: "git-delta"
uri: ~ uri: ~
sources: ~ sources: ~
sigkey: ~ sigkey: ~
types: ~ types: ~
suites: ~ suites: ~
comps: ~ comps: ~
handler: ~ handler: default
- name: git-doc - name: "git-doc"
uri: ~ uri: ~
sources: ~ sources: ~
sigkey: ~ sigkey: ~
types: ~ types: ~
suites: ~ suites: ~
comps: ~ comps: ~
handler: ~ handler: default
- name: git-man - name: "git-man"
uri: ~ uri: ~
sources: ~ sources: ~
sigkey: ~ sigkey: ~
types: ~ types: ~
suites: ~ suites: ~
comps: ~ comps: ~
handler: ~ handler: default
- name: fail2ban - name: fail2ban
uri: ~ uri: ~
sources: ~ sources: ~
@@ -162,15 +240,7 @@ pkgs:
types: ~ types: ~
suites: ~ suites: ~
comps: ~ comps: ~
handler: ~ handler: default
- name: crowdsec
uri: ~
sources: ~
sigkey: ~
types: ~
suites: ~
comps: ~
handler: ~
- name: glow - name: glow
uri: ~ uri: ~
sigkey: "https://repo.charm.sh/apt/gpg.key" sigkey: "https://repo.charm.sh/apt/gpg.key"
@@ -178,7 +248,7 @@ pkgs:
types: deb types: deb
suites: "*" suites: "*"
comps: "*" comps: "*"
handler: ~ handler: default
- name: pandoc - name: pandoc
uri: ~ uri: ~
sigkey: ~ sigkey: ~
@@ -186,7 +256,7 @@ pkgs:
types: ~ types: ~
suites: ~ suites: ~
comps: ~ comps: ~
handler: ~ handler: default
- name: curl - name: curl
uri: ~ uri: ~
sigkey: ~ sigkey: ~
@@ -194,15 +264,15 @@ pkgs:
types: ~ types: ~
suites: ~ suites: ~
comps: ~ comps: ~
handler: ~ handler: default
- name: build-essential - name: "build-essential"
uri: ~ uri: ~
sigkey: ~ sigkey: ~
sources: ~ sources: ~
types: ~ types: ~
suites: ~ suites: ~
comps: ~ comps: ~
handler: ~ handler: default
- name: fastfetch - name: fastfetch
uri: ~ uri: ~
sigkey: ~ sigkey: ~
@@ -210,7 +280,7 @@ pkgs:
types: ~ types: ~
suites: ~ suites: ~
comps: ~ comps: ~
handler: ~ handler: default
- name: gcc - name: gcc
uri: ~ uri: ~
sigkey: ~ sigkey: ~
@@ -218,7 +288,7 @@ pkgs:
types: ~ types: ~
suites: ~ suites: ~
comps: ~ comps: ~
handler: ~ handler: default
- name: dpkg-dev - name: dpkg-dev
uri: ~ uri: ~
sigkey: ~ sigkey: ~
@@ -226,7 +296,7 @@ pkgs:
types: ~ types: ~
suites: ~ suites: ~
comps: ~ comps: ~
handler: ~ handler: default
- name: ufw - name: ufw
uri: ~ uri: ~
sigkey: ~ sigkey: ~
@@ -234,7 +304,7 @@ pkgs:
types: ~ types: ~
suites: ~ suites: ~
comps: ~ comps: ~
handler: ~ handler: default
- name: avahi-daemon - name: avahi-daemon
uri: ~ uri: ~
sigkey: ~ sigkey: ~
@@ -242,7 +312,7 @@ pkgs:
types: ~ types: ~
suites: ~ suites: ~
comps: ~ comps: ~
handler: ~ handler: default
- name: avahi-utils - name: avahi-utils
uri: ~ uri: ~
sigkey: ~ sigkey: ~
@@ -250,39 +320,7 @@ pkgs:
types: ~ types: ~
suites: ~ suites: ~
comps: ~ comps: ~
handler: ~ handler: default
- 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 - name: libpam-u2f
uri: ~ uri: ~
sigkey: ~ sigkey: ~
@@ -290,7 +328,7 @@ pkgs:
types: ~ types: ~
suites: ~ suites: ~
comps: ~ comps: ~
handler: ~ handler: default
- name: pamu2fcfg - name: pamu2fcfg
uri: ~ uri: ~
sigkey: ~ sigkey: ~
@@ -298,7 +336,7 @@ pkgs:
types: ~ types: ~
suites: ~ suites: ~
comps: ~ comps: ~
handler: ~ handler: default
- name: pcscd - name: pcscd
uri: ~ uri: ~
sigkey: ~ sigkey: ~
@@ -306,7 +344,7 @@ pkgs:
types: ~ types: ~
suites: ~ suites: ~
comps: ~ comps: ~
handler: ~ handler: default
- name: tftpd-hpa - name: tftpd-hpa
uri: ~ uri: ~
sigkey: ~ sigkey: ~
@@ -314,7 +352,7 @@ pkgs:
types: ~ types: ~
suites: ~ suites: ~
comps: ~ comps: ~
handler: ~ handler: default
- name: gocryptfs - name: gocryptfs
uri: ~ uri: ~
sigkey: ~ sigkey: ~
@@ -322,7 +360,7 @@ pkgs:
types: ~ types: ~
suites: ~ suites: ~
comps: ~ comps: ~
handler: ~ handler: default
- name: cryfs - name: cryfs
uri: ~ uri: ~
sigkey: ~ sigkey: ~
@@ -330,7 +368,7 @@ pkgs:
types: ~ types: ~
suites: ~ suites: ~
comps: ~ comps: ~
handler: ~ handler: default
- name: tmux - name: tmux
uri: ~ uri: ~
sigkey: ~ sigkey: ~
@@ -338,39 +376,23 @@ pkgs:
types: ~ types: ~
suites: ~ suites: ~
comps: ~ comps: ~
handler: ~ handler: default
- name: cpu-checker - name: "cpu-checker"
uri: ~ uri: ~
sigkey: ~ sigkey: ~
sources: ~ sources: ~
types: ~ types: ~
suites: ~ suites: ~
comps: ~ comps: ~
handler: ~ handler: default
- name: libpam-doc - name: "libpam-doc"
uri: ~ uri: ~
sigkey: ~ sigkey: ~
sources: ~ sources: ~
types: ~ types: ~
suites: ~ suites: ~
comps: ~ comps: ~
handler: ~ handler: default
- name: burp
uri: ~
sigkey: ~
sources: ~
types: ~
suites: ~
comps: ~
handler: ~
- name: rsync
uri: ~
sigkey: ~
sources: ~
types: ~
suites: ~
comps: ~
handler: ~
- name: gnupg - name: gnupg
uri: ~ uri: ~
sigkey: ~ sigkey: ~
@@ -378,16 +400,56 @@ pkgs:
types: ~ types: ~
suites: ~ suites: ~
comps: ~ comps: ~
handler: ~ handler: default
- name: gnupg-agent - name: "gnupg-agent"
uri: ~ uri: ~
sigkey: ~ sigkey: ~
sources: ~ sources: ~
types: ~ types: ~
suites: ~ suites: ~
comps: ~ comps: ~
handler: ~ handler: default
userspace: 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: ~
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 - name: neovim
uri: ~ uri: ~
sources: ~ sources: ~
@@ -403,7 +465,7 @@ pkgs:
types: ~ types: ~
suites: ~ suites: ~
comps: ~ comps: ~
handler: ~ handler: default
- name: podman - name: podman
uri: ~ uri: ~
sigkey: ~ sigkey: ~
@@ -411,15 +473,23 @@ pkgs:
types: ~ types: ~
suites: ~ suites: ~
comps: ~ comps: ~
handler: ~ handler: podman
- name: podman-compose - name: passt
uri: ~ uri: ~
sigkey: ~ sigkey: ~
sources: ~ sources: ~
types: ~ types: ~
suites: ~ suites: ~
comps: ~ comps: ~
handler: ~ handler: default
- name: "podman-compose"
uri: ~
sigkey: ~
sources: ~
types: ~
suites: ~
comps: ~
handler: default
- name: distrobox - name: distrobox
uri: ~ uri: ~
sigkey: ~ sigkey: ~
@@ -427,79 +497,7 @@ pkgs:
types: ~ types: ~
suites: ~ suites: ~
comps: ~ comps: ~
handler: ~ handler: default
- 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 - name: python3.13
uri: ~ uri: ~
sigkey: ~ sigkey: ~
@@ -507,31 +505,31 @@ pkgs:
types: ~ types: ~
suites: ~ suites: ~
comps: ~ comps: ~
handler: ~ handler: default
- name: python3-venv - name: "python3-venv"
uri: ~ uri: ~
sigkey: ~ sigkey: ~
sources: ~ sources: ~
types: ~ types: ~
suites: ~ suites: ~
comps: ~ comps: ~
handler: ~ handler: default
- name: python3-pip - name: "python3-pip"
uri: ~ uri: ~
sigkey: ~ sigkey: ~
sources: ~ sources: ~
types: ~ types: ~
suites: ~ suites: ~
comps: ~ comps: ~
handler: ~ handler: default
- name: python3-doc - name: "python3-doc"
uri: ~ uri: ~
sigkey: ~ sigkey: ~
sources: ~ sources: ~
types: ~ types: ~
suites: ~ suites: ~
comps: ~ comps: ~
handler: ~ handler: default
- name: golang - name: golang
uri: ~ uri: ~
sigkey: ~ sigkey: ~
@@ -539,15 +537,15 @@ pkgs:
types: ~ types: ~
suites: ~ suites: ~
comps: ~ comps: ~
handler: ~ handler: default
- name: golang-doc - name: "golang-doc"
uri: ~ uri: ~
sigkey: ~ sigkey: ~
sources: ~ sources: ~
types: ~ types: ~
suites: ~ suites: ~
comps: ~ comps: ~
handler: ~ handler: default
- name: hugo - name: hugo
uri: ~ uri: ~
sigkey: ~ sigkey: ~
@@ -555,39 +553,47 @@ pkgs:
types: ~ types: ~
suites: ~ suites: ~
comps: ~ comps: ~
handler: ~ handler: default
- name: yt-dlp - name: "yt-dlp"
uri: ~ uri: ~
sigkey: ~ sigkey: ~
sources: ~ sources: ~
types: ~ types: ~
suites: ~ suites: ~
comps: ~ comps: ~
handler: ~ handler: default
- name: syncthing-discosrv - name: "syncthing-discosrv"
uri: ~ uri: ~
sigkey: ~ sigkey: ~
sources: ~ sources: ~
types: ~ types: ~
suites: ~ suites: ~
comps: ~ comps: ~
handler: ~ handler: default
- name: syncthing-relaysrv - name: "syncthing-relaysrv"
uri: ~ uri: ~
sigkey: ~ sigkey: ~
sources: ~ sources: ~
types: ~ types: ~
suites: ~ suites: ~
comps: ~ comps: ~
handler: ~ handler: default
- name: syncthing-relaysrv - name: burp
uri: ~ uri: ~
sigkey: ~ sigkey: ~
sources: ~ sources: ~
types: ~ types: ~
suites: ~ suites: ~
comps: ~ comps: ~
handler: ~ handler: default
- name: rsync
uri: ~
sigkey: ~
sources: ~
types: ~
suites: ~
comps: ~
handler: default
- name: rclone - name: rclone
uri: ~ uri: ~
sigkey: ~ sigkey: ~
@@ -595,39 +601,63 @@ pkgs:
types: ~ types: ~
suites: ~ suites: ~
comps: ~ comps: ~
handler: ~ handler: default
- name: aria2 - name: proftpd
uri: ~ uri: ~
sigkey: ~ sigkey: ~
sources: ~ sources: ~
types: ~ types: ~
suites: ~ suites: ~
comps: ~ comps: ~
handler: ~ handler: default
- name: mopidy - name: reprepro
uri: ~ uri: ~
sigkey: ~ sigkey: ~
sources: ~ sources: ~
types: ~ types: ~
suites: ~ suites: ~
comps: ~ comps: ~
handler: ~ handler: default
- name: mopidy-mpd - name: erlang
uri: ~ uri: ~
sigkey: ~ sigkey: ~
sources: ~ sources: ~
types: ~ types: ~
suites: ~ suites: ~
comps: ~ comps: ~
handler: ~ handler: default
- name: minidlna - name: "erlang-hex"
uri: ~ uri: ~
sigkey: ~ sigkey: ~
sources: ~ sources: ~
types: ~ types: ~
suites: ~ suites: ~
comps: ~ 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
- name: "libsecret-1-dev"
uri: ~
sigkey: ~
sources: ~
types: ~
suites: ~
comps: ~
handler: default
# <dict[<str>:<dict>]> representing package groups installed by shell scripts # <dict[<str>:<dict>]> representing package groups installed by shell scripts
script: script:
# <list[<dict>]> representing user-level or supplemental shell script installations # <list[<dict>]> representing user-level or supplemental shell script installations
@@ -656,12 +686,12 @@ pkgs:
archive: archive:
# <list[<dict>]> representing user-level or supplemental source archives # <list[<dict>]> representing user-level or supplemental source archives
userspace: userspace:
# - name: surge - name: surge
# src: "https://github.com/SurgeDM/Surge/releases/download/v0.8.6/Surge_0.8.6_linux_amd64.tar.gz" src: "https://github.com/SurgeDM/Surge/releases/download/v0.8.6/Surge_0.8.6_linux_amd64.tar.gz"
# deploy: ~ deploy: ~
# pre: ~ pre: ~
# post: ~ post: ~
# handler: surge handler: surge
- name: nvm - name: nvm
src: "https://nodejs.org/dist/v24.16.0/node-v24.16.0-linux-x64.tar.xz" src: "https://nodejs.org/dist/v24.16.0/node-v24.16.0-linux-x64.tar.xz"
deploy: ~ deploy: ~
@@ -676,7 +706,7 @@ pkgs:
handler: difftastic handler: difftastic
# <dict[<str>:<dict>]> representing package groups installed from source git repositories # <dict[<str>:<dict>]> representing package groups installed from source git repositories
git_repos: git_repos:
# userspace: userspace:
# # @TODO use below to build Podman container instead, to deploy with podman-compose # # @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/ # # @NOTE https://github.com/papis/papis and https://papis.readthedocs.io/en/latest/
# - name: papis # - name: papis
@@ -686,6 +716,41 @@ pkgs:
# pre: ~ # pre: ~
# post: ~ # post: ~
# handler: false # 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 - name: quartz
src: "https://github.com/jackyzha0/quartz.git" src: "https://github.com/jackyzha0/quartz.git"
branch: v5.0.0 branch: v5.0.0
-33
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:
+23 -6
View File
@@ -1,14 +1,15 @@
# @NOTE run 'ansible-playbook' command on this using 'sudo' # @NOTE run 'ansible-playbook' command on this using 'sudo'
- name: Initialize homeserver - name: Initialize homeserver
hosts: "{{ chosen_host | default('armitage') }}" hosts: "{{ chosen_host | default('staging1.test') }}"
remote_user: root remote_user: root
vars: vars:
harden: true harden: true
vars_files: vars_files:
# - vars/certbot_settings@homeserver.yml # REQUIRED
- vars/local_facts.yml # REQUIRED - vars/local_facts.yml # REQUIRED
- vars/vim_settings.yml # REQUIRED - vars/wireguard_settings.yml # REQUIRED
- vars/tail_net.yml - vars/podpose_settings.yml # REQUIRED
- vars/crowdsec.yml - vars/surge_settings.yml
- vars/users@{{ inventory_hostname | default('homeserver') }}.yml - vars/users@{{ inventory_hostname | default('homeserver') }}.yml
- vars/config@{{ inventory_hostname | default('homeserver') }}.yml - vars/config@{{ inventory_hostname | default('homeserver') }}.yml
tasks: tasks:
@@ -33,12 +34,28 @@
- name: Updating hostname - name: Updating hostname
become: true become: true
ansible.builtin.hostname: ansible.builtin.hostname:
name: "{{ inventory_hostname }}" name: "{{ fqdn | default(inventory_hostname) }}"
- name: Updating hosts file
become: true
ansible.builtin.lineinfile:
path: /etc/hosts
regexp: "^127\\.0\\.1\\.1"
line: "127.0.1.1 {{ fqdn | default(inventory_hostname) }}"
insertbefore: BOF
state: present
- name: Updating host icon name - name: Updating host icon name
become: true become: true
ansible.builtin.command: ansible.builtin.command:
cmd: "hostnamectl set-icon-name computer-server" 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 - name: Rebooting machine for hostname change
become: true become: true
ansible.builtin.reboot: ansible.builtin.reboot:
msg: "Rebooting machine" msg: "Rebooting machine.."
connect_timeout: 0
test_command: ~
ignore_errors: true
+64 -10
View File
@@ -1,15 +1,16 @@
# @NOTE run 'ansible-playbook' command on this using 'sudo' # @NOTE run 'ansible-playbook' command on this using 'sudo'
- name: Initialize VPS - name: Initialize VPS
# hosts: sukaato hosts: "{{ chosen_host | default('staging0.test') }}"
hosts: "{{ chosen_host | default('sukaato') }}" remote_user: "{{ chosen_user | default('root') }}"
remote_user: root
vars: vars:
harden: true harden: true
vars_files: vars_files:
- vars/local_facts.yml # REQUIRED - vars/local_facts.yml # REQUIRED
- vars/vim_settings.yml # REQUIRED - vars/vpn_settings.yml # REQUIRED
- vars/tail_net.yml - vars/wireguard_settings.yml # REQUIRED
- vars/crowdsec.yml - vars/headscale_settings.yml # REQUIRED
- vars/podpose_settings.yml # REQUIRED
- vars/certbot_settings@vps.yml # REQUIRED
- vars/users@{{ inventory_hostname | default('vps') }}.yml - vars/users@{{ inventory_hostname | default('vps') }}.yml
- vars/config@{{ inventory_hostname | default('vps') }}.yml - vars/config@{{ inventory_hostname | default('vps') }}.yml
tasks: tasks:
@@ -31,15 +32,68 @@
ansible.builtin.include_role: ansible.builtin.include_role:
name: init-server name: init-server
tasks_from: ssh-users tasks_from: ssh-users
- name: Update hostname - name: Flushing handlers
ansible.builtin.meta: flush_handlers
- name: Updating hostname
become: true become: true
ansible.builtin.hostname: ansible.builtin.hostname:
name: "{{ inventory_hostname }}" name: "{{ fqdn | default(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 {{ fqdn | default(inventory_hostname) }}"
insertbefore: BOF
state: present
- name: Updating host icon name
become: true become: true
ansible.builtin.command: ansible.builtin.command:
cmd: "hostnamectl set-icon-name computer-server" 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.
- name: Ensuring user has read prior message regarding upcoming reboot
ansible.builtin.pause:
- name: Rebooting machine for hostname change - name: Rebooting machine for hostname change
become: true become: true
ansible.builtin.reboot: ansible.builtin.reboot:
msg: "Rebooting machine" msg: "Rebooting machine.."
connect_timeout: 0
test_command: ~
+73
View File
@@ -0,0 +1,73 @@
[project]
name = "skato-ansible"
version = "0.1.0"
requires-python = ">=3.13"
dependencies = [
"ansible==13.7.0",
"ansible-builder==3.1.1",
"ansible-compat==26.3.0",
"ansible-core==2.20.6",
"ansible-lint==26.4.0",
"ansible-navigator==26.4.0",
"ansible-runner==2.4.3",
"ansible-specdoc==0.0.20",
"appdirs==1.4.4",
"attrs==26.1.0",
"baron==0.10.1",
"bindep==2.14.0",
"black==26.5.1",
"bracex==2.6",
"certifi==2026.5.20",
"cffi==2.0.0",
"charset-normalizer==3.4.7",
"click==8.4.1",
"cryptography==48.0.0",
"deprecated==1.3.1",
"distro==1.9.0",
"enrich==1.2.7",
"filelock==3.29.0",
"idna==3.16",
"jinja2==3.1.6",
"jsonschema==4.26.0",
"jsonschema-specifications==2025.9.1",
"linode-api4==5.44.0",
"lockfile==0.12.2",
"markdown-it-py==4.2.0",
"markupsafe==3.0.3",
"mdurl==0.1.2",
"molecule==26.4.0",
"mypy-extensions==1.1.0",
"onigurumacffi==1.5.0",
"packaging==26.2",
"parsley==1.3",
"passlib==1.7.4",
"pathspec==1.0.4",
"pbr==7.0.3",
"pexpect==4.9.0",
"pip==25.1.1",
"platformdirs==4.9.6",
"pluggy==1.6.0",
"polling==0.3.2",
"ptyprocess==0.7.0",
"pycparser==3.0",
"pygments==2.20.0",
"python-daemon==3.1.2",
"pytokens==0.4.1",
"pyyaml==6.0.3",
"redbaron==0.9.2",
"referencing==0.37.0",
"requests==2.34.2",
"resolvelib==1.2.1",
"rich==15.0.0",
"rpds-py==0.30.0",
"rply==0.7.8",
"ruamel-yaml==0.19.1",
"ruamel-yaml-clib==0.2.15",
"setuptools==82.0.1",
"subprocess-tee==0.4.2",
"tzdata==2026.2",
"urllib3==2.7.0",
"wcmatch==10.1",
"wrapt==2.2.1",
"yamllint==1.38.0",
]
-65
View File
@@ -1,65 +0,0 @@
ansible==13.7.0
ansible-builder==3.1.1
ansible-compat==26.3.0
ansible-core==2.20.6
ansible-lint==26.4.0
ansible-navigator==26.4.0
ansible-runner==2.4.3
ansible-specdoc==0.0.20
appdirs==1.4.4
attrs==26.1.0
baron==0.10.1
bindep==2.14.0
black==26.5.1
bracex==2.6
certifi==2026.5.20
cffi==2.0.0
charset-normalizer==3.4.7
click==8.4.1
cryptography==48.0.0
deprecated==1.3.1
distro==1.9.0
enrich==1.2.7
filelock==3.29.0
idna==3.16
jinja2==3.1.6
jsonschema==4.26.0
jsonschema-specifications==2025.9.1
linode-api4==5.44.0
lockfile==0.12.2
markdown-it-py==4.2.0
markupsafe==3.0.3
mdurl==0.1.2
molecule==26.4.0
mypy-extensions==1.1.0
onigurumacffi==1.5.0
packaging==26.2
parsley==1.3
pathspec==1.0.4
pbr==7.0.3
pexpect==4.9.0
platformdirs==4.9.6
pluggy==1.6.0
polling==0.3.2
ptyprocess==0.7.0
pycparser==3.0
pygments==2.20.0
python-daemon==3.1.2
pytokens==0.4.1
pyyaml==6.0.3
redbaron==0.9.2
referencing==0.37.0
requests==2.34.2
resolvelib==1.2.1
rich==15.0.0
rpds-py==0.30.0
rply==0.7.8
ruamel-yaml==0.19.1
ruamel-yaml-clib==0.2.15
setuptools==82.0.1
subprocess-tee==0.4.2
tzdata==2026.2
urllib3==2.7.0
wcmatch==10.1
wrapt==2.2.1
yamllint==1.38.0
@@ -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
@@ -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
@@ -0,0 +1,14 @@
[Unit]
Description=dsnet
After=network-online.target
Wants=network-online.target
[Service]
Type=oneshot
ExecStart=/usr/bin/dsnet up
ExecStop=/usr/bin/dsnet down
RemainAfterExit=yes
ExecReload=/usr/bin/dsnet sync
[Install]
WantedBy=default.target
@@ -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
@@ -0,0 +1,14 @@
[Unit]
Description=thrunet
After=network-online.target
Wants=network-online.target
[Service]
Type=oneshot
ExecStart=/usr/local/bin/dsnet-forward.sh start
ExecStop=/usr/local/bin/dsnet-forward.sh stop
RemainAfterExit=yes
# ExecReload=/usr/bin/dsnet sync
[Install]
WantedBy=default.target
@@ -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"
@@ -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

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

+20 -8
View File
@@ -5,19 +5,31 @@
ansible.builtin.debug: ansible.builtin.debug:
msg: "No post-installaton or additional installation steps needed--continuing..." msg: "No post-installaton or additional installation steps needed--continuing..."
listen: default listen: default
- name: Setting up ViM
ansible.builtin.include_tasks:
file: tasks/contingent/pkg/vim.yml
listen: vim
- name: Setting up Headscale
ansible.builtin.include_tasks:
file: tasks/contingent/pkg/headscale.yml
listen: headscale
- name: Setting up Git - name: Setting up Git
ansible.builtin.include_tasks: ansible.builtin.include_tasks:
file: tasks/contingent/pkg/git.yml file: tasks/contingent/pkg/git.yml
listen: git listen: git
- name: Setting up Certbot
ansible.builtin.include_tasks:
file: tasks/contingent/pkg/certbot.yml
listen: certbot
- name: Setting up TOR - name: Setting up TOR
ansible.builtin.include_tasks: ansible.builtin.include_tasks:
file: tasks/contingent/pkg/tor.yml file: tasks/contingent/pkg/tor.yml
listen: tor 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
listen: crowdsec
- name: Setting up Headscale
ansible.builtin.include_tasks:
file: tasks/contingent/pkg/headscale.yml
listen: headscale
- name: Setting up DSNet
ansible.builtin.include_tasks:
file: tasks/contingent/pkg/dsnet.yml
listen: dsnet
+42 -6
View File
@@ -5,6 +5,10 @@
ansible.builtin.debug: ansible.builtin.debug:
msg: "No post-installaton or additional installation steps needed--continuing..." msg: "No post-installaton or additional installation steps needed--continuing..."
listen: default listen: default
- name: Setting up ViM
ansible.builtin.include_tasks:
file: tasks/contingent/pkg/vim.yml
listen: vim
- name: Settng up NeoViM - name: Settng up NeoViM
ansible.builtin.include_tasks: ansible.builtin.include_tasks:
file: tasks/contingent/pkg/neovim.yml file: tasks/contingent/pkg/neovim.yml
@@ -33,15 +37,47 @@
ansible.builtin.include_tasks: ansible.builtin.include_tasks:
file: tasks/contingent/pkg/uv.yml file: tasks/contingent/pkg/uv.yml
listen: uv listen: uv
- name: Setting up Radicle - name: Setting up Podman
ansible.builtin.include_tasks: ansible.builtin.include_tasks:
file: tasks/contingent/pkg/radicle.yml file: tasks/contingent/pkg/podman.yml
listen: radicle listen: podman
- name: Setting up Surge - name: Setting up Podman Compose sources
ansible.builtin.include_tasks: ansible.builtin.include_tasks:
file: tasks/contingent/pkg/surge.yml file: tasks/contingent/pkg/skato_compose.yml
listen: surge listen: skato_compose
- name: Setting up Quartz - name: Setting up Quartz
ansible.builtin.include_tasks: ansible.builtin.include_tasks:
file: tasks/contingent/pkg/quartz.yml file: tasks/contingent/pkg/quartz.yml
listen: quartz 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
@@ -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
@@ -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: |
{{ fqdn | default(inventory_hostname) }} IN A {{ ipify_public_ip }}
_acme-challenge.{{ fqdn | default(inventory_hostname) }} IN CNAME {{ fqdn | default(inventory_hostname) }}.acme.{{ fqdn | default(inventory_hostname) }}.
acme.{{ fqdn | default(inventory_hostname) }} IN NS ns.acme.{{ fqdn | default(inventory_hostname) }}.
ns.acme.{{ fqdn | default(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: []
@@ -1,7 +1,11 @@
- name: Preparing non-containerized Crowdsec
when: not crowdsec.containerized
block:
- name: Changing the address and port of the Crowdsec server - name: Changing the address and port of the Crowdsec server
become: true become: true
ansible.builtin.lineinfile: ansible.builtin.lineinfile:
path: /etc/crowdsec/config.yaml path: /etc/crowdsec/config.yaml
insertafter: EOF
regexp: "^ {4}listen_uri" regexp: "^ {4}listen_uri"
line: " listen_uri: localhost:{{ crowdsec.port }}" line: " listen_uri: localhost:{{ crowdsec.port }}"
owner: root owner: root
@@ -11,7 +15,8 @@
become: true become: true
ansible.builtin.lineinfile: ansible.builtin.lineinfile:
path: /etc/crowdsec/config.yaml path: /etc/crowdsec/config.yaml
regexp: "^ {2}listen_uri" regexp: "^ {2}listen_addr"
insertafter: EOF
line: " listen_addr: localhost" line: " listen_addr: localhost"
owner: root owner: root
group: root group: root
@@ -20,8 +25,41 @@
become: true become: true
ansible.builtin.lineinfile: ansible.builtin.lineinfile:
path: /etc/crowdsec/local_api_credentials.yaml path: /etc/crowdsec/local_api_credentials.yaml
insertafter: EOF
regexp: "^url" regexp: "^url"
line: "url: http://localhost:{{ crowdsec.port }}" line: "url: http://localhost:{{ crowdsec.port }}"
owner: root owner: root
group: root group: root
mode: "644" 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
@@ -5,6 +5,7 @@
cmd: "echo ~{{ ansible_user }}" cmd: "echo ~{{ ansible_user }}"
register: ansible_user_home register: ansible_user_home
- name: Linking binaries to directories already in PATH environment variable - name: Linking binaries to directories already in PATH environment variable
ignore_errors: true
ansible.builtin.file: ansible.builtin.file:
src: "{{ ansible_user_home.stdout }}/downloads/archives/released/difftastic/{{ item }}" src: "{{ ansible_user_home.stdout }}/downloads/archives/released/difftastic/{{ item }}"
dest: "{{ ansible_user_home.stdout }}/.local/bin/{{ item }}" dest: "{{ ansible_user_home.stdout }}/.local/bin/{{ item }}"
@@ -13,9 +14,10 @@
- difft - difft
- name: Linking binaries to directories already in PATH environment variable - name: Linking binaries to directories already in PATH environment variable
become: true become: true
ignore_errors: true
ansible.builtin.file: ansible.builtin.file:
src: "{{ ansible_user_home.stdout }}/downloads/archives/released/difftastic/{{ item }}" src: "{{ ansible_user_home.stdout }}/downloads/archives/released/difftastic/{{ item }}"
dest: "/usr/local/bin/{{ item }}" dest: "/usr/bin/{{ item }}"
state: link state: link
loop: loop:
- difft - difft
@@ -0,0 +1,159 @@
- 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: Initializing DSNet
become: true
ansible.builtin.command:
cmd: dsnet init
- name: Running DSNet VPN service interface
become: true
ansible.builtin.command:
cmd: dsnet up
- name: Creating a directory to house VPN service client configurations
ansible.builtin.file:
path: "{{ ansible_user_home.stdout }}/.wg/authorized_clients.d"
recurse: true
owner: "{{ ansible_user }}"
group: "{{ ansible_user }}"
mode: "755"
state: directory
- name: Adding peer device for DSNet VPN service interface
become: true
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.clients }}"
loop_control:
index_var: idx
- name: Changing ownership of consequent DSNet VPN service client configurations
ansible.builtin.file:
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.clients }}"
loop_control:
index_var: idx
- 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: Presenting DSNet VPN service client configuration files to control node for copying
when: data_method.user_input == "show"
block:
- 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.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 | 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: ((fqdn is undefined or fqdn == None) and item.name != fqdn) or 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: ((fqdn is defined and fqdn != None) and item.name == fqdn) or 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: "./roles/init-server/files/user/wg/containerized/{{ item.name }}{{ (idx | string) }}.conf"
flat: true
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 \"{{ 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
- name: Ensuring IP forwarding is allowed
become: true
ansible.posix.sysctl:
name: "net.{{ item }}.ip_forward"
value: "1"
sysctl_set: true
state: present
loop:
- ipv4
# - ipv6
- name: Creating SystemD unit for placing up DSNet interface
become: true
ansible.builtin.copy:
src: systemd/system/dsnet.service
dest: /etc/systemd/system/dsnet.service
owner: root
group: root
force: true
backup: true
- name: Reloading SystemD and enabling DSNet interface
become: true
ansible.builtin.systemd_service:
name: dsnet
enabled: true
daemon_reload: true
- name: Copying script for DSNet iptables rules
become: true
ansible.builtin.template:
src: usr/local/bin/dsnet-forward.sh.j2
dest: /usr/local/bin/dsnet-forward.sh
owner: root
group: root
mode: "755"
force: true
backup: true
- name: Creating SystemD unit for DSNet iptables rules
become: true
ansible.builtin.copy:
src: systemd/system/thrunet.service
dest: /etc/systemd/system/thrunet.service
owner: root
group: root
force: true
backup: true
- name: Reloading SystemD
become: true
ansible.builtin.systemd_service:
name: thrunet
daemon_reload: true
- 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
@@ -8,6 +8,23 @@
when: ansible_facts["system"] == "Linux" when: ansible_facts["system"] == "Linux"
ansible.builtin.shell: ansible.builtin.shell:
cmd: "echo {{ ansible_user }}" 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 - name: Configuring Headscale
become: true become: true
ansible.builtin.template: ansible.builtin.template:
@@ -18,6 +35,7 @@
mode: "644" mode: "644"
force: true force: true
backup: true backup: true
# validate: "headscale configtest"
- name: Starting SystemD service - name: Starting SystemD service
become: true become: true
ansible.builtin.systemd_service: ansible.builtin.systemd_service:
@@ -28,11 +46,55 @@
- name: Registering a headscale user - name: Registering a headscale user
become: true become: true
ansible.builtin.command: ansible.builtin.command:
# cmd: "headscale users create {{ item.username }} -d '{{ item.dname }}' -e '{{ item.email }}' -p '{{ pfp | default(default_pfp) }}'" cmd: "headscale users create {{ headscale.users.admin.username }} -d '{{ headscale.users.admin.dname }}' -e '{{ headscale.users.admin.email }}'"
cmd: "headscale users create {{ item.username }} -d '{{ item.dname }}' -e '{{ item.email }}'"
# vars:
# default_pfp: ~
register: headscale_registration register: headscale_registration
changed_when: changed_when:
- "'User created' in headscale_registration.stdout" - "'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
@@ -15,13 +15,14 @@
ansible.builtin.shell: ansible.builtin.shell:
cmd: "{{ ansible_user_home.stdout }}/.local/bin/julia-install.sh --yes" cmd: "{{ ansible_user_home.stdout }}/.local/bin/julia-install.sh --yes"
creates: "{{ ansible_user_home.stdout }}/.juliaup/bin" creates: "{{ ansible_user_home.stdout }}/.juliaup/bin"
async: 900
poll: 5
- name: Linking binaries to directories already in PATH environment variable - name: Linking binaries to directories already in PATH environment variable
become: true become: true
ignore_errors: true
ansible.builtin.file: ansible.builtin.file:
src: "{{ ansible_user_home.stdout }}/.juliaup/bin/{{ item }}" src: "{{ ansible_user_home.stdout }}/.juliaup/bin/{{ item }}"
dest: "/usr/local/bin/{{ item }}" dest: "/usr/bin/{{ item }}"
owner: root
group: root
state: link state: link
loop: loop:
- julia - julia
@@ -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
@@ -9,17 +9,6 @@
ansible.builtin.shell: ansible.builtin.shell:
cmd: "echo {{ ansible_user }}" cmd: "echo {{ ansible_user }}"
register: current_user register: current_user
- name: Copy system ViM configuration to home directory
become: true
ansible.builtin.copy:
src: /root/.vimrc
remote_src: true
dest: "{{ ansible_user_home.stdout }}/.vimrc"
owner: "{{ ansible_user }}"
group: "{{ ansible_user }}"
mode: "644"
force: true
backup: true
- name: Creating directory tree for NeoViM configuration files - name: Creating directory tree for NeoViM configuration files
ansible.builtin.file: ansible.builtin.file:
path: "{{ ansible_user_home.stdout }}/.config/nvim" path: "{{ ansible_user_home.stdout }}/.config/nvim"
+16 -23
View File
@@ -18,75 +18,68 @@
ansible.builtin.set_fact: ansible.builtin.set_fact:
prebuilt_nodepaths: "{{ prebuilt_nodes.files | map(attribute='path') }}" prebuilt_nodepaths: "{{ prebuilt_nodes.files | map(attribute='path') }}"
- name: Linking binaries to directories already in PATH environment variable - name: Linking binaries to directories already in PATH environment variable
ignore_errors: true
ansible.builtin.file: ansible.builtin.file:
src: "{{ item[0] }}/bin/{{ item[1] }}" src: "{{ item[0] }}/bin/{{ item[1] }}"
dest: "/usr/local/bin/{{ item[1] }}" dest: "/usr/bin/{{ item[1] }}"
owner: root
group: root
state: link state: link
loop: "{{ prebuilt_nodepaths | product(['node']) }}" loop: "{{ prebuilt_nodepaths | product(['node']) }}"
- name: Linking binaries to directories already in PATH environment variable - name: Linking binaries to directories already in PATH environment variable
ignore_errors: true
ansible.builtin.file: ansible.builtin.file:
src: "{{ item[0] }}/lib/node_modules/corepack/dist/{{ item[1] }}.js" src: "{{ item[0] }}/lib/node_modules/corepack/dist/{{ item[1] }}.js"
dest: "/usr/local/bin/{{ item[1] }}" dest: "/usr/bin/{{ item[1] }}"
owner: root
group: root
state: link state: link
loop: "{{ prebuilt_nodepaths | product(['corepack']) }}" loop: "{{ prebuilt_nodepaths | product(['corepack']) }}"
- name: Linking binaries to directories already in PATH environment variable - name: Linking binaries to directories already in PATH environment variable
ignore_errors: true
ansible.builtin.file: ansible.builtin.file:
src: "{{ item[0] }}/lib/node_modules/npm/bin/{{ item[1] }}-cli.js" src: "{{ item[0] }}/lib/node_modules/npm/bin/{{ item[1] }}-cli.js"
dest: "/usr/local/bin/{{ item[1] }}" dest: "/usr/bin/{{ item[1] }}"
owner: root
group: root
state: link state: link
loop: "{{ prebuilt_nodepaths | product(['npm','npx']) }}" loop: "{{ prebuilt_nodepaths | product(['npm','npx']) }}"
- name: Link includes to directories already recognized by system - name: Link includes to directories already recognized by system
ignore_errors: true
ansible.builtin.file: ansible.builtin.file:
src: "{{ item[0] }}/include/{{ item[1] }}" src: "{{ item[0] }}/include/{{ item[1] }}"
dest: "/usr/local/include/{{ item[1] }}" dest: "/usr/include/{{ item[1] }}"
owner: root
group: root
state: link state: link
loop: "{{ prebuilt_nodepaths | product(['node']) }}" loop: "{{ prebuilt_nodepaths | product(['node']) }}"
- name: Link requisite libraries to directories already recognized by system - name: Link requisite libraries to directories already recognized by system
ignore_errors: true
ansible.builtin.file: ansible.builtin.file:
src: "{{ item[0] }}/lib/{{ item[1] }}" src: "{{ item[0] }}/lib/{{ item[1] }}"
dest: "/usr/local/lib/{{ item[1] }}" dest: "/usr/lib/{{ item[1] }}"
owner: root
group: root
state: link state: link
loop: "{{ prebuilt_nodepaths | product(['node_modules']) }}" loop: "{{ prebuilt_nodepaths | product(['node_modules']) }}"
- name: Create man1 subdirectory for man pages - name: Create man1 subdirectory for man pages
ansible.builtin.file: ansible.builtin.file:
path: /usr/local/share/man/man1 path: /usr/share/man/man1
recurse: true recurse: true
owner: root owner: root
group: root group: root
mode: "644" mode: "644"
state: directory state: directory
- name: Link shared resources to directories already recognized by system - name: Link shared resources to directories already recognized by system
ignore_errors: true
ansible.builtin.file: ansible.builtin.file:
src: "{{ item[0] }}/share/man/man1/{{ item[1] }}.1" src: "{{ item[0] }}/share/man/man1/{{ item[1] }}.1"
dest: "/usr/local/share/man/man1/{{ item[1] }}.1" dest: "/usr/share/man/man1/{{ item[1] }}.1"
owner: root
group: root
state: link state: link
loop: "{{ prebuilt_nodepaths | product(['node']) }}" loop: "{{ prebuilt_nodepaths | product(['node']) }}"
- name: Create man1 subdirectory for man pages - name: Create man1 subdirectory for man pages
ansible.builtin.file: ansible.builtin.file:
path: /usr/local/share/doc path: /usr/share/doc
recurse: true recurse: true
owner: root owner: root
group: root group: root
mode: "644" mode: "644"
state: directory state: directory
- name: Link shared resources to directories already recognized by system - name: Link shared resources to directories already recognized by system
ignore_errors: true
ansible.builtin.file: ansible.builtin.file:
src: "{{ item[0] }}/share/doc/{{ item[1] }}" src: "{{ item[0] }}/share/doc/{{ item[1] }}"
dest: "/usr/local/share/doc/{{ item[1] }}" dest: "/usr/share/doc/{{ item[1] }}"
owner: root
group: root
state: link state: link
loop: "{{ prebuilt_nodepaths | product(['node']) }}" loop: "{{ prebuilt_nodepaths | product(['node']) }}"
# - name: Reboot machine for shell environment change # - name: Reboot machine for shell environment change
@@ -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
@@ -4,23 +4,180 @@
ansible.builtin.shell: ansible.builtin.shell:
cmd: "echo ~{{ ansible_user }}" cmd: "echo ~{{ ansible_user }}"
register: ansible_user_home 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 - name: Installing NodeJS dependencies of quartz software
become: true
become_user: "{{ current_user.stdout }}"
community.general.npm: community.general.npm:
path: "{{ ansible_user_home.stdout }}/repos/.foreign/quartz" path: "{{ ansible_user_home.stdout }}/repos/.foreign/quartz"
state: latest state: latest
- name: Configuring quartz software - name: Configuring quartz software
block: 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 - name: Initializing quartz website
become: true
become_user: "{{ current_user.stdout }}"
ansible.builtin.command: 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" 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 - name: Installing quartz plugins referenced in website template
become: true
become_user: "{{ current_user.stdout }}"
ansible.builtin.command: ansible.builtin.command:
argv:
- npx
- "-y"
- quartz
- plugin
- install
chdir: "{{ ansible_user_home.stdout }}/repos/.foreign/quartz" chdir: "{{ ansible_user_home.stdout }}/repos/.foreign/quartz"
cmd: npx quartz plugin install --from-config - name: Starting quartz site web server
# - name: Starting quartz site web server become: true
# ansible.builtin.command: become_user: "{{ current_user.stdout }}"
# chdir: "{{ ansible_user_home.stdout }}/repos/.foreign/quartz" ansible.builtin.command:
# cmd: npx quartz build --serve argv:
# register: stdout - npx
# changed_when: stdout - "-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
@@ -15,13 +15,16 @@
ansible.builtin.shell: ansible.builtin.shell:
cmd: "{{ ansible_user_home.stdout }}/.local/bin/radicle-install.sh" cmd: "{{ ansible_user_home.stdout }}/.local/bin/radicle-install.sh"
creates: "{{ ansible_user_home.stdout }}/.radicle" creates: "{{ ansible_user_home.stdout }}/.radicle"
async: 600
poll: 5
- name: Bootstrapping Radicle - name: Bootstrapping Radicle
become: true become: true
block: block:
- name: Linking binaries to directories already in PATH environment variable - name: Linking binaries to directories already in PATH environment variable
ignore_errors: true
ansible.builtin.file: ansible.builtin.file:
src: "{{ ansible_user_home.stdout }}/.radicle/bin/{{ item }}" src: "{{ ansible_user_home.stdout }}/.radicle/bin/{{ item }}"
dest: "/usr/local/bin/{{ item }}" dest: "/usr/bin/{{ item }}"
state: link state: link
loop: loop:
- rad - rad
@@ -29,16 +32,17 @@
- git-remote-rad - git-remote-rad
- name: Create man1 subdirectory for man pages - name: Create man1 subdirectory for man pages
ansible.builtin.file: ansible.builtin.file:
path: /usr/local/share/man/man1 path: /usr/share/man/man1
recurse: true recurse: true
owner: root owner: root
group: root group: root
mode: "644" mode: "644"
state: directory state: directory
- name: Link manpages to Linux manpage directories - name: Link manpages to Linux manpage directories
ignore_errors: true
ansible.builtin.file: ansible.builtin.file:
src: "{{ ansible_user_home.stdout }}/.radicle/man/man1/{{ item }}.1" src: "{{ ansible_user_home.stdout }}/.radicle/man/man1/{{ item }}.1"
dest: "/usr/local/share/man/man1/{{ item }}.1" dest: "/usr/share/man/man1/{{ item }}.1"
state: link state: link
loop: loop:
- rad - rad
@@ -15,11 +15,14 @@
ansible.builtin.shell: ansible.builtin.shell:
cmd: "{{ ansible_user_home.stdout }}/.local/bin/rustup-install.sh -yq" cmd: "{{ ansible_user_home.stdout }}/.local/bin/rustup-install.sh -yq"
creates: "{{ ansible_user_home.stdout }}/.cargo/bin" creates: "{{ ansible_user_home.stdout }}/.cargo/bin"
async: 600
poll: 5
- name: Linking binaries to directories already in PATH environment variable - name: Linking binaries to directories already in PATH environment variable
become: true become: true
ignore_errors: true
ansible.builtin.file: ansible.builtin.file:
src: "{{ ansible_user_home.stdout }}/.cargo/bin/{{ item }}" src: "{{ ansible_user_home.stdout }}/.cargo/bin/{{ item }}"
dest: "/usr/local/bin/{{ item }}" dest: "/usr/bin/{{ item }}"
state: link state: link
loop: loop:
- rustup - rustup
@@ -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
@@ -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
@@ -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
@@ -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: ((fqdn is defined and fqdn != None) and item.name == fqdn) or 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: ((fqdn is defined and fqdn != None) and item.name == fqdn) or 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)
@@ -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
@@ -6,16 +6,31 @@
register: ansible_user_home register: ansible_user_home
- name: Linking binaries to directories already in PATH environment variable - name: Linking binaries to directories already in PATH environment variable
become: true become: true
ignore_errors: true
ansible.builtin.file: ansible.builtin.file:
src: "{{ ansible_user_home.stdout }}/downloads/archives/released/surge/{{ item }}" src: "{{ ansible_user_home.stdout }}/downloads/archives/released/surge/{{ item }}"
dest: "/usr/local/bin/{{ item }}" dest: "/usr/bin/{{ item }}"
state: link state: link
loop: loop:
- surge - surge
- name: Starting to spin up the Surge service
when: surge.service.enabled and not surge.containerized
block:
- name: Installing accompanying complementary Surge system service - name: Installing accompanying complementary Surge system service
become: true
ansible.builtin.command: ansible.builtin.command:
cmd: surge service install 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 - name: Acquiring API token for remote Surge service control
become: true
ansible.builtin.command: ansible.builtin.command:
cmd: surge token cmd: surge token
register: surge_token register: surge_token
@@ -24,35 +39,48 @@
prompt: "Type \"fetch\" to get the Surge API token, or \"show\" to see it for manual copying instead" prompt: "Type \"fetch\" to get the Surge API token, or \"show\" to see it for manual copying instead"
echo: true echo: true
register: data_method register: data_method
- name: Choosing to present Surge API token to Control Node
when: data_method.user_input == "show"
block:
- name: Presenting Surge API token to Control Node - name: Presenting Surge API token to Control Node
when: data_method.user_input == "show"
ansible.builtin.debug: ansible.builtin.debug:
msg: "Make sure to store the following API token for Surge:\n {{ surge_token.stdout }}" msg: "Make sure to store the following API token for Surge:\n {{ surge_token.stdout }}"
- name: Giving opportunity to manually copy Surge API token - name: Giving opportunity to manually copy Surge API token
when: data_method.user_input == "show"
ansible.builtin.pause: 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 - name: Creating temporary file on managed node that stores Surge API token
become: true become: true
when: data_method.user_input == "fetch"
ansible.builtin.copy: ansible.builtin.copy:
content: "{{ surge_token.stdout }}" content: "{{ surge_token.stdout }}"
dest: /tmp/surge.token dest: /tmp/surge.secret
owner: "{{ ansible_user }}" owner: "{{ ansible_user }}"
group: "{{ ansible_user }}" group: "{{ ansible_user }}"
mode: "644" mode: "644"
state: touch
register: surge_token register: surge_token
- name: Placing Surge API token into file on control node - name: Placing Surge API token into file on control node
when: data_method.user_input == "fetch"
ansible.builtin.fetch: ansible.builtin.fetch:
src: "{{ surge_token.dest }}" src: "{{ surge_token.dest }}"
dest: "/var/tmp/{{ inventory_hostname }}/surge.token" 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 flat: true
- name: Informing control node of acquired files - name: Informing control node of acquired files
when: data_method.user_input == "fetch"
ansible.builtin.debug: 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 - name: Giving control node user time to read the aforementiioned message
when: data_method.user_input == "fetch"
ansible.builtin.pause: 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
@@ -15,11 +15,14 @@
ansible.builtin.shell: ansible.builtin.shell:
cmd: "{{ ansible_user_home.stdout }}/.local/bin/uv-install.sh" cmd: "{{ ansible_user_home.stdout }}/.local/bin/uv-install.sh"
creates: "{{ ansible_user_home.stdout }}/.local/bin/uv" creates: "{{ ansible_user_home.stdout }}/.local/bin/uv"
async: 600
poll: 5
- name: Linking binaries to directories already in PATH environment variable - name: Linking binaries to directories already in PATH environment variable
become: true become: true
ignore_errors: true
ansible.builtin.file: ansible.builtin.file:
src: "{{ ansible_user_home.stdout }}/.local/bin/{{ item }}" src: "{{ ansible_user_home.stdout }}/.local/bin/{{ item }}"
dest: "/usr/local/bin/{{ item }}" dest: "/usr/bin/{{ item }}"
state: link state: link
loop: loop:
- uv - uv
@@ -19,6 +19,7 @@
recurse: true recurse: true
owner: "{{ ansible_user }}" owner: "{{ ansible_user }}"
group: "{{ ansible_user }}" group: "{{ ansible_user }}"
mode: "755"
state: directory state: directory
loop: loop:
- autoload - autoload
@@ -30,12 +31,13 @@
become_user: "{{ current_user.stdout }}" become_user: "{{ current_user.stdout }}"
ansible.builtin.uri: ansible.builtin.uri:
url: "https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim" url: "https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim"
dest: "{{ ansible_user_home.stdout }}/.vim/autoload/" dest: "{{ ansible_user_home.stdout }}/.vim/autoload/plug.vim"
owner: "{{ ansible_user }}" owner: "{{ ansible_user }}"
group: "{{ ansible_user }}" group: "{{ ansible_user }}"
force: true force: true
mode: "644" mode: "644"
follow_redirects: safe follow_redirects: safe
timeout: 300
- name: Configuring ViM - name: Configuring ViM
become: true become: true
become_user: "{{ current_user.stdout }}" become_user: "{{ current_user.stdout }}"
@@ -46,4 +48,9 @@
group: "{{ ansible_user }}" group: "{{ ansible_user }}"
force: true force: true
backup: true backup: true
# @TODO run command to make sure plugins referenced in 'vimrc' are installed - name: Informing user of need to manually run PlugInstall in ViM
ansible.builtin.debug:
msg: "Make sure to run \":PlugInstall\" the first time you open/use ViM"
- name: Pausing to ensure user has read message about needed manual PlugInstall execution for ViM
ansible.builtin.pause:
seconds: 30
@@ -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
+24 -9
View File
@@ -87,13 +87,6 @@
# @TODO uncomment below before continuing with testing previous task # @TODO uncomment below before continuing with testing previous task
# - name: Premature end of play # - name: Premature end of play
# ansible.builtin.meta: end_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 - name: Registering a package source
when: item.sources != None when: item.sources != None
ansible.builtin.deb822_repository: ansible.builtin.deb822_repository:
@@ -108,6 +101,10 @@
- name: Updating package cache - name: Updating package cache
ansible.builtin.apt: ansible.builtin.apt:
update_cache: true update_cache: true
- name: Upgrading
ansible.builtin.apt:
upgrade: dist
autoremove: true
- name: Installing a local package in managed node - name: Installing a local package in managed node
when: item.uri != None when: item.uri != None
ansible.builtin.apt: ansible.builtin.apt:
@@ -121,6 +118,8 @@
name: "{{ item.name }}" name: "{{ item.name }}"
state: present state: present
notify: "{{ item.handler | default('default') }}" notify: "{{ item.handler | default('default') }}"
async: 600
poll: 5
loop: "{{ ((pkgs.mngr.core | default([]))) | rejectattr('uri', 'search', '\\.deb$') }}" loop: "{{ ((pkgs.mngr.core | default([]))) | rejectattr('uri', 'search', '\\.deb$') }}"
tags: tags:
- get_mngr_pkgs - get_mngr_pkgs
@@ -137,7 +136,8 @@
owner: "{{ ansible_user }}" owner: "{{ ansible_user }}"
group: "{{ ansible_user }}" group: "{{ ansible_user }}"
force: true force: true
mode: "744" mode: "755"
timeout: 300
notify: "{{ ((pkgs.script.core | default([])))[idx].handler | default('default') }}" notify: "{{ ((pkgs.script.core | default([])))[idx].handler | default('default') }}"
loop: "{{ (pkgs.script.core | default([])) }}" loop: "{{ (pkgs.script.core | default([])) }}"
loop_control: loop_control:
@@ -206,7 +206,6 @@
dest: "{{ ansible_user_home.stdout }}/repos/.foreign/{{ item.name }}" dest: "{{ ansible_user_home.stdout }}/repos/.foreign/{{ item.name }}"
version: "{{ item.branch }}" version: "{{ item.branch }}"
clone: true clone: true
single_branch: true
notify: "{{ item.handler | default('default') }}" notify: "{{ item.handler | default('default') }}"
loop: "{{ (pkgs.git_repos.core | default([])) }}" loop: "{{ (pkgs.git_repos.core | default([])) }}"
register: installation_repos register: installation_repos
@@ -216,3 +215,19 @@
msg: Rebooting machine msg: Rebooting machine
tags: tags:
- get_git_pkgs - get_git_pkgs
- name: Installing software as pre-compiled binary
block:
- name: Grabbing software binary
become: true
ansible.builtin.get_url:
url: "{{ item.src }}"
dest: "/usr/bin/{{ item.name }}"
owner: root
group: root
mode: "755"
force: true
backup: true
notify: "{{ item.handler }}"
timeout: 300
loop: "{{ (pkgs.binaries.core | default([])) }}"
+20
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"
+21 -5
View File
@@ -2,6 +2,22 @@
--- ---
# tasks file for roles/init-vps # tasks file for roles/init-vps
# @NOTE server deployment method is based on task tags compiled herein # @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 - name: Finding SSH public keys for root
delegate_facts: true delegate_facts: true
delegate_to: localhost delegate_to: localhost
@@ -44,7 +60,7 @@
- name: Creating the VPS - name: Creating the VPS
linode.cloud.instance: linode.cloud.instance:
api_token: "{{ token | prompted_token.user_input }}" api_token: "{{ token | prompted_token.user_input }}"
label: "{{ instance }}" label: "{{ fqdn }}"
type: g6-standard-2 type: g6-standard-2
image: "{{ operating_system }}" image: "{{ operating_system }}"
disk_encryption: enabled disk_encryption: enabled
@@ -86,7 +102,7 @@
ansible.builtin.wait_for_connection: ansible.builtin.wait_for_connection:
delay: 20 delay: 20
timeout: 300 timeout: 300
loop: "{{ groups[instance] | default(hostvars[instance]) }}" loop: "{{ groups[fqdn] | default(hostvars[fqdn]) }}"
- name: Checking if that server has required operating system - name: Checking if that server has required operating system
delegate_to: "{{ item }}" delegate_to: "{{ item }}"
delegate_facts: true delegate_facts: true
@@ -94,7 +110,7 @@
when: ansible_facts["system"] != "Linux" and item is ansible.utils['ip_pref'] when: ansible_facts["system"] != "Linux" and item is ansible.utils['ip_pref']
ansible.builtin.fail: ansible.builtin.fail:
msg: Unsupported operating system found 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 - name: Checking if that server has required Linux distro
delegate_to: "{{ item }}" delegate_to: "{{ item }}"
delegate_facts: true 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'] when: ansible_facts["system"] == "Linux" and ansible_facts["os_family"] != "Debian" and item is ansible.utils['ip_pref']
ansible.builtin.fail: ansible.builtin.fail:
msg: Unsupported Linux distro found 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 - name: Providing authorized keys for server root account
delegate_to: "{{ item[0] }}" delegate_to: "{{ item[0] }}"
delegate_facts: true delegate_facts: true
@@ -112,6 +128,6 @@
user: "{{ ansible_user }}" user: "{{ ansible_user }}"
key: "{{ lookup('file', item[1]) }}" key: "{{ lookup('file', item[1]) }}"
state: present state: present
loop: "{{ (groups[instance] | default(hostvars[instance])) | product(root_pubkey_paths) }}" loop: "{{ (groups[fqdn] | default(hostvars[fqdn])) | product(root_pubkey_paths) }}"
tags: tags:
- lan - lan
@@ -88,13 +88,6 @@
# @TODO uncomment below before continuing with testing previous task # @TODO uncomment below before continuing with testing previous task
# - name: Premature end of play # - name: Premature end of play
# ansible.builtin.meta: end_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 - name: Registering a package source
when: item.sources != None when: item.sources != None
ansible.builtin.deb822_repository: ansible.builtin.deb822_repository:
@@ -109,6 +102,10 @@
- name: Updating package cache - name: Updating package cache
ansible.builtin.apt: ansible.builtin.apt:
update_cache: true update_cache: true
- name: Upgrading
ansible.builtin.apt:
upgrade: dist
autoremove: true
- name: Installing a local package in managed node - name: Installing a local package in managed node
when: item.uri != None when: item.uri != None
ansible.builtin.apt: ansible.builtin.apt:
@@ -122,6 +119,8 @@
name: "{{ item.name }}" name: "{{ item.name }}"
state: latest state: latest
notify: "{{ item.handler | default('default') }}" # @TODO create corresponding roles/init-vps handlers 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$') }}" loop: "{{ (pkgs.mngr.userspace | default([])) | rejectattr('uri', 'search', '\\.deb$') }}"
tags: tags:
- get_mngr_pkgs - get_mngr_pkgs
@@ -138,7 +137,8 @@
owner: "{{ ansible_user }}" owner: "{{ ansible_user }}"
group: "{{ ansible_user }}" group: "{{ ansible_user }}"
force: true force: true
mode: "744" mode: "755"
timeout: 300
notify: "{{ (pkgs.script.userspace | default([]))[idx].handler | default('default') }}" notify: "{{ (pkgs.script.userspace | default([]))[idx].handler | default('default') }}"
loop: "{{ (pkgs.script.userspace | default([])) }}" loop: "{{ (pkgs.script.userspace | default([])) }}"
loop_control: loop_control:
@@ -206,7 +206,6 @@
dest: "{{ ansible_user_home.stdout }}/repos/.foreign/{{ item.name }}" dest: "{{ ansible_user_home.stdout }}/repos/.foreign/{{ item.name }}"
version: "{{ item.branch }}" version: "{{ item.branch }}"
clone: true clone: true
single_branch: true
notify: "{{ item.handler | default('default') }}" notify: "{{ item.handler | default('default') }}"
loop: "{{ (pkgs.git_repos.userspace | default([])) }}" loop: "{{ (pkgs.git_repos.userspace | default([])) }}"
register: installation_repos register: installation_repos
@@ -216,5 +215,18 @@
msg: Rebooting machine msg: Rebooting machine
tags: tags:
- get_git_pkgs - get_git_pkgs
# @TODO add a reboot either here or in any of the handlers potentially notified from here in - name: Installing software as pre-compiled binary
# order to update environment (unless found better solution) block:
- name: Grabbing software binary
become: true
ansible.builtin.get_url:
url: "{{ item.src }}"
dest: "/usr/bin/{{ item.name }}"
owner: root
group: root
mode: "755"
force: true
backup: true
notify: "{{ item.handler }}"
timeout: 300
loop: "{{ (pkgs.binaries.userspace | default([])) }}"
@@ -10,13 +10,29 @@
# #
# https://myheadscale.example.com:443 # 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 # Address to listen to / bind to on the server
# #
# For production: # For production:
# listen_addr: 0.0.0.0:8080 # 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 # Address to listen to /metrics and /debug, you may want
# to keep this endpoint private to your internal network # to keep this endpoint private to your internal network
@@ -31,8 +47,8 @@ metrics_listen_addr: 127.0.0.1:9090
# #
# For production: # For production:
# grpc_listen_addr: 0.0.0.0:50443 # grpc_listen_addr: 0.0.0.0:50443
{% if tail.grpc.expose %} {% if headscale.grpc.expose %}
grpc_listen_addr: {{ '0.0.0.0' + tail.grpc.port }} grpc_listen_addr: {{ '0.0.0.0' + ':' + (headscale.grpc.port | string) }}
{% else %} {% else %}
grpc_listen_addr: 127.0.0.1:50443 grpc_listen_addr: 127.0.0.1:50443
{% endif %} {% endif %}
@@ -41,7 +57,7 @@ grpc_listen_addr: 127.0.0.1:50443
# mode. This is not recommended as the traffic will # mode. This is not recommended as the traffic will
# be unencrypted. Only enable if you know what you # be unencrypted. Only enable if you know what you
# are doing. # are doing.
{% if tail.grpc.secure %} {% if headscale.grpc.secure %}
grpc_allow_insecure: false grpc_allow_insecure: false
{% else %} {% else %}
grpc_allow_insecure: true 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. # # in the 'ssl' field. Refers to https://www.postgresql.org/docs/current/libpq-ssl.html Table 34.1.
# ssl: false # ssl: false
{% if mode == 'prod' or headscale.scheme == 'https' %}
### TLS configuration ### TLS configuration
# #
## Let's encrypt / ACME ## Let's encrypt / ACME
@@ -260,32 +277,42 @@ database:
# headscale supports automatically requesting and setting up # headscale supports automatically requesting and setting up
# TLS for a domain with Let's Encrypt. # TLS for a domain with Let's Encrypt.
# #
{% if certbot is undefined or certbot == None %}
# URL to ACME directory # 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 # Email to register with ACME provider
acme_email: "" # acme_email: ""
# Domain name to request a TLS certificate for: # Domain name to request a TLS certificate for:
tls_letsencrypt_hostname: "" # tls_letsencrypt_hostname: ""
# Path to store certificates and metadata needed by # Path to store certificates and metadata needed by
# letsencrypt # letsencrypt
# For production: # 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: # Type of ACME challenge to use, currently supported types:
# HTTP-01 or TLS-ALPN-01 # HTTP-01 or TLS-ALPN-01
# See: https://headscale.net/stable/ref/tls/ # 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 # When HTTP-01 challenge is chosen, letsencrypt must set up a
# verification endpoint, and it will be listening on: # verification endpoint, and it will be listening on:
# :http = port 80 # :http = port 80
tls_letsencrypt_listen: ":http" # tls_letsencrypt_listen: ":http"
{% else %}
{% if not certbot.containerized %}
## Use already defined certificates: ## Use already defined certificates:
tls_cert_path: "" tls_cert_path: {{ '/etc/letsencrypt/live/' + web_fqdn + '/fullchain.pem' }}
tls_key_path: "" 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: log:
# Valid log levels: panic, fatal, error, warn, info, debug, trace # 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. # `base_domain` must be a FQDN, without the trailing dot.
# The FQDN of the hosts will be # The FQDN of the hosts will be
# `hostname.base_domain` (e.g., _myhost.example.com_). # `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 # 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. # settings (default) and force the use of Headscale's DNS configuration.
@@ -343,7 +370,7 @@ dns:
# List of DNS servers to expose to clients. # List of DNS servers to expose to clients.
nameservers: nameservers:
global: {{ tail.magic_dns.nameservers }} global: {{ headscale.magic_dns.nameservers }}
# NextDNS (see https://tailscale.com/docs/integrations/nextdns). # NextDNS (see https://tailscale.com/docs/integrations/nextdns).
# "abc123" is example NextDNS ID, replace with yours. # "abc123" is example NextDNS ID, replace with yours.
@@ -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 %}
@@ -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 }}
@@ -0,0 +1,14 @@
CERTBOT_EMAIL="{{ certbot.email }}"
CERTBOT_AUTHENTICATOR={{ certbot.auth_method }}
SERVER_WEBROOT_PATH={{ ansible_user_home.stdout + "/srv/certbot." + (fqdn | default(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 %}
@@ -0,0 +1,27 @@
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
}
}
@@ -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"
@@ -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
@@ -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" }}
@@ -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 %>
}
}
@@ -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 %}
@@ -38,7 +38,7 @@ tasks:
populate_folders: populate_folders:
{% if download_mode == 'direct' %} {% if download_mode == 'direct' %}
proxy: proxy:
https: 'socks5://<< sox.hostname >>:<< sox.port >>' https: 'socks5://<< tor.proxy.hostname >>:<< tor.proxy.port >>'
{% endif %} {% endif %}
if: if:
- "'batch' in title.lower()": reject - "'batch' in title.lower()": reject
@@ -63,16 +63,19 @@ tasks:
template: limited_series template: limited_series
{% if flexget.download_mode == 'aria2' %} {% if flexget.download_mode == 'aria2' %}
aria2: aria2:
server: << aria.hostname >> server: << aria.rpc.hostname >>
port: << aria.port >> port: << aria.rpc.port >>
{% if aria.secret != None or aria.secret is defined %} {% if aria.rpc.secret != None and aria.rpc.secret is defined %}
secret: << aria.secret >> 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 %} {% endif %}
{% if aria.credentials != None or aria.credentials is defined %} {% if mode == 'prod' %}
username: << aria.credentials.username >> scheme: << aria.rpc.scheme >>
password: << aria.credentials.password >> {% else %}
scheme: http
{% endif %} {% endif %}
scheme: << aria.scheme >>
rpc_mode: json rpc_mode: json
rpc_path: jsonrpc rpc_path: jsonrpc
path: '~/downloads/media/vids/{{ series_name }}' path: '~/downloads/media/vids/{{ series_name }}'
@@ -85,21 +88,25 @@ tasks:
fap_queue: fap_queue:
{% if download_mode == 'direct' %} {% if download_mode == 'direct' %}
proxy: proxy:
https: 'socks5://<< sox.hostname >>:<< sox.port >>' https: 'socks5://<< tor.proxy.hostname >>:<< tor.proxy.port >>'
{% endif %} {% endif %}
template: porn_vids template: porn_vids
{% if flexget.download_mode == 'aria2' %} {% if flexget.download_mode == 'aria2' %}
aria2: aria2:
server: << aria.hostname >> server: << aria.rpc.hostname >>
port: << aria.port >> port: << aria.rpc.port >>
{% if aria.secret != None or aria.secret is defined %} {% if aria.rpc.secret != None and aria.rpc.secret is defined %}
secret: << aria.secret >> secret: << aria.rpc.secret >>
{% endif %} {% endif %}
{% if aria.credentials != None or aria.credentials is defined %} {% if aria.rpc.credentials != None and aria.rpc.credentials is defined %}
username: << aria.credentials.username >> username: << aria.rpc.credentials.username >>
password: << aria.credentials.password >> password: << aria.rpc.credentials.password >>
{% endif %}
{% if mode == 'prod' %}
scheme: << aria.rpc.scheme >>
{% else %}
scheme: http
{% endif %} {% endif %}
scheme: << aria.scheme >>
rpc_mode: json rpc_mode: json
rpc_path: jsonrpc rpc_path: jsonrpc
path: ~/downloads/.xxx/media/vids path: ~/downloads/.xxx/media/vids
@@ -112,21 +119,25 @@ tasks:
film_queue: film_queue:
{% if download_mode == 'direct' %} {% if download_mode == 'direct' %}
proxy: proxy:
https: 'socks5://<< sox.hostname >>:<< sox.port >>' https: 'socks5://<< tor.proxy.hostname >>:<< tor.proxy.port >>'
{% endif %} {% endif %}
template: feature_films template: feature_films
{% if flexget.download_mode == 'aria2' %} {% if flexget.download_mode == 'aria2' %}
aria2: aria2:
server: << aria.hostname >> server: << aria.rpc.hostname >>
port: << aria.port >> port: << aria.rpc.port >>
{% if aria.secret != None or aria.secret is defined %} {% if aria.rpc.secret != None or aria.rpc.secret is defined %}
secret: << aria.secret >> secret: << aria.rpc.secret >>
{% endif %} {% endif %}
{% if aria.credentials != None or aria.credentials is defined %} {% if aria.rpc.credentials != None or aria.rpc.credentials is defined %}
username: << aria.credentials.username >> username: << aria.rpc.credentials.username >>
password: << aria.credentials.password >> password: << aria.rpc.credentials.password >>
{% endif %}
{% if mode == 'prod' %}
scheme: << aria.rpc.scheme >>
{% else %}
scheme: http
{% endif %} {% endif %}
scheme: << aria.scheme >>
rpc_mode: json rpc_mode: json
rpc_path: jsonrpc rpc_path: jsonrpc
path: ~/downloads/media/vids path: ~/downloads/media/vids
@@ -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 %}
@@ -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.
@@ -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

@@ -0,0 +1,3 @@
MYSQL_DB_HOST=localhost
MYSQL_DB_USER={{ mysql.users.admin.username }}
MYSQL_DB_NAME={{ mysql.users.admin.databases.init.name }}
@@ -0,0 +1,3 @@
machine {{ source_code.host }}
login {{ source_code.user | default(source_code.ssh_user) }}
password {{ source_code.http_password | default(source_code.ssh_password) }}
@@ -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 %}
@@ -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
@@ -0,0 +1 @@
REDIS_PARAMS={{ "--requirepass " + redis.password + " --appendonly yes" }}
+1 -1
View File
@@ -56,7 +56,7 @@ set wildmenu
" Make wildmenu behave like similar to Bash completion. " Make wildmenu behave like similar to Bash completion.
set wildmode=list:longest 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. " There are certain files that we would never want to edit with Vim.
" Wildmenu will ignore files with these extensions. " Wildmenu will ignore files with these extensions.
@@ -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
+114 -67
View File
@@ -3,33 +3,36 @@ set -euo pipefail
# @TODO long-term, turn this simple bash script into more complex Python Click project # @TODO long-term, turn this simple bash script into more complex Python Click project
SKANSIBLE_SCRIPT_PATH=$(dirname "$0") SKANSIBLE_SCRIPT_PATH=$(dirname "$0")
SKANSIBLE_STAGE=1
SKANSIBLE_DEBUG=1 export ANSIBLE_FORCE_COLOR=True
SKANSIBLE_UNIT_TEST=1 SKANSIBLE_STAGE=0
DEFAULT_USER=senpai ANSIBLE_VERBOSITY=0
DEFAULT_SKANSIBLE_PLAY_HOST=vps SKANSIBLE_UNITTEST=False
SKANSIBLE_SSH_KEY_COLLECTION=(~/.ssh/ed25519\@staging ~/.ssh/ecdsa\@staging ~/.ssh/ed25519-37851076-sk\@staging ~/.ssh/ecdsa-37851076-sk\@staging) SKANSIBLE_MODE=prod
if [[ "$1" == "version" ]]; then if [[ "$1" == "version" ]]; then
echo "0.0.0" echo "26.07"
fi fi
if [[ "$1" == "show-defaults" ]]; then if [[ "$1" == "show-defaults" ]]; then
source "${SKANSIBLE_SCRIPT_PATH}/.env/bin/activate" source "${SKANSIBLE_SCRIPT_PATH}/.venv/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)" printf "Private SSH keys available throufh SSH agent: |\n%s\n" "$(ssh-add -l)"
fi fi
if [[ "$1" == "start-agent" ]]; then if [[ "$1" == "start-agent" ]]; then
source "${SKANSIBLE_SCRIPT_PATH}/.env/bin/activate" source "${SKANSIBLE_SCRIPT_PATH}/.venv/bin/activate"
eval "$(ssh-agent -s)" eval "$(ssh-agent -s)"
fi fi
if [[ "$1" == "list-agent" ]]; then
source "${SKANSIBLE_SCRIPT_PATH}/.venv/bin/activate"
ssh-add -l
fi
if [[ "$1" == "populate-agent" ]]; then if [[ "$1" == "populate-agent" ]]; then
shift 1 shift 1
source "${SKANSIBLE_SCRIPT_PATH}/.env/bin/activate" source "${SKANSIBLE_SCRIPT_PATH}/.venv/bin/activate"
if [[ "$1" == "all" ]]; then if [[ "$1" == "all" ]]; then
for SKANSIBLE_SSH_KEY in ~/.ssh/*; do for SKANSIBLE_SSH_KEY in ~/.ssh/*; do
@@ -44,91 +47,135 @@ if [[ "$1" == "populate-agent" ]]; then
*) ssh-add "${SKANSIBLE_SSH_KEY}";; *) ssh-add "${SKANSIBLE_SSH_KEY}";;
esac esac
done done
elif [[ "$1" == "select" ]]; 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
for key in "${SKANSIBLE_SSH_KEY_COLLECTION[@]}"; do for key in "${SKANSIBLE_SSH_KEY_COLLECTION[@]}"; do
ssh-add "$key" ssh-add "$key"
done done
elif [[ -z "$1" ]]; then
# @TODO improve by adding fuzzy querying or file finding pror
ssh-add "$1"
fi
fi
if [[ "$1" == "list-agent" ]]; then exit 0
source "${SKANSIBLE_SCRIPT_PATH}/.env/bin/activate"
ssh-add -l
fi fi
if [[ "$1" == "init" ]]; then if [[ "$1" == "init" ]]; then
shift 1 shift 1
source "${SKANSIBLE_SCRIPT_PATH}/.env/bin/activate" source "${SKANSIBLE_SCRIPT_PATH}/.venv/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 "htd:m:s:n:v:u:" opt; do
case $opt in case $opt in
h) Help "$1";; h) Help "init";;
s) SKANSIBLE_STAGE=0;; s) SKANSIBLE_STAGE="$OPTARG";;
d) SKANSIBLE_DEBUG=0;; n) SKANSIBLE_CONN_HOST="$OPTARG";;
t) SKANSIBLE_UNIT_TEST=0;; v) export ANSIBLE_VERBOSITY="$OPTARG";;
u) SKANSIBLE_CONN_USER="$OPTARG";; t) SKANSIBLE_UNITTEST=True;;
n) SKANSIBLE_CONN_HOSTS="$OPTARG";; u) export ANSIBLE_REMOTE_USER="$OPTARG";;
p) SKANSIBLE_PLAY_HOSTS="$OPTARG";; m) SKANSIBLE_MODE="$OPTARG";;
d) SKANSIBLE_FQDN="$OPTARG";;
*) echo "Err: Invalid option set"; exit 1;; *) echo "Err: Invalid option set"; exit 1;;
esac esac
done done
if [ -n "$SKANSIBLE_STAGE" ]; then
# SKANSIBLE_CONN_HOST=staging${SKANSIBLE_STAGE}.test
if [[ "$SKANSIBLE_STAGE" == 0 ]]; then if [[ "$SKANSIBLE_STAGE" == 0 ]]; then
SKANSIBLE_CONN_HOSTS=${SKANSIBLE_CONN_HOSTS:-${DEFAULT_SKANSIBLE_PLAY_HOST}}_test 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}" --extra-vars "fqdn=${SKANSIBLE_FQDN:-staging.test}" "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}" --extra-vars "fqdn=${SKANSIBLE_FQDN:-staging.test}" "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}" --extra-vars "fqdn=${SKANSIBLE_FQDN:-staging.test}" "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}" --extra-vars "fqdn=${SKANSIBLE_FQDN:-staging.test}" "init@${SKANSIBLE_PLAY_HOST}.yml"
fi
fi
else
if [[ -z "$SKANSIBLE_CONN_HOST" ]] && [[ -z "$SKANSIBLE_FQDN" ]]; then
echo "When not doing staging, chosen or preferred host must be made explicit as well as desired FQDN"
exit 1
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=prod" --extra-vars "fqdn=${SKANSIBLE_FQDN}" "init@${SKANSIBLE_PLAY_HOST}.yml"
fi
fi fi
if [[ "$SKANSIBLE_DEBUG" == 0 ]]; then exit 0
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"
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
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"
fi
fi
fi fi
if [[ "$1" == "bootstrap" ]]; then if [[ "$1" == "bootstrap" ]]; then
shift 1 shift 1
source "${SKANSIBLE_SCRIPT_PATH}/.env/bin/activate" source "${SKANSIBLE_SCRIPT_PATH}/.venv/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 "htd:m:s:n:v:u:" opt; do
case $opt in case $opt in
h) Help "$1";; h) Help "bootstrap";;
s) SKANSIBLE_STAGE=0;; s) SKANSIBLE_STAGE="$OPTARG";;
d) SKANSIBLE_DEBUG=0;; n) SKANSIBLE_CONN_HOST="$OPTARG";;
t) SKANSIBLE_UNIT_TEST=0;; v) export ANSIBLE_VERBOSITY=4;;
u) SKANSIBLE_CONN_USER="$OPTARG";; t) SKANSIBLE_UNITTEST=True;;
n) SKANSIBLE_CONN_HOSTS="$OPTARG";; u) export ANSIBLE_REMOTE_USER="$OPTARG";;
p) SKANSIBLE_PLAY_HOSTS="$OPTARG";; m) SKANSIBLE_MODE="$OPTARG";;
d) SKANSIBLE_FQDN="$OPTARG";;
*) echo "Err: Invalid option set"; exit 1;; *) echo "Err: Invalid option set"; exit 1;;
esac esac
done done
if [ -n "$SKANSIBLE_STAGE" ]; then
# SKANSIBLE_CONN_HOST=staging${SKANSIBLE_STAGE}.test
if [[ "$SKANSIBLE_STAGE" == 0 ]]; then if [[ "$SKANSIBLE_STAGE" == 0 ]]; then
SKANSIBLE_CONN_HOSTS=${SKANSIBLE_CONN_HOSTS:-${DEFAULT_SKANSIBLE_PLAY_HOST}}_test 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}" --extra-vars "fqdn=${SKANSIBLE_FQDN:-staging.test}" "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}" --extra-vars "fqdn=${SKANSIBLE_FQDN:-staging.test}" "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}" --extra-vars "fqdn=${SKANSIBLE_FQDN:-staging.test}" "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}" --extra-vars "fqdn=${SKANSIBLE_FQDN:-staging.test}" "administrate@${SKANSIBLE_PLAY_HOST}.yml"
fi
fi
else
if [[ -z "$SKANSIBLE_CONN_HOST" ]]; then
echo "When not doing staging, chosen or preferred host must be made explicit as well as desired FQDN"
exit 1
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=prod" --extra-vars "fqdn=${SKANSIBLE_FQDN}" "administrate@${SKANSIBLE_PLAY_HOST}.yml"
fi
fi fi
if [[ "$SKANSIBLE_DEBUG" == 0 ]]; then exit 0
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"
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
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"
fi
fi
fi fi
+16
View File
@@ -0,0 +1,16 @@
Vagrant.configure("2") do |config|
config.vm.box = "debian/trixie64"
config.vm.hostname = "staging0.test"
config.vm.network "private_network", ip: "192.168.122.234", bridge: "virbr0", ipv6: true
config.vm.network "forwarded_port", guest: 51820, host: 51820
config.vm.network "forwarded_port", guest: 80, host: 80
config.vm.network "forwarded_port", guest: 443, host: 443
config.ssh.username = "root"
config.ssh.password = "vagrant"
config.vm.provider "libvirt" do |lv|
lv.memory = 2048
lv.cpus = 3
lv.driver = "kvm"
end
config.vm.box_version = "13.20260519.1"
end
+16
View File
@@ -0,0 +1,16 @@
Vagrant.configure("2") do |config|
config.vm.box = "debian/trixie64"
config.vm.hostname = "staging0.test"
config.vm.network "private_network", ip: "192.168.200.201", bridge: "virbr0", ipv6: true
config.vm.network "forwarded_port", guest: 51820, host: 51820
# config.vm.network "forwarded_port", guest: 80, host: 80
# config.vm.network "forwarded_port", guest: 443, host: 443
config.ssh.username = "root"
config.ssh.password = "vagrant"
config.vm.provider "libvirt" do |lv|
lv.memory = 2048
lv.cpus = 3
lv.driver = "kvm"
end
config.vm.box_version = "13.20260519.1"
end
-6
View File
@@ -1,6 +0,0 @@
aria:
scheme: http
hostname: localhost
port: "6800"
secret: ~
credentals: ~
+146
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
View File
@@ -0,0 +1,3 @@
caddy:
containerized: true
scheme: http
+10
View File
@@ -0,0 +1,10 @@
certbot:
mode: "{{ mode | default('prod') }}"
containerized: true
auth_method: webroot
port: ~
email: ajt95@prole.biz
domains:
- "{{ fqdn | default(inventory_hostname) }}"
- "*.{{ fqdn | default(inventory_hostname) }}"
cron: "2 6 24 1 *"
+10
View File
@@ -0,0 +1,10 @@
certbot:
mode: "{{ mode | default('prod') }}"
containerized: false
auth_method: dns
port: 53
email: ajt95@prole.biz
domains:
- "{{ fqdn | default(inventory_hostname) }}"
- "*.{{ fqdn | default(inventory_hostname) }}"
cron: ~
-2
View File
@@ -1,2 +0,0 @@
crowdsec:
port: 8181
+9
View File
@@ -0,0 +1,9 @@
crowdsec:
containerized: false
port: 6050
colls:
- "crowdsecurity/base-http-scenarios"
- "crowdsecurity/proftpd"
parsers: []
scenarios: []
postoverflows: []
+9
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
-2
View File
@@ -1,2 +0,0 @@
flexget:
download_mode: direct
+3
View File
@@ -0,0 +1,3 @@
flexget:
enabled: true
download_mode: direct
+16
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
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
+23
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
View File
@@ -0,0 +1,3 @@
local_facts:
user_id: rika
user_dir: /home/rika
-3
View File
@@ -1,3 +0,0 @@
local_facts:
user_id: ""
user_dir: ""
+17
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) }}"
+12
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 }}"
+15
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
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
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
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
-3
View File
@@ -1,3 +0,0 @@
sox:
hostname: localhost
port: "9050"

Some files were not shown because too many files have changed in this diff Show More