135 Commits
Author SHA1 Message Date
DarkFeather ac7abefb77 Concluding the testing of the Geth role 2026-08-10 16:33:41 -05:00
DarkFeather a7c8d6471b Capturing containers running directly on Node 2026-08-05 16:58:18 -05:00
DarkFeather 08f5a533df K3s deploy on Rpis -- Rancher will live in Node 2026-08-05 16:38:28 -05:00
DarkFeather 311eb69d33 Revising Geth README; commenting Geth2-5 for staging 2026-07-31 15:50:37 -05:00
DarkFeather 51b1f00fb2 Adding diff method 2026-07-31 15:40:41 -05:00
DarkFeather 0710816bac Shaolin should be set at 0800 2026-07-31 15:35:12 -05:00
DarkFeather 3184acd651 Adding verbosity for debugging & flipping output order for check-domain 2026-07-28 17:46:36 -05:00
DarkFeather 99650f873c Monitoring updates 2026-07-15 12:41:42 -05:00
DarkFeather 7675f5ef79 Infrastructure updates 2026-07-15 12:26:52 -05:00
DarkFeather 886212e9f4 Simplifying network management 2026-07-15 12:18:48 -05:00
DarkFeather 33e24704b9 AUR updates 2026-07-15 11:25:25 -05:00
DarkFeather 5238bf62f4 Updates for tt-rss 2:r12866.fbed63e44-1 2026-07-15 11:21:12 -05:00
DarkFeather 5a89b54ca2 Updating AniNIX/Maat build list and order 2026-04-29 12:38:00 -05:00
DarkFeather c613df274a Adding Node4 2026-04-29 12:07:37 -05:00
DarkFeather 5ee1687dc6 Dropping 80/tcp/http 2026-03-30 14:05:33 -05:00
DarkFeather 355e2e9be1 Clarifying disconnected services 2026-03-30 13:58:37 -05:00
DarkFeather 327baab415 Documenting singularity role 2026-03-30 13:49:52 -05:00
DarkFeather 8c222b230c Update for AMA homepage 2026-01-13 02:11:25 -06:00
DarkFeather 0084b4ea19 Moving LetsEncrypt to ClouDNS API validation -- some LetsEncrypt queries come from non-US origins. 2026-01-13 02:10:33 -06:00
DarkFeather 0070afde5d Generalizing GeoIP to be consumed by more services 2025-12-29 14:46:55 -06:00
DarkFeather b6785b861a Merge branch 'domain-monitoring' into geoip 2025-12-18 14:44:15 -06:00
DarkFeather 43f764e664 Adding domain monitoring for TLSA/SSHFP/CAA records 2025-12-18 14:43:13 -06:00
DarkFeather 49839d1333 Adding geoip block to Superintendent for testing 2025-12-18 14:41:35 -06:00
DarkFeather 804b2e3c6c Adding geoip module and instituting a deny variable for vhosts to consume 2025-12-18 14:41:32 -06:00
DarkFeather fdd438268a Merge conflict 2025-12-15 10:08:11 -06:00
DarkFeather d579dac24a Update for AMA home page to reduce exposure of our influences 2025-12-14 11:43:02 -06:00
DarkFeather f00f95a689 Update to use grep -F to find secrets -- it prevents special characters in secrets being interpreted. 2025-12-14 11:42:22 -06:00
DarkFeather 18cc3380d6 Adding geoip block to Superintendent for testing 2025-12-02 14:47:29 -06:00
DarkFeather ad6e48d7e0 Adding geoip module and instituting a deny variable for vhosts to consume 2025-12-02 14:43:49 -06:00
DarkFeather 31992aa487 Moving KiwiIRC websocket behind Nginx instead of dedicated external port 2025-10-21 15:31:32 -05:00
DarkFeather 571455802b Catchup 2025-10-21 14:04:09 -05:00
DarkFeather 4df485af5d Updates for requirements 2025-10-21 13:55:07 -05:00
DarkFeather 365e476b82 Update for internal subdomains as well as external 2025-10-21 13:54:23 -05:00
DarkFeather c7f88d988b IRC Update for KiwiIRC 1.7 2025-10-21 13:52:25 -05:00
DarkFeather 333a987dac Moving these hooks to AniNIX/Uniglot 2025-10-09 20:37:39 -05:00
DarkFeather 40355ea6e0 Updates for Foundation JS 2025-10-09 20:36:31 -05:00
DarkFeather b50de1e4f7 Styling updates for Gitea upgrades 2025-09-30 17:14:49 -05:00
DarkFeather 25c9872a0a Updates for AniNIX/Password 2025-09-29 16:33:35 -05:00
DarkFeather 78af592485 Updates for latest inspircd & anope 2025-09-29 16:33:05 -05:00
DarkFeather a14dfd6562 Password package update 2025-04-27 15:25:54 -05:00
DarkFeather 6864492ce4 Community is gone. https://archlinux.org/news/cleaning-up-old-repositories/ 2025-04-15 14:33:51 -05:00
DarkFeather 35eabff91a Removing unneeded packages 2025-04-15 14:32:41 -05:00
DarkFeather 16ed6e85dc Need latest on config 2025-04-15 14:31:23 -05:00
DarkFeather 02bf4326a3 Deprecating wolfpack.aninix.net subdomain 2025-04-15 14:24:56 -05:00
DarkFeather 405fcb4447 Formatting 2025-04-15 14:03:32 -05:00
DarkFeather 5089c82710 Inventory sanity checks 2025-04-15 13:59:53 -05:00
DarkFeather 7962727fb3 Updates for yggdrasil 2025-04-15 13:58:49 -05:00
DarkFeather a82bd54091 Linting 2025-04-12 06:58:34 -05:00
DarkFeather 17f900003f Moving WolfPack output to /home instead of /srv for users to access with SFTP & Cyberbrain 2025-04-12 06:42:45 -05:00
DarkFeather 9f131ca0a9 Adding AIDE to HIDS tools 2025-04-12 04:36:22 -05:00
DarkFeather b6692593a3 Fixing text 2025-04-12 02:59:24 -05:00
DarkFeather 81960d92b0 Updating generate-monitoring to use TrackIPEntries 2025-04-12 02:58:38 -05:00
DarkFeather 59b3181d61 Updates for packages 2024-09-02 23:54:57 -05:00
project2501 f139ea55b4 ++precommit-hooks/playbook-lint-check 2024-08-22 15:30:41 -05:00
project2501 2e154389de patching-verification.yml -- trailing whitespace 2024-08-22 10:39:18 -05:00
DarkFeather f5ef18851c First round injecting news articles into homepages using serverside precompiled snippets 2024-08-20 00:17:09 -05:00
DarkFeather 8886b572b0 Rebuild Pacman keyring 2024-08-12 17:30:29 -05:00
DarkFeather a17e2c6fe9 Updates for Raspberry Pi 12 Bookworm 2024-07-23 14:18:32 -05:00
DarkFeather 9366d8b6d7 Catch up for Foundation 2024-04-05 13:16:42 -05:00
DarkFeather 5c3eb7f358 Moving VMs to Host cpu emulation 2024-04-04 13:15:38 -05:00
DarkFeather 33cf371a0d Updating roles 2024-04-01 00:53:08 -05:00
DarkFeather 9aa0a89b79 Seeding Aether 2024-04-01 00:52:29 -05:00
DarkFeather 3a01543c8b Capturing APC automation 2024-04-01 00:49:36 -05:00
DarkFeather 87973dfb6e Simplifying group management 2024-04-01 00:49:02 -05:00
DarkFeather 85286b5412 Catching up with automation 2024-04-01 00:47:05 -05:00
DarkFeather 6f36d515e3 AniNIX/Wiki#21 -- effecting renames for policy 2024-04-01 00:44:23 -05:00
DarkFeather 323b4dd306 Pathing updates for Gitea 1.21.5 -- custom/public to custom/public/assets 2024-03-07 12:28:46 -06:00
DarkFeather e75d03a313 Update for automated response around poorly behaving archlinux-keyring weekly timer; rename Sora role to Password 2024-03-07 12:27:21 -06:00
DarkFeather 930441ae9a Adding enforcement exit code 2024-01-18 12:04:30 -06:00
DarkFeather f9a3bd789b Removing duplicate resource 2024-01-12 16:17:55 -06:00
DarkFeather 15dd844093 Correcting abandoned rename 2024-01-12 16:10:40 -06:00
DarkFeather 43d7375dae Updating AniNIX/Scratch for naming & persistence warning 2024-01-12 15:34:41 -06:00
DarkFeather cd3210c5fb Adding minor webapps to WebServer tracking 2024-01-12 13:06:58 -06:00
DarkFeather 221ce69a80 Catching up wolfpack to reenable 2024-01-12 13:06:19 -06:00
DarkFeather 1ca0272031 Adding ucode & UPS definitions to IAC 2023-12-21 12:58:32 -06:00
DarkFeather e244895552 Finalizing Cyberbrain role 2023-12-19 16:20:58 -06:00
DarkFeather cea66f285a Finishing rename from Core to Yggdrasil 2023-12-19 16:16:35 -06:00
DarkFeather 50167c0f03 Virtualizing Core host as Yggdrasil VM 2023-12-07 13:28:54 -06:00
DarkFeather 7b98c953b1 Merging out nginx conversion 2023-11-30 02:48:50 -06:00
DarkFeather 69e2bcc966 Evolution of deployment 2023-11-30 02:47:16 -06:00
DarkFeather 8392a3fe46 Hooks catch-up 2023-11-30 02:44:01 -06:00
DarkFeather 63a43c6f0e Fixing PKGBUILD dependencies 2023-11-16 12:59:49 -06:00
DarkFeather 528af8b0f5 Fixing PKGBUILD dependencies 2023-11-16 12:58:52 -06:00
DarkFeather 9b317d1677 Dropping Stripe as a payment method (will replace with Venmo/USDCoin address) & Google Analytics for AniNIX/Sharingan -- some updates for CSP in line with https://observatory.mozilla.org/analyze/aninix.net 2023-11-16 12:50:26 -06:00
DarkFeather 5fa67890c2 Moving from openresty to nginx+modsec for HTTP/2 Rapid Reset reasons 2023-11-09 13:03:06 -06:00
DarkFeather 444b8171f5 Adding packaging 2023-10-20 19:08:32 -05:00
DarkFeather ea75da1b41 catchup 2023-10-08 12:28:14 -05:00
DarkFeather 5ab88dc387 Updating some SSH config 2023-07-19 15:41:27 -05:00
DarkFeather 60f848b55d Extending check interval for warrant canary checks 2023-05-30 16:03:22 -05:00
DarkFeather 75bf57c131 Adding checks on AniNIX/Grimoire to Core 2023-05-30 15:51:36 -05:00
DarkFeather 921e45afda pacman hook was using wrong user 2023-05-05 05:16:48 -05:00
DarkFeather 633f231b26 Catching up config with known state 2023-05-02 17:32:11 -05:00
DarkFeather be2908625d Adding org-wide packaging config to AniNIX/Maat 2023-05-01 22:01:30 -05:00
DarkFeather 49b67de7ec Removing large amounts of extra commenting and old/unused features; SASL support 2023-04-18 23:56:59 -05:00
DarkFeather e9fde0d8c9 Removing storefront from /martialarts; decomming stagnant copy of our RSS feed 2023-04-07 20:14:26 -05:00
DarkFeather 6a4aabee01 OpenVPN now manages the tunnel device -- DarkNet does not need bridge/tap config 2023-03-29 23:31:04 -05:00
DarkFeather 5fef78f60e Catching up IRC -- MOTD colors; servicefile; logging; config 2023-03-22 17:44:57 -05:00
DarkFeather 2f93e03f3a Zeek currently fails to build and burns too many system resources -- dropping. 2023-02-27 23:45:58 -06:00
DarkFeather 638b4e8c6e Seeding Maat role 2023-02-22 22:33:58 -06:00
DarkFeather 956b00a06e Syncing scripts and hooks 2023-02-22 21:54:52 -06:00
DarkFeather d92ab6acda Cleaning up to fit AniNIX/Uniglot hooks; catching up with testing 2023-02-20 16:50:10 -06:00
DarkFeather a2fecf9d64 Adding DHParam generation for IRC ssl_openssl 2023-01-20 08:49:56 -06:00
DarkFeather bef53d5889 Placing mediawiki package on hold 2022-12-23 11:28:29 -06:00
DarkFeather 99b7b9026c Removing IRC-Bots as a separate role -- folding into IRC role as part of the service 2022-12-18 22:25:40 -06:00
DarkFeather c589f5ac55 Updating DarkNet VPN setup 2022-12-18 22:24:44 -06:00
DarkFeather 36d0be5f88 Infrastructure cleanup 2022-12-18 22:23:17 -06:00
DarkFeather 890e20c64c Catching up Webserver config 2022-12-18 22:21:39 -06:00
DarkFeather 72a62b63eb Seeding IRC automation after a lot of work 2022-12-18 22:18:43 -06:00
DarkFeather 0626c66413 Removing large files; adding hook to watch for them 2022-12-18 22:14:25 -06:00
DarkFeather a34c96df6b Whitespace cleanup to get in sync with AniNIX/Uniglot hooks 2022-11-20 20:03:01 -06:00
DarkFeather a43cb4b6bb Updates to fix certbot.service issues reloading 2022-10-01 23:54:40 -05:00
DarkFeather 12d2ca9a1d Updating WebServer deployment 2022-09-15 14:23:34 -05:00
DarkFeather 81b9a0a190 Logic update in tmux-hosts 2022-09-15 13:16:39 -05:00
DarkFeather b7d26b6aa7 Updating Foundation role 2022-09-15 13:16:08 -05:00
DarkFeather 94f546a7be Starting Foundation automation 2022-07-02 10:24:10 -05:00
DarkFeather 59b54619f7 Catching up Sharingan, Geth, and ShadowArch roles 2022-05-25 14:50:16 -05:00
DarkFeather 8b2b0be95b Ensuring we go through local networking for our VIPs 2022-05-23 21:30:24 -05:00
DarkFeather 9758b23193 Current state; https://archlinux.org/news/qemu-700-changes-split-package-setup/ 2022-05-11 17:20:57 -05:00
DarkFeather 51e2836378 Updating Sharingan for testing 2022-05-04 10:30:23 -05:00
DarkFeather 01dde4008d Got rkhunter working for HIDS; operational fixes for Sharingan 2022-05-03 16:57:52 -05:00
DarkFeather d0146770a4 Current state of Sharingan role -- still need to add rkhunter 2022-05-02 15:00:29 -05:00
DarkFeather 1c2f4266ad Adding Nazara README.md 2022-04-29 11:15:20 -05:00
DarkFeather d1140cf78b Catching up with current dev 2022-04-19 12:01:03 -05:00
DarkFeather a881363b9b Fixing Nazara errors 2022-03-25 06:08:12 -05:00
DarkFeather 5d04f1b393 Updating Geth-Hub role for config options; moving sources.list to ShadowArch control with pacman.conf 2022-01-29 23:41:46 -06:00
DarkFeather 921d53c724 Catching up with current successes 2022-01-25 23:54:43 -06:00
DarkFeather 94a4736839 Syncing current state. 2021-12-19 21:32:19 -06:00
DarkFeather eb39acaa06 Adding a role for TheRaven 2021-11-21 04:53:42 -06:00
DarkFeather 8f85acce78 Seeding the Cyberbrain role 2021-11-09 16:01:39 -06:00
DarkFeather 87775fe636 Updates for structure 2021-03-16 03:09:19 -05:00
DarkFeather 68ef34c3c6 Adding some SSL support scripts 2021-01-01 12:45:34 -06:00
DarkFeather 17a9e9ef7d Group controls, hostkey protection, and typo correction in SSH 2020-12-25 05:40:57 -06:00
DarkFeather 432cc36ef8 Updating DarkNet role 2020-11-02 16:15:47 -06:00
DarkFeather ffbd7b7bd8 Adding better syslog 2020-10-18 23:49:25 -05:00
DarkFeather e12c8ff0c6 Updating Ubiqtorate 2020-10-08 16:33:19 -05:00
388 changed files with 25488 additions and 2 deletions
+17
View File
@@ -1,3 +1,20 @@
# Generated files
roles/Node/files/*-vm.service
roles/Chappaai/files/dns
roles/Chappaai/files/dhcp
roles/Node/files/vm-definitions/**
roles/ShadowArch/files/mirrorlist
roles/Sharingan/files/monit/checks/availability
roles/Foundation/files/custom/public/img/**
roles/Maat/files/pacoloco.yaml
venv/**
wiki/
wiki/**
**/pkg/**
**/src/**
**pkg.tar.zst
wiki/**
# ---> Python
# Byte-compiled / optimized / DLL files
__pycache__/
+31
View File
@@ -0,0 +1,31 @@
pkgdirname != basename `git config remote.origin.url` | sed 's/.git$$//'
optlist = bin examples playbooks roles
compile:
@echo Nothing to do
install: clean compile
mkdir -p ${pkgdir}/opt/aninix/${pkgdirname}/
for opt in ${optlist}; do cp -pr $$opt ${pkgdir}/opt/aninix/${pkgdirname}/${opt}; done
make checkperm
clean:
git clean -fdX
uninstall:
rm -Rf ${pkgdir}/opt/aninix/${pkgdirname}/
test: compile
#python3 -m pytest
checkperm:
chown -R root: ${pkgdir}/opt/aninix/${pkgdirname}/
chmod 0755 ${pkgdir}/opt/aninix/${pkgdirname}/
chmod -R a+r ${pkgdir}/opt/aninix/${pkgdirname}/
diff:
@echo Nothing to do.
for opt in ${optlist}; do diff -r ${pkgdir}/opt/aninix/${pkgdirname}/${opt} $$opt; done
reverse:
for opt in ${optlist}; do rsync -avzlp ${pkgdir}/opt/aninix/${pkgdirname}/${opt}/ $$opt; done
+42
View File
@@ -0,0 +1,42 @@
pkgname="$(git config remote.origin.url | rev | cut -f 1 -d '/' | rev | sed 's/.git$//')"
pkgver="$(git describe --tag --abbrev=0)"."$(( `git log "$(git describe --tag --abbrev=0)"..HEAD | grep -c commit` + 1 ))"."$(git rev-parse --short HEAD)"
pkgrel=1
pkgdesc="$(head -n 1 README.md)"
arch=("x86_64")
url="$(git config remote.origin.url | sed 's/.git$//')"
license=('custom')
groups=()
depends=('bash>=4.4' 'python>=3.11' 'ansible>=8.3' 'tmux' 'openssh')
makedepends=('make>=4.2')
checkdepends=()
optdepends=()
provides=("${pkgname}")
conflicts=()
replaces=("${pkgname,,}" "aninix-${pkgname,,}")
backup=()
options=()
install=
changelog=
source=()
noextract=()
md5sums=()
validpgpkeys=()
prepare() {
git pull
}
build() {
make -C ..
}
check() {
chmod -R u+r ../pkg
make -C .. test
}
package() {
export pkgdir="${pkgdir}"
make -C .. install
install -D -m644 ../LICENSE "${pkgdir}/usr/share/licenses/${pkgname}/LICENSE"
}
+50 -2
View File
@@ -1,3 +1,51 @@
# Tenebrous
This project is our Infrastructure-as-Code solution, detailing the deployment & some repeatable operational tasks of the AniNIX.
This project will discover and provide inventory intelligence to Sora, Shadowfeed, Geth, and Sharingan. It is named after the fictional Tenebrous from the SWTOR game.
# Etymology
It is named after flagship carrier Kapisi from the game [Homeworld: Deserts of Kharak](https://store.steampowered.com/app/281610?snr=5000_5100___primarylinks). The carrier was the command and production center of Operation Khadiim, an expedition to understand an anomaly on their world & escape the fanaticism of their Gaalsien rivals. The S'jet were able to succeed in this mission not only due to the military efficacy of their forces but also through the research and production capabilities available to the Kapisi.
This project seeks to give other admins and engineers to launch their own infrastructures and break out of any strangleholds that may have entangled them, whether that is tribalism, vendor lock, or stigma.
# Relevant Files and Software
This project expects that you use an Ansible vault for credentials. Create one and add this to your `.bashrc`.
```
export ANSIBLE_VAULT_PASSWORD_FILE=$HOME/password-store/${organization}.vault.password
export ANSIBLE_VAULT_FILE=$HOME/password-store/${organization}.vault
```
Take a look at `examples/msn0.yml` as an example inventory -- make sure you populate one of your own. The scripts here expect inventories to have layers of groups -- the top group under `all` must be managed vs. unmanaged. The rest of the scripts use YAMLPath to sort out the rest of the groups.
Once you have your vault and inventory, use [AniNIX/ShadowArch](/AniNIX/ShadowArch) with your hypervisor to provision the base image for your machines, or [Raspbian](https://www.raspberrypi.org/).
Then, use the SSH key playbook to copy your key and the deploy playbook to set things up.
```
ansible-playbook -i your-inventory.yml playbooks/sshkey.yml
ansible-playbook -i your-inventory.yml playbooks/deploy.yml
```
We've also added two scripts in `./bin` to make your life easier:
* `full-deploy`: This is the general role. If you are creating an AniNIX replica, once you have your inventory and vault populated, then you can run this script to push everything. This is also optimal when rotating vault secrets or other global tasks. This is effectively standardizing invocation of our overall deployment playbook.
* `deploy-role`: When you are updating a specific role, use this script to push that role to your group. Ideally, this should only be used to push a role that you have been working on to a target group in your inventory that's already tagged for the role in the deployment playbook.
Happy hacking!
# Etymology
The [Ubiqtorate](https://starwars.fandom.com/wiki/Ubiqtorate/Legends) was a far-reaching security orchestration entity within Palpatine's Empire. It was mean to collect and act on intelligence to improve the security posture of the regime. We use this project similarly -- Ubiqtorate is the Infrastructure-as-Code behind the throne, making changes and ensuring services stay in line.
# Relevant Files and Software
This project is mostly built on [Ansible](https://docs.ansible.com/). You will need to understand inventories, playbooks, and vaults at the minimum.
# Available Clients
None -- this project is used to describe actions for other services to take.
# Equivalents or Competition
Similar tools include Puppet, chef, salty, Ansible Tower, Terraform, etc. We have chosen to go the raw Ansible route, so that we don't have to maintain the build infrastructure separately and to make our responses more agile.
# Exceptions
Some services, such as AniNIX/Sharingan and AniNIX/Geth, store their configuration in internal datastructures and databases such that we cannot easily export our build for others to use. We will document what we have done for each of these as best we can in the README.md files for others to replicate. Backups of these services into AniNIX/Aether are therefore dumps of these databases and not available to share.
+51
View File
@@ -0,0 +1,51 @@
#!/bin/bash
# Ensure we are in the source directory.
cd $(dirname $0)/..
# Role is first argument
role="$1"
if [ -z "$role" ]; then
echo Need a role as first argument.
exit 1
fi
# Handle verbosity
if [ "$1" == "-v" ]; then
set -x
shift
role="$1"
fi
# Handle usage
if [ "$role" == "-h" ] || [ "$role" == "--help" ]; then
echo "Usage: $0 -h"
echo " $0 \$role \$targetgroup [\$optional_inventory]"
exit 0
fi
# Find the root of the git clone
while [ ! -d .git ]; do
cd ..
if [ "$PWD" == '/' ]; then
echo "This needs to be run from the Kapisi checkout"
exit 3
fi
done
# Get the targetgroup
targetgroup="$2"
if [ -z "$targetgroup" ]; then
targetgroup="$role" # Deploy a role to the server named for that function
fi
# Allow an inventory override
inventory="$3"
if [ -z "$inventory" ]; then
inventory=examples/msn0.yml
fi
# Invoke the one-role playbook for the role on the targetgroup
ansible-playbook -i "$inventory" -e "role=$role" -e "targets=$targetgroup" playbooks/one-role.yml
# and return the exit status
exit $?
+52
View File
@@ -0,0 +1,52 @@
#!/bin/bash
# Role is first argument
taskfile="$1"
if [ -z "$taskfile" ]; then
echo Need a taskfile as first argument.
exit 1
fi
# Ensure we are in the source directory.
cd $(dirname $1)/..
# Handle verbosity
if [ "$1" == "-v" ]; then
set -x
shift
taskfile="$1"
fi
# Handle usage
if [ "$taskfile" == "-h" ] || [ "$taskfile" == "--help" ]; then
echo "Usage: $0 -h"
echo " $0 \$taskfile \$targetgroup [\$optional_inventory]"
exit 0
fi
# Find the root of the git clone
while [ ! -d .git ]; do
cd ..
if [ "$PWD" == '/' ]; then
echo "This needs to be run from the Kapisi checkout"
exit 3
fi
done
# Get the targetgroup
targetgroup="$2"
if [ -z "$targetgroup" ]; then
targetgroup="$taskfile" # Deploy a taskfile to the server named for that function
fi
# Allow an inventory override
inventory="$3"
if [ -z "$inventory" ]; then
inventory=examples/msn0.yml
fi
# Invoke the one-taskfile playbook for the taskfile on the targetgroup
ansible-playbook -i "$inventory" -e "taskfile=$taskfile" -e "targets=$targetgroup" "$(dirname $0)/../playbooks/one-taskfile.yml"
# and return the exit status
exit $?
+27
View File
@@ -0,0 +1,27 @@
#!/bin/bash
# Ensure we are in the source directory.
cd $(dirname $0)/..
# Arguments
inventory="$1"
if [ "$inventory" == "-h" ] || [ "$inventory" == "--help" ]; then
echo "Usage: $0 -h # Usage"
echo " $0 # Run a complete deployment."
exit 0
elif [ -z "$inventory" ]; then
inventory="examples/msn0.yml"
fi
# Find the root of the git clone
while [ ! -d .git ]; do
cd ..
if [ "$PWD" == '/' ]; then
echo "This needs to be run from the Kapisi checkout"
exit 3
fi
done
ansible-playbook -i examples/msn0.yml playbooks/deploy.yml
+14
View File
@@ -0,0 +1,14 @@
#!/bin/bash
curl -s https://raw.githubusercontent.com/archlinux/svntogit-packages/packages/pacman-mirrorlist/trunk/mirrorlist | awk '/^## United States$/{f=1; next}f==0{next}/^$/{exit}{print substr($0, 1);}' | sed 's/^#Server/Server/' > /tmp/candidates
cat <<EOM > ../roles/Maat/files/pacoloco.yaml
port: 9129
download_timeout: 3600 # download will timeout after 3600 seconds
cache_dir: /var/cache/pacoloco
purge_files_after: 360000 # 360000 seconds or 100 hours, 0 to disable
repos:
archlinux:
urls:
$(rankmirrors -n 6 /tmp/candidates | sed 's/^Server = / - /' | grep -v generated\ by | cut -f 1 -d \$)
user_agent: Pacoloco
EOM
+72
View File
@@ -0,0 +1,72 @@
#!/usr/bin/env python3
# File: generate-pihole-dns-dhcp.py
#
# Description: This file generates the DNS and DHCP files for pihole.
#
# Package: AniNIX/Kapisi
# Copyright: WTFPL
#
# Author: DarkFeather <darkfeather@aninix.net>
import os
import subprocess
import sys
import re
import yaml
from kapisi_lib import *
rolepath='../roles/Sharingan/files'
monfilepath=rolepath+"/monit/checks/availability"
def WriteMonitoringEntry(entryset):
### Create the ping-based monitoring entry
# param entryset: Entries matched from the inventory
global monfile
with open(monfilepath,'a') as monfile:
# Write host entries
for host in entryset:
try:
monfile.write('check program ' + host + '_ping_mon with path "/usr/lib/monitoring-plugins/check_ping -H ' + entryset[host][2] + ' -w 100,50% -c 1000,100% -p 3 -t 60 -4"\n')
monfile.write(' if status != 0 for 3 times within 5 cycles then exec "/etc/monit.d/scripts/critical ' + entryset[host][2] + ' is not online."\n\n')
except:
print(host + ' is not complete for monitoring.')
def WriteSSHMonitoringEntry(entryset):
### Create the ping-based monitoring entry
# param entryset: Entries matched from the inventory
global monfile
with open(monfilepath,'a') as monfile:
# Write host entries
for host in entryset:
try:
monfile.write('check program ' + host + '_ssh_mon with path "/usr/lib/monitoring-plugins/check_ssh -H ' + entryset[host][2] + '"\n')
monfile.write(' if status != 0 for 3 times within 5 cycles then exec "/etc/monit.d/scripts/critical ' + host + ' is not responding to SSH."\n\n')
except:
print(host + ' is not complete for monitoring.')
def GenerateFiles(file):
### Open the file and parse it
# param file: the file to work on
global monfilepath
if not os.path.isdir(rolepath):
os.mkdir(rolepath)
# Parse the yaml
entryset = TrackIPEntries(file,searchstring='all.children.managed.**.ip')
if os.path.isfile(monfilepath): os.remove(monfilepath)
WriteSSHMonitoringEntry(entryset)
WriteMonitoringEntry(entryset)
if __name__ == '__main__':
if len(sys.argv) != 2:
print("You need to supply an inventory file.")
sys.exit(1)
GenerateFiles(sys.argv[1])
sys.exit(0)
+81
View File
@@ -0,0 +1,81 @@
#!/usr/bin/env python3
# File: generate-pihole-dns-dhcp.py
#
# Description: This file generates the DNS and DHCP files for pihole.
# It expects that the inventory has two levels of grouping.
#
# Package: AniNIX/Kapisi
# Copyright: WTFPL
#
# Author: DarkFeather <darkfeather@aninix.net>
import os
import re
import subprocess
import sys
from kapisi_lib import *
rolepath='../roles/Chappaai/files'
dnsfilepath=rolepath+"/dns"
dhcpfilepath=rolepath+"/dhcp"
entryset={}
def WriteDHCPEntries(dhcpfile):
### Create the DHCP entry
# param content: the yaml content to parse
# param hosttype: managed or unmanaged
# param hostclass: the type of host as classified in the yaml
global entryset
for host in entryset:
# Entries should be:
# dhcp-host=mac,ip,fqdn
dhcpfile.write('dhcp-host=' + entryset[host][1] + ',' + entryset[host][0] + ',' + entryset[host][2] + '\n')
def WriteDNSEntries(dnsfile):
### Create the DNS entry
# param content: the yaml content to parse
# param hosttype: managed or unmanaged
# param hostclass: the type of host as classified in the yaml
global entryset
for host in entryset:
# Entries should be:
# ip host fqdn
dnsfile.write(entryset[host][0] + ' ' + entryset[host][2] + ' ' + host + '\n')
def GenerateFiles(file):
### Open the file and parse it
# param file: the file to work on
global dnsfile
if not os.path.isdir(rolepath):
os.mkdir(rolepath)
# Parse the yaml
with open(file, 'r') as stream:
content = yaml.safe_load(stream)
external_domain = content['all']['vars']['external_domain']
# Clear the DNS file
with open(dhcpfilepath,'w') as dhcpfile:
dhcpfile.write('dhcp-range='+content['all']['vars']['dhcprange']+'\n')
dhcpfile.write('dhcp-option=option:dns-server,'+content['all']['vars']['dns']+'\n\n')
dhcpfile.write('dhcp-range='+content['all']['vars']['staticrange']+'\n')
WriteDHCPEntries(dhcpfile)
with open(dnsfilepath,'w') as dnsfile:
dnsfile.write(content['all']['vars']['webfront']+' '+external_domain+' '+content['all']['vars']['internal_subdomains'].replace(' ','.'+external_domain+' ')+'.'+external_domain+' '+content['all']['vars']['external_subdomains'].replace(' ','.'+external_domain+' ')+'.'+external_domain+' '+content['all']['vars']['hosted_domains']+"\n")
WriteDNSEntries(dnsfile)
print('Files should be in '+rolepath);
### Main function
# param sys.argv: Input arguments
if __name__ == '__main__':
if len(sys.argv) < 2:
print("You need to supply an inventory file.")
sys.exit(1)
if len(sys.argv) == 3:
entryset = TrackIPEntries(sys.argv[1],sys.argv[2])
else:
entryset = TrackIPEntries(sys.argv[1])
GenerateFiles(sys.argv[1])
#dumper.dump(entryset)
sys.exit(0)
+21
View File
@@ -0,0 +1,21 @@
#!/bin/bash
# File: ./generate-ssh-keyscan
#
# Description: This file generates a known_host block for the inventory.
#
# Package: AniNIX/HelloWorld
# Copyright: WTFPL
#
# Author: DarkFeather <ircs://aninix.net:6697/DarkFeather>
inventory="$1"
replicadomain="$(grep replica_domain:\ "$inventory" | awk '{ print $2; }';)"
for short in `ansible -i "$inventory" --list-hosts managed | grep -v hosts | sed 's/^\s\+//'`; do
long="$short"'.'"$replicadomain"
ip="$(dig "$long" +short)"
ssh-keyscan -t ed25519 -f <(echo "$long" "$long","$short","$ip") 2>&1
ssh-keyscan -t rsa -f <(echo "$long" "$long","$short","$ip") 2>/dev/null
done
+95
View File
@@ -0,0 +1,95 @@
#!/usr/bin/env python3
# File: generate-systemd-vms.py
#
# Description: This file generates the systemd.service files that run our VM's
#
# Package: AniNIX/Kapisi
# Copyright: WTFPL
#
# Author: DarkFeather <darkfeather@aninix.net>
import os
import shutil
import sys
import yaml
filepath="../roles/Node/files/vm-definitions/"
def WriteVMFile(content,hosttype,hostclass):
### Create the service files for the hosts
# param content: the yaml content to parse
# param hosttype: managed or unmanaged
# param hostclass: the type of host as classified in the yaml
global filepath
for host in content['all']['children'][hosttype]['children'][hostclass]['hosts']:
cores = 0
memory = 0
vnc = 0
disks = ''
mac = ''
bridge = ''
# Make sure the host definition has all the critera
try:
cores = str(content['all']['children'][hosttype]['children'][hostclass]['hosts'][host]['cores'])
memory = str(content['all']['children'][hosttype]['children'][hostclass]['hosts'][host]['memory'])
vnc = str(content['all']['children'][hosttype]['children'][hostclass]['hosts'][host]['vnc'])
disks = ' '.join(content['all']['children'][hosttype]['children'][hostclass]['hosts'][host]['disks'])
mac = content['all']['children'][hosttype]['children'][hostclass]['hosts'][host]['mac']
bridge = content['all']['children'][hosttype]['children'][hostclass]['hosts'][host]['bridge']
except Exception as e:
print('Host ' + host + " doesn't have the attributes needed to be a VM -- skipping.")
print(e)
1 == 1
# Write the file.
with open(filepath+host+'-vm.service','w') as vmfile:
vmfile.write('[Unit]\n')
vmfile.write('Description=AniNIX/' + host + '\n')
vmfile.write('After=network-online.target\n')
vmfile.write('\n')
vmfile.write('[Service]\n')
vmfile.write('ExecStart=/usr/sbin/qemu-system-x86_64 -name AniNIX/' + host + ' -machine type=q35,accel=kvm')
if 'uefi' in content['all']['children'][hosttype]['children'][hostclass]['hosts'][host].keys(): vmfile.write(' -bios /usr/share/edk2-ovmf/x64/OVMF.fd')
vmfile.write(' -cpu host -smp ' + cores + ' ' + disks + ' -net nic,macaddr=' + mac + ',model=virtio -net bridge,br=' + bridge + ' -vga std -nographic -serial none -vnc :' + str(vnc) + ' -m size=' + str(memory) + 'G -device virtio-rng-pci\n')
vmfile.write('ExecReload=/bin/kill -HUP $MAINPID\n')
vmfile.write('KillMode=process\n')
vmfile.write('Restart=always\n')
vmfile.write('User=root\n')
vmfile.write('Group=root\n')
vmfile.write('\n')
vmfile.write('[Install]\n')
vmfile.write('WantedBy=multi-user.target\n')
print(host+'-vm.service')
def GenerateFiles(file):
### Open the file and parse it
# param file: the file to work on
global filepath
try:
shutil.rmtree(filepath)
except:
1 == 1
finally:
os.mkdir(filepath)
# Parse the yaml
with open(file, 'r') as stream:
content = yaml.safe_load(stream)
# Add service files for each host
WriteVMFile(content,'managed','virtual')
WriteVMFile(content,'unmanaged','ovas')
WriteVMFile(content,'unmanaged','test_ovas')
if __name__ == '__main__':
if len(sys.argv) != 2:
print("You need to supply an inventory file.")
sys.exit(1)
GenerateFiles(sys.argv[1])
sys.exit(0)
+72
View File
@@ -0,0 +1,72 @@
import re
import yaml
from types import SimpleNamespace
from yamlpath.common import Parsers
from yamlpath.wrappers import ConsolePrinter
from yamlpath import Processor
from yamlpath import YAMLPath
from yamlpath.exceptions import YAMLPathException
def TrackIPEntries(yaml_file,searchstring='all.children.**.ip'):
### Try to parse an Ansible inventory for hosts with the 'ip' attribute.
# param file: the file to parse
# return: a populated entry set in form [{Host,[ip,mac,fqdn]},...]
# Borrowing from upstream author's example at https://pypi.org/project/yamlpath/
entryset = {}
replicadomain = GetReplicaDomain(yaml_file)
# The various classes of this library must be able to write messages somewhere
# when things go bad.
#logging_args = SimpleNamespace(quiet=True, verbose=False, debug=False)
logging_args = SimpleNamespace(quiet=True, verbose=True, debug=True)
log = ConsolePrinter(logging_args)
# Prep the YAML parser
yaml = Parsers.get_yaml_editor()
(yaml_data, doc_loaded) = Parsers.get_yaml_data(yaml, log, yaml_file)
if not doc_loaded:
exit(1)
processor = Processor(log, yaml_data)
yaml_path = YAMLPath(searchstring)
# Create a regex pattern to remove the end of the path
ippattern = re.compile('\\.ip$')
try:
for node_coordinate in processor.get_nodes(yaml_path, mustexist=True):
# Strip the path to the host entry.
path = ippattern.sub("",str(node_coordinate.path))
# Pull the IP
ip = str(node_coordinate.node)
# Pull the hosname
splitpath = path.split('.')
hostname = splitpath[len(splitpath)-1]
#print("Got {} from '{}''.".format(ip,path))
# Path the MAC
mac_yaml_path = YAMLPath(path+".mac")
mac=""
try:
for node_coordinate in processor.get_nodes(mac_yaml_path, mustexist=True):
mac = str(node_coordinate.node)
except YAMLPathException as ex:
log.error(ex)
# Add the host to the entryset.
entryset.update({ hostname : [ip,mac,hostname+'.'+replicadomain] })
except YAMLPathException as ex:
log.error(ex)
finally:
return entryset
def GetReplicaDomain(file):
'''
Return the defined replica domain
'''
with open(file, 'r') as stream:
content = yaml.safe_load(stream)
return content['all']['vars']['replica_domain']
+18
View File
@@ -0,0 +1,18 @@
#!/bin/bash
if [ "$USER" != root ]; then
sudo $0 $@
exit 0
fi
grep -A 2 copy: tasks/main.yml | tr '\n' ' ' | sed 's/--/\n/g' | while read copyline; do
dest="$(echo "$copyline" | sed 's/ /\n/g' | grep src: | awk '{ print $2; }' )"
src="$(echo "$copyline" | sed 's/ /\n/g' | grep dest: | awk '{ print $2; }' )"
if [ -d "$src" ]; then
cp -r "$src"/* files/"$dest"
else
cp -r "$src" files/"$dest"
fi
chown -R "$SUDO_USER": files/"$dest"
done
Executable
+90
View File
@@ -0,0 +1,90 @@
#!/bin/bash
# File: tmux-hosts
#
# Description: This script allows you to open groups of hosts in 2x2 tmux panes
#
# Package: AniNIX/Ubiqtorate
# Copyright: WTFPL
#
# Author: DarkFeather <ircs://irc.aninix.net:6697/DarkFeather>
# Sanity
set -Eo pipefail
# Defaults
group=all
offset=0
unset inventory
function usage() {
# Show helptext
# param retcode: what to exit
retcode="$1"
echo "Usage: $0 [ -o offset ] [-g group ] [-i inventory.yml]"
echo " $0 -h"
echo "Group is optional -- add it if you only want to look at a specific subset."
echo "Add -v for verbosity."
exit "$retcode"
}
function tmuxHosts() {
# Open hosts in Tmux -- ported from pnp/misc-scripts.git geotmux
# param host1: the first host
# param host2: the second host
# param host3: the third host
# param host4: the fourth host
host1="$1"
host2="$2"
host3="$3"
host4="$4"
name="$group-$offset"
# If no TMUX session started, then add one with four panes.
if [ -z "$TMUX" ]; then
tmux new-session -s "$name" -d "/bin/bash -l -c ssh\\ $host1"
tmux select-window -t "$name":0
tmux split-window "/bin/bash -l -c ssh\\ $host2"
tmux split-window -h -t 0 "/bin/bash -l -c ssh\\ $host3"
tmux select-window -t "$name":1
tmux split-window -h -t 2 "/bin/bash -l -c ssh\\ $host4"
tmux setw synchronize-panes
tmux a -d -t "$name"
# Otherwise, add a new window to the current session with all four sessions.
else
tmux new-window -n "$name" "/bin/bash -l -c ssh\\ $host1"
tmux select-window -t "$name"
tmux split-window "/bin/bash -l -c ssh\\ $host2"
tmux select-window -t "$name"
tmux split-window -h -t 0 "/bin/bash -l -c ssh\\ $host3"
tmux select-window -t "$name"
tmux split-window -h -t 2 "/bin/bash -l -c ssh\\ $host4"
tmux setw synchronize-panes
tmux select-window -t "$name"
fi
}
# main
if [ "$(basename $0)" == "tmux-hosts" ]; then
while getopts 'g:hi:o:v' OPTION; do
case "${OPTION}" in
g) group="${OPTARG}" ;;
h) echo Open Ansible hosts in TMUX panes.; usage 0 ;;
i) inventory="${OPTARG}" ;;
o) offset="${OPTARG}" ;;
v) set -x ;;
*) usage 1 ;;
esac
done
if [ -z "$inventory" ]; then
inventory=$(grep -E ^inventory ~/.ansible.cfg | cut -f 2 -d '=')
fi
tmuxHosts $(ansible -i "$inventory" --list-hosts "$group"\
| grep -v hosts\ \( \
| sed 's/\s\+//g' \
| if [ $offset -gt 0 ]; then tail -n +"${offset}"; else cat; fi \
| head -n 4 \
| tr '\n' ' ')
fi
+68
View File
@@ -0,0 +1,68 @@
---
# deploy.yml
#
# This playbook details how an entire datacenter should be deployed
#
# Parameters:
# threads: Number of threads to use; default is 16.
#
- hosts: managed
serial: "{{ threads | default('16') }}"
gather_facts: true
ignore_unreachable: true
roles:
- ShadowArch
- SSH
- Sharingan
- hosts: physical
gather_facts: true
ignore_unreachable: true
roles:
- hardware
- hosts: Yggdrasil
gather_facts: true
ignore_unreachable: true
roles:
- Aether
- Foundation
- Grimoire
- IRC
- Password
- SSL
- TheRaven
- WebServer
- WolfPack
- Yggdrasil
- hosts: DarkNet
order: sorted
serial: "{{ threads | default('16') }}"
gather_facts: true
ignore_unreachable: true
vars_files:
- "{{ lookup('env', 'ANSIBLE_VAULT_FILE') }}"
roles:
- DarkNet
- WolfPack
- hosts: "{{ item }}"
gather_facts: true
ignore_unreachable: true
roles:
- "{{ item }}"
loop:
- Chappaai
- Maat
- Geth
- Node
- Vergil
#- DedSec
#- BT
- hosts: Node3
gather_facts: true
ignore_unreachable: true
roles:
- Cyberbrain
BIN
View File
Binary file not shown.
+368
View File
@@ -0,0 +1,368 @@
all:
vars:
# Environment-wide data
external_domain: "aninix.net"
external_subdomains: "cyberbrain foundation irc lykos maat password sharingan singularity superintendent www yggdrasil"
internal_subdomains: "ircservices"
hosted_domains: "travelpawscvt.com"
replica_domain: "MSN0.AniNIX.net"
time_zone: "America/Chicago"
# Services used by all
main_subnet: 10.0.1.0
router: 10.0.1.1
netmask: 24
dhcprange: '10.0.1.224,10.0.1.254,255.255.255.0,12h'
staticrange: '10.0.1.1,10.0.1.223,255.255.255.0,12h'
dns: "10.0.1.2"
logserver: "10.0.1.16"
webfront: "10.0.1.3"
mirroruri: "http://Maat.MSN0.AniNIX.net:9129/repo/archlinux/$repo/os/$arch"
# Standards
daemon_shell: /sbin/nologin
user_shell: /bin/bash
ansible_become_method: sudo
ansible_become_user: root
static: false
wireless_ssid: 'Shadownet'
ansible_python_interpreter: auto_silent
aether_primary: 'Yggdrasil'
ldap:
server: "10.0.1.3"
orgdn: "dc=aninix,dc=net"
binduser: 'binduser'
userou: 'ou=People'
groupou: 'ou=Group'
filter: '(&(objectClass=person)(!(pwdReset=TRUE)))'
organization: # Information about the group
admin: 'DarkFeather'
email: 'ircs://irc.aninix.net:6697/DarkFeather'
displayname: 'AniNIX'
gpgkey: '904DE6275579CB589D85720C1CC1E3F4ED06F296'
ssl: # Standard SSL cryptographic standards
identity: 'aninix.net-0002' # The Let's Encrypt identity to use
ciphersuite: "!NULL:!SSLv2:!SSLv3:!TLSv1:EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH"
Aether_nodes:
- DedSec.msn0.aninix.net
operational_countries:
- 'US'
# https://github.com/ansible/ansible/issues/86122
ansible_ssh_common_args: '-o "SetEnv TERM=dumb"'
children:
managed:
children:
physical: # 10.0.1.0/28
hosts:
Chappaai:
ipinterface: eth0
ip: 10.0.1.2
mac: e4:5f:01:01:ff:9b
static: true
children:
Node:
hosts:
Node1:
ipinterface: enp1s0
ip: 10.0.1.5
mac: fa:ec:43:87:4d:2d
tap: true
ups: 'apc'
active_vms:
- Yggdrasil
Node2:
ipinterface: enp1s0
ip: 10.0.1.7
mac: 56:02:ef:2c:1f:7c
tap: true
active_vms:
- DarkNet
- Maat
- Sharingan
- Superintendent
Node3:
ipinterface: enp1s0
ip: 10.0.1.8
mac: b2:c6:2c:02:b2:6e
tap: true
active_vms:
- TDS-Jump
active_containers:
- 'takserver-5.4-RELEASE-17': 'takserver:5.4-RELEASE-17'
- 'takserver-db-5.4-RELEASE-17': 'takserver-db:5.4-RELEASE-17'
- 'filestash': 'machines/filestash'
- 'filestash_oods': 'onlyoffice/documentserver'
- 'geth-rancher': 'rancher/rancher'
Node4:
ansible_user: depriv
ipinterface: enp1s0
ip: 10.0.1.6
mac: c8:ff:bf:0c:71:94
tap: true
ups: 'apc'
active_vms:
- Yggdrasil
pitest:
hosts:
Geth0:
ipinterface: eth0
ip: 10.0.1.9
mac: b8:27:eb:09:a1:a0
static: true
Geth5:
ipinterface: eth0
ip: 10.0.1.14
mac: b8:27:eb:81:f5:4b
static: true
Geth:
vars:
geth_primary: Geth1
hosts:
Geth1:
ipinterface: eth0
ip: 10.0.1.10
mac: e4:5f:01:01:ff:d5
static: true
Geth2:
ipinterface: eth0
ip: 10.0.1.11
mac: e4:5f:01:01:ff:9c
static: true
Geth3:
ipinterface: eth0
ip: 10.0.1.12
mac: e4:5f:01:01:ff:96
static: true
Geth4:
ipinterface: eth0
ip: 10.0.1.13
mac: e4:5f:01:01:ff:e4
static: true
virtual: # 10.0.1.16/28
vars:
hosts:
Sharingan:
ip: 10.0.1.16
ipinterface: ens3
mac: 00:15:5d:01:02:10
cores: 4
memory: 6
vnc: 8
bridge: br0
uefi: true
siem: true
disks:
- '-drive format=raw,index=0,media=disk,file=/dev/sdc'
# On hold because of https://aninix.net/DarkFeather/MSN0/issues/6
holdpkg: "elasticsearch graylog mongodb44-bin mongodb-tools-bin"
DarkNet:
ipinterface: ens3
ip: 10.0.1.17
mac: 00:15:5d:01:02:05
cores: 2
memory: 2
vnc: 9
bridge: br0
disks:
- '-drive format=raw,index=0,media=disk,file=/dev/sdb'
wolfpack_config: 'gitea@foundation.aninix.net:DarkFeather/WolfPack-Config.git'
Maat:
ip: 10.0.1.18
ipinterface: ens3
mac: 00:15:5d:01:02:07
cores: 2
memory: 2
bridge: br0
vscan_enabled: true
vnc: 7
disks:
- '-drive format=qcow2,l2-cache-size=8M,file=/mnt/cage2/vm/Maat.qcow2'
Yggdrasil:
ipinterface: ens3
ip: 10.0.1.3
mac: 00:25:90:0d:6e:86
static: true
sslidentity: aninix.net-0002
secdetection: true
iptv_location: "ToonamiAftermathEast.us|TVSClassicMovies.us|UniversalComedy|ABCNewsLive"
aether_source: true
cores: 8
memory: 10
bridge: br0
vnc: 1
vscan_enabled: true
discord_mapping:
therafters: therafters
sharingan: sharingan
tech: tech
foundation: foundation
3nclave: 3NCLAVE
martialarts: martialarts
signups: masignups
workouts: maworkouts
town-hall: citizens
121st-signups: 121st-signups
disks:
- '-device virtio-scsi-pci,id=scsi0 -drive file=/dev/sda,if=none,format=raw,discard=unmap,aio=native,cache=none,id=sda -device scsi-hd,drive=sda,bus=scsi0.0'
- '-device virtio-scsi-pci,id=scsi1 -drive file=/dev/sdb,if=none,format=raw,discard=unmap,aio=native,cache=none,id=sdb -device scsi-hd,drive=sdb,bus=scsi1.0'
- '-device virtio-scsi-pci,id=scsi2 -drive file=/dev/sdc,if=none,format=raw,discard=unmap,aio=native,cache=none,id=sdc -device scsi-hd,drive=sdc,bus=scsi2.0'
- '-device virtio-scsi-pci,id=scsi3 -drive file=/dev/sdd,if=none,format=raw,discard=unmap,aio=native,cache=none,id=sdd -device scsi-hd,drive=sdd,bus=scsi3.0'
Vergil: # 10.0.1.32/28
vars:
motion_enabled: yes
hosts:
Vergil1:
ip: 10.0.1.32
mac: b8:27:eb:e3:ff:59
rotate: 0
remote: NS-RC4NA-14
Vergil2:
ip: 10.0.1.33
mac: b8:27:eb:cf:26:88
motion_enabled: no
rotate: 180
remote: NS-RC4NA-14
Vergil3:
ip: 10.0.1.34
mac: b8:27:eb:60:73:68
rotate: 90
remote: LG-AKB73715608
unmanaged:
children:
# Both OVA groups are in the same subnet -- test_ovas aren't monitored
ovas: # 10.0.1.48/28
hosts:
Superintendent:
ip: 10.0.1.49
mac: de:8b:9e:19:55:1e
cores: 2
memory: 2
vnc: 6
bridge: br0
uefi: true
disks:
- '-drive format=qcow2,l2-cache-size=8M,file=/mnt/cage2/vm/hassos_ova-5.13.qcow2'
test_ovas: # 10.0.1.48/28
hosts:
TDS-Jump:
ip: 10.0.1.48
mac: 00:15:5d:01:02:08
cores: 2
memory: 2
vnc: 4
bridge: br0
disks:
- '-drive format=qcow2,l2-cache-size=8M,file=/srv/node/vm/TDSJump.qcow2'
DedNet:
ip: 10.0.1.50
mac: 00:15:5d:01:02:09
cores: 2
memory: 2
vnc: 3
bridge: br0
disks:
- '-drive format=qcow2,l2-cache-size=8M,file=/mnt/cage2/vm/DedNet.qcow2'
- '-cdrom /srv/node/iso/kali-linux.iso -boot order=d'
Aether:
ip: 10.0.1.51
mac: 00:15:5d:01:02:11
cores: 2
memory: 2
vnc: 5
bridge: br0
disks:
- '-drive if=none,id=disk0,cache=none,format=raw,aio=native,file=/dev/sdc'
- '-cdrom /srv/node/iso/archlinux.iso -boot order=d'
test1:
ip: 10.0.1.52
ipinterface: ens3
mac: 00:15:5d:01:02:06
cores: 2
memory: 2
bridge: br0
vnc: 10
disks:
- '-drive format=qcow2,l2-cache-size=8M,file=/mnt/cage2/vm/test1.qcow2'
test2:
ip: 10.0.1.53
ipinterface: ens3
mac: 00:15:5d:01:02:03
cores: 2
memory: 2
bridge: br0
vnc: 11
disks:
- '-drive format=qcow2,l2-cache-size=8M,file=/mnt/cage2/vm/test2.qcow2'
test3:
ip: 10.0.1.54
ipinterface: ens3
mac: 00:15:5d:01:02:04
cores: 2
memory: 2
bridge: br0
vnc: 12
disks:
- '-drive format=qcow2,l2-cache-size=8M,file=/mnt/cage2/vm/test3.qcow2'
# appliances are monitored -- adhoc_appliances are convenience only and not monitored.
appliances:
hosts: # 10.0.1.64/27
Shadownet: # Router must be at root
ip: 10.0.1.1
mac: 2c:30:33:64:f4:03
Print: # Print is excepted for legacy setup reasons before we laid out subnets.
ip: 10.0.1.6
mac: 00:80:92:77:ce:e4
Geth-Eyes:
ip: 10.0.1.68
mac: 9c:a3:aa:33:a3:99
# "Core-Console":
# ip: 10.0.1.74
# mac: 00:25:90:0D:82:5B
# "Node0-Console":
# ip: 10.0.1.75
# mac: 00:25:90:3E:C6:8C
adhoc_appliances:
hosts: # 10.0.1.64/27
DarkFeather:
ip: 10.0.1.64
mac: f4:2b:8c:10:31:44
Lykos:
ip: 10.0.1.65
mac: 70:74:14:4f:8e:42
Node0:
ip: 10.0.1.66
mac: 70:32:17:46:49:89
LivingRoomTV:
ip: 10.0.1.69
mac: 80:d2:1d:17:63:0e
BedRoomTV:
ip: 10.0.1.70
mac: a4:77:33:4c:2a:44
TrainingRoomTV:
ip: 10.0.1.71
mac: 80:d2:1d:17:63:10
BT:
ip: 10.0.1.72
mac: 8a:00:aa:7f:df:d1
DedSec:
ip: 10.0.1.73
mac: d4:e9:8a:7d:79:b3
# dhcp build space: 10.0.1.224/27
iot: # 10.0.2.0/24
hosts:
# Nest Thermostat
LivingRoomRegulator:
ip: 10.0.2.2
mac: 64:16:66:08:57:f5
# Nest Protect
Monitor:
ip: 10.0.2.3
mac: 18:b4:30:2f:f1:37
# Chamberlain My-Q
Gatekeeper:
ip: 10.0.2.4
mac: 64:52:99:14:28:2b
# iRobot Roomba
# CaretakerAlpha has no network
CaretakerBravo:
ip: 10.0.2.5
mac: 40:9f:38:95:06:34
# CaretakerCharlie has no network
@@ -0,0 +1,27 @@
# This playbook disables the archlinux-keyring-wkd-sync.service and timer, because they tend to fail for bad reasons.
#
---
- hosts: managed
ignore_errors: true
gather_facts: true
become: yes
tasks:
- name: Disable services & timers
when: ansible_os_family == "Archlinux"
service:
name: "{{ item }}"
state: stopped
enabled: no
loop:
- archlinux-keyring-wkd-sync.timer
- archlinux-keyring-wkd-sync.service
- name: Reset failed
when: ansible_os_family == "Archlinux"
command: "systemctl reset-failed {{ item }}"
loop:
- archlinux-keyring-wkd-sync.timer
- archlinux-keyring-wkd-sync.service
+61
View File
@@ -0,0 +1,61 @@
---
# patching.yml
#
# This playbook can be used to patch all the servers in an inventory to the latest on the repo servers
# Variables:
# - hosts: the host grouper in the inventory -- default: all
# - action: update or upgrade -- default: update
# - delay: minutes to wait after a reboot -- default 5
#
#
# Patch then restart a node
- hosts: "{{ targets | default('geth_hubs') }}"
order: sorted
ignore_unreachable: true
serial: 1
vars:
ansible_become: yes
ansible_become_method: sudo
oldmajor: stretch
newmajor: buster
tasks:
- name: Check /var free percentage
command: /bin/bash -c "df -m /var | tail -n 1 | awk '{ print $5; }' | sed 's/%//' "
become: no
register: df_output
- name: Verify /var space
assert:
that:
- 90 > {{ df_output.stdout }}
fail_msg: "Not enough free space"
- apt:
name: python-apt
state: present
- name: apt dist-upgrade
apt:
update_cache: yes
upgrade: dist
ignore_errors: yes
- name: Replace repo
command: "sed -i 's/{{ oldmajor }}/{{ newmajor }}/g' /etc/apt/sources.list"
become: yes
- name: Update packages
apt:
upgrade: full
update_cache: yes
autoremove: yes
autoclean: yes
ignore_errors: yes
# - name: Perform firmware-update
# command: rpi-update
# become: yes
- reboot:
- wait_for_connection:
+29
View File
@@ -0,0 +1,29 @@
# ---
# one-role.yml
#
# Test a single role against a host or group of hosts.
#
# Parameters:
# targets: group in the inventory to use
# threads: number of simultaneous executions
# role: role to run
# sshport (optional): override 22/tcp/ssh for Ansible control
#
# Expects ANSIBLE_VAULT_FILE to be set in the environment to path the vault
# Also set ANSIBLE_VAULT_PASSWORD_FILE to your password file location if you want it.
#
- hosts: "{{ targets | default('all') }}"
order: sorted
serial: "{{ threads | default('8') }}"
gather_facts: true
ignore_unreachable: true
vars:
ansible_ssh_port: "{{ sshport | default('22') }}"
therole: "{{ role | default('Uptime') }}"
ansible_become_password: "{{ passwords[inventory_hostname] }}"
vars_files:
- "{{ lookup('env', 'ANSIBLE_VAULT_FILE') }}"
roles:
- "{{ therole }}"
+27
View File
@@ -0,0 +1,27 @@
---
# patching.yml
#
# Variables:
# - hosts: what hosts in the inventory to use
# - threads: how many to check in parallel
- hosts: "{{ hosts | default('managed') }}"
order: sorted
serial: "{{ threads | default('4') }}"
ignore_unreachable: true
vars:
ansible_become: no
tasks:
- name: Check updates
yum:
list=updates
update_cache=true
ignore_errors: true
register: yumupdates
- name: Patching succeeded
ignore_errors: true
assert:
that:
- yumupdates.results|length == 0
- df_output.stdout is search("rhel-7-server-rpms-nist")
+31
View File
@@ -0,0 +1,31 @@
---
# patching.yml
#
# This playbook can be used to patch all the servers in an inventory to the latest software available.
# Because we typically encrypt our disk storage, we don't wait for the connection to become available again.
# Variables:
# - target: the host grouper in the inventory -- default: all
#
# Patch then restart a node
#
#
- hosts: "{{ targets | default('virtual') }}"
order: sorted
serial: 4
vars:
ansible_become: yes
ansible_become_method: sudo
roles:
- patching
- hosts: physical
order: sorted
serial: 4
vars:
ansible_become: yes
ansible_become_method: sudo
tasks:
- include_role:
name: patching
when: targets is unset
+33
View File
@@ -0,0 +1,33 @@
---
- hosts: "{{ targets | default('all') }}"
become: true
gather_facts: false
tasks:
- name: Clean
command: rm -Rf /etc/pacman.d/gnupg
- name: Initialize keyring
command: /usr/bin/pacman-key --init
- name: Add ArchLinux
command: /usr/bin/pacman-key --populate archlinux
- name: Add AniNIX
command: /usr/bin/pacman-key --populate aninix
- name: Locally sign AniNIX
command: /usr/bin/pacman-key --lsign 904DE6275579CB589D85720C1CC1E3F4ED06F296
- name: Update DB
command: /usr/bin/pacman-key --updatedb
- name: Update packages
pacman:
name:
- archlinux-keyring
- ShadowArch
state: latest
update_cache: true
+1
View File
@@ -0,0 +1 @@
../roles/
+39
View File
@@ -0,0 +1,39 @@
# ---
# sshkey.yml
#
# ssh-keyscan and copy your SSH key to hosts
#
# Parameters:
# targets: group in the inventory to use
# threads: number of simultaneous executions
# pubkey: file to hand off
# sshport (optional): override 22/tcp/ssh for Ansible control
#
# Expects ANSIBLE_VAULT_FILE to be set in the environment to path the vault
#
- hosts: "{{ targets | default('managed') }}"
order: sorted
serial: "{{ threads | default('8') }}"
gather_facts: true
ignore_unreachable: true
vars:
ansible_ssh_password: "{{ passwords[inventory_hostname] }}"
ansible_ssh_port: "{{ sshport | default('22') }}"
keyfile: "{{ pubkey | default(lookup('env','HOME') + '/.ssh/id_ed25519.pub') }}"
vars_files:
- "{{ lookup('env', 'ANSIBLE_VAULT_FILE') }}"
tasks:
# Scanning SSH keys has been replaced with ../bin/generate-ssh-keyscan
- name: Get key
delegate_to: localhost
command: "cat {{ keyfile }}"
register: key
- authorized_key:
user: "{{ ansible_user_id }}"
key: "{{ key.stdout }}"
state: present
exclusive: true
name: "Pass authorized key"
+28
View File
@@ -0,0 +1,28 @@
# ---
# one-role.yml
#
# Test a single role against a host or group of hosts.
#
# Parameters:
# targets: group in the inventory to use
# threads: number of simultaneous executions
# variablename: the variable to print
# sshport (optional): override 22/tcp/ssh for Ansible control
#
# Expects ANSIBLE_VAULT_FILE to be set in the environment to path the vault
# Also set ANSIBLE_VAULT_PASSWORD_FILE to your password file location if you want it.
#
- hosts: "{{ targets | default('managed') }}"
order: sorted
serial: "{{ threads | default('8') }}"
gather_facts: true
ignore_unreachable: true
vars:
ansible_ssh_port: "{{ sshport | default('22') }}"
variablename: "{{ variable | default('ansible_os_family') }}"
vars_files:
- "{{ lookup('env', 'ANSIBLE_VAULT_FILE') }}"
tasks:
- debug:
msg: "{{ lookup('vars',variablename) | default('undefined') }}"
+52
View File
@@ -0,0 +1,52 @@
---
- hosts: "{{ targets | default('managed') }}"
become: true
tasks:
- name: Verify IP
ignore_errors: true
register: status
assert:
that:
- "ip in ansible_default_ipv4.address"
- debug:
msg: "Inventory IP {{ ip }} for {{ inventory_hostname }} doesn't match configured {{ ansible_default_ipv4.address }}"
when: status.failed
- name: Verify MAC
ignore_errors: true
register: status
assert:
that:
- "mac in ansible_default_ipv4.macaddress"
- debug:
msg: "Inventory MAC {{ mac }} for {{ inventory_hostname }} doesn't match configured {{ ansible_default_ipv4.macaddress }}"
when: status.failed
- name: Verify cores
ignore_errors: true
when: cores is defined
register: corescheck
assert:
that:
- "cores == ansible_processor_cores"
- debug:
msg: "Inventory {{ cores }} cores for {{ inventory_hostname }} doesn't match configured {{ ansible_processor_cores }}"
when: cores is defined and corescheck.failed
- name: Verify memory
ignore_errors: true
register: memcheck
when: memory is defined
assert:
that:
- "memory == (ansible_memtotal_mb - ansible_memtotal_mb % 1000)/ 1000 + 1 " # hasty rounding
- debug:
msg: "Inventory {{ memory }} GB memory for {{ inventory_hostname }} doesn't match configured {{ (ansible_memtotal_mb - ansible_memtotal_mb % 1000)/ 1000 + 1 }} GB"
when: memory is defined and memcheck.failed
+12
View File
@@ -0,0 +1,12 @@
#!/bin/bash
# Webserver apps directory should be short -- apps that fail this category should become their own.
retcode=0
for file in `find roles/WebServer/files/apps -type f`; do
if [[ $(wc -l "$file" | awk '{ print $1; }') -gt 10 ]]; then
echo "$file" is too long to be deployed as a mini-app under the WebServer role.
retcode=1
fi
done
exit $retcode
+58
View File
@@ -0,0 +1,58 @@
#!/usr/bin/bash
# File: find-bad-ipam
#
# Description: This file finds bad IPAM entries in an inventory.
#
# Package: AniNIX/Ubiqtorate
# Copyright: WTFPL
#
# Author: DarkFeather <ircs://aninix.net:6697/DarkFeather>
file="examples/msn0.yml"
function findBadTerm() {
### Check for a term to be duplicated.
# param file: the file
# param term: the term to search for duplicates
file="$1"
term="$2"
results="$(grep -i "$term:" "$file" | tr '[[:upper:]]' '[[:lower:]]' | sed 's/\s+'"$term"':\s*//' | sort | uniq -c | grep -vE '^\s+1\s+' )"
if [ -n "$results" ]; then
echo "Some ${term} entries are duplicated. Search for the above terms in your inventory and deduplicate."
echo "$results"
exit 2
fi
}
function Usage() {
### Helptext
# param retcode: what to return
retcode="$1"
echo "Usage: $0 -f SOMEFILE"
echo " $0 -h"
echo "Add -v for verbosity."
exit $retcode
}
while getopts 'f:hv' OPTION; do
### Parse arguments
case "$OPTION" in
f) file="$OPTARG" ;;
h) echo "Find bad IPAM entries in an inventory." ; Usage 0 ;;
v) set -x ;;
*) Usage 1 ;;
esac
done
# Sanity check
if [ -z "$file" ] || [ ! -f "$file" ]; then
echo Need an inventory to process.
Usage 3;
fi
# Check for the unique attributes.
for i in ip vnc mac; do
findBadTerm "$file" "$i"
done
+12
View File
@@ -0,0 +1,12 @@
#!/bin/bash
# Limit files in git to 1M.
IFS="
"
git ls-files | xargs -n1 du -k | grep -vE '^[[:digit:]]?[[:digit:]]?[[:digit:]][[:space:]]|venv|\s./.git/'
if [ $? -ne 1 ]; then
echo
echo "These files are probably larger than you want to commit to Git. Please try to find an alternate delivery path, such as a CDN or Git-LFS."
exit 1;
fi
+17
View File
@@ -0,0 +1,17 @@
#!/bin/bash
export IFS="
"
retcode=0
for macline in `grep -E '^\s+mac: ' examples/*.yml`; do
if [ "${macline}" != "${macline,,}" ]; then
mac="$( echo "${macline}" | awk '{ print $2; }')"
retcode=1
echo "${mac} has mismatched case -- should be lower."
sed -i "s/${mac}/${mac,,}/g" examples/*.yml
echo "Attempted replacement."
fi
done
exit $retcode
@@ -0,0 +1,14 @@
#!/bin/bash
retcode=0
for host in `ansible -i "examples/msn0.yml" --list-hosts managed | grep -v ' hosts '`; do
if [ ! -f roles/ShadowArch/files/motd/"$host" ]; then
echo "Need MOTD for $host"
retcode=1;
fi
if [ ! -f roles/Sharingan/files/monit/hostdefs/"$host" ]; then
echo "Need Sharingan-Data file for $host"
retcode=1;
fi
done
exit $retcode
+40
View File
@@ -0,0 +1,40 @@
#!/bin/bash
# Ignore Ansibilized templates.
saferegex='\{\{.+\}\}|secrets\['
# Ignore comments
saferegex="$saferegex"'|^[a-z,A-Z,0-9,_,-,/,.]+:\s*;|^[a-z,A-Z,0-9,_,-,/,.]+:\s*#|^[a-z,A-Z,0-9,_,-,/,.]+:\s*//|\s+[/]?[*][/]?\s+'
# AniNIX Constructs
saferegex="$saferegex"'|password.aninix.net|aur.list'
# Web constructs
saferegex="$saferegex"'|.css:|.html:|.md:|htdocs|htpasswd'
# Ignore template text to set policy
saferegex="$saferegex"'|_LENGTH|Set new|attempt|pwdchange'
# haveibeenpwned is referenced in comments
saferegex="$saferegex"'|haveibeenpwned'
# Unset variables.
saferegex="$saferegex"'|\s+=\s*$|\s+yes$|\s+no$'
# Ignore LDAP attributes
saferegex="$saferegex"'|pwpolicies|pwdLastSuccess|pwdAttribute|pwdMaxAge|pwdExpireWarning|pwdInHistory|pwdCheckQuality|pwdMaxFailure|pwdLockout|pwdLockoutDuration|pwdGraceAuthNLimit|pwdFailureCountInterval|pwdMustChange|pwdMinLength|pwdAllowUserChange|pwdSafeModify|pwdChangedTime|pwdPolicy|last changed their password on|/root/.ldappass'
# Ignore IRC Modules
saferegex="$saferegex"'|m_password_hash.so|/quote ns identify|SELECT|password_attribute|SET PASS|SASET PASS'
# Ignore SSH known hosts
saferegex="$saferegex""|ssh_known_hosts:|"
git ls-files roles/*/{files,templates} | xargs grep -irE 'secret|password|pw|passphrase|pass=' | grep -vE "$saferegex"
if [ $? -ne 1 ]; then
echo
echo If these are false positives, you need to add the signature to the whitelist in $0.
echo Otherwise, convert any files above to templates and encode the passphrase into your vault.
exit 1;
fi
IFS="
"
for i in `ansible-vault decrypt --output - ${ANSIBLE_VAULT_FILE} | sed 's/\s\?-\?\s\?[A-Za-z0-9_]\+://' | grep -vE '\||password|^\s\?$|#|https://' | sed "s/^ \+['\"]\?//" | sed "s/[\"']\s\?//" | sort | uniq`; do
grep -rlF "${i}" .
if [ $? -ne 1 ]; then
echo "A secret starting with $(echo "$i" | cut -c 1-7) was found in the files above."
exit 1;
fi
done
View File
+5
View File
@@ -0,0 +1,5 @@
pyaml
yamlpath
pytest
python3-nmap
simplejson
+7
View File
@@ -0,0 +1,7 @@
See [AniNIX/Aether](/AniNIX/Aether) for complete details of the tool.
Role requirements:
* `secrets['Aether']` in Vault
* A YAML list of nodes under the key `Aether_nodes` in Vault
* A host called 'Core' to act as the source
* 22/tcp/sftp access through firewalls to the Core host from any clients
@@ -0,0 +1,3 @@
#!/bin/bash
### Gitea ###
tar cvzf "$BACKUPDIR"/gitea.tgz /var/lib/gitea/data
@@ -0,0 +1,3 @@
#!/bin/bash
### Grimoire ###
sudo -u postgres pg_dumpall > "$BACKUPDIR"/grimoire.sql
@@ -0,0 +1,3 @@
#!/bin/bash
### IRC Services ###
cp /opt/anope/data/anope.db "$BACKUPDIR"
@@ -0,0 +1,9 @@
#!/bin/bash
### Wiki ###
mkdir "$BACKUPDIR"/wiki/
for i in `find /usr/share/webapps/ -maxdepth 1 -type d | grep mediawiki`; do
foldername="$(echo "$i" | rev | cut -f 1 -d '/' | rev)"
dbname="$(grep '^\$wgDBname' "$i"/LocalSettings.php | cut -f 2 -d \")"
$BACKUPCMD "${i}"/LocalSettings.php "$BACKUPDIR"/wiki/"$foldername"-localsettings.php
sudo -u postgres pg_dump "$dbname" > "$BACKUPDIR"/wiki/"$dbname".psql
done
@@ -0,0 +1,3 @@
#!/bin/bash
### Yggdrasil -- File & SHA list only for space reasons ###
cp /srv/yggdrasil/library.sha256 "$BACKUPDIR"/yggdrasil.library.sha256
+146
View File
@@ -0,0 +1,146 @@
# Example configuration file for AIDE.
# More information about configuration options available in the aide.conf manpage.
@@define DBDIR /var/lib/aide
@@define LOGDIR /var/log/aide
# The location of the database to be read.
database_in=file:@@{DBDIR}/aide.db.gz
# The location of the database to be written.
#database_out=sql:host:port:database:login_name:passwd:table
#database_out=file:aide.db.new
database_out=file:@@{DBDIR}/aide.db.new.gz
# Whether to gzip the output to database
gzip_dbout=yes
# Default.
log_level=warning
report_level=changed_attributes
report_url=file:@@{LOGDIR}/aide.log
report_url=stdout
#report_url=stderr
#
# Here are all the attributes we can check
#p: permissions
#i: inode
#n: number of links
#l: link name
#u: user
#g: group
#s: size
###b: block count
#m: mtime
#a: atime
#c: ctime
#S: check for growing size
#I: ignore changed filename
#ANF: allow new files
#ARF: allow removed files
#
# Here are all the digests we can use
#md5: md5 checksum
#sha1: sha1 checksum
#sha256: sha256 checksum
#sha512: sha512 checksum
#rmd160: rmd160 checksum
#tiger: tiger checksum
#haval: haval checksum
#crc32: crc32 checksum
#gost: gost checksum
#whirlpool: whirlpool checksum
# These are the default rules
#R: p+i+l+n+u+g+s+m+c+md5
#L: p+i+l+n+u+g
#E: Empty group
#>: Growing logfile p+l+u+g+i+n+S
# You can create custom rules - my home made rule definition goes like this
ALLXTRAHASHES = sha1+rmd160+sha256+sha512+whirlpool+tiger+haval+gost+crc32
ALLXTRAHASHES = sha1+rmd160+sha256+sha512+tiger
# Everything but access time (Ie. all changes)
EVERYTHING = R+ALLXTRAHASHES
# Sane, with multiple hashes
# NORMAL = R+rmd160+sha256+whirlpool
NORMAL = R+rmd160+sha256
# For directories, don't bother doing hashes
DIR = p+i+n+u+g+acl+xattrs
# Access control only
PERMS = p+i+u+g+acl
# Logfile are special, in that they often change
LOG = >
# Just do md5 and sha256 hashes
LSPP = R+sha256
# Some files get updated automatically, so the inode/ctime/mtime change
# but we want to know when the data inside them changes
DATAONLY = p+n+u+g+s+acl+xattrs+md5+sha256+rmd160+tiger
# Next decide what directories/files you want in the database.
/boot NORMAL
/bin NORMAL
/sbin NORMAL
/lib NORMAL
/lib64 NORMAL
/opt NORMAL
/usr NORMAL
/root NORMAL
# These are too volatile
!/usr/src
!/usr/tmp
# Check only permissions, inode, user and group for /etc, but
# cover some important files closely.
/etc PERMS
!/etc/mtab
# Ignore backup files
!/etc/.*~
/etc/exports NORMAL
/etc/fstab NORMAL
/etc/passwd NORMAL
/etc/group NORMAL
/etc/gshadow NORMAL
/etc/shadow NORMAL
/etc/security/opasswd NORMAL
/etc/hosts.allow NORMAL
/etc/hosts.deny NORMAL
/etc/sudoers NORMAL
/etc/skel NORMAL
/etc/logrotate.d NORMAL
/etc/resolv.conf DATAONLY
/etc/nscd.conf NORMAL
/etc/securetty NORMAL
# Shell/X starting files
/etc/profile NORMAL
/etc/bashrc NORMAL
/etc/bash_completion.d/ NORMAL
/etc/login.defs NORMAL
/etc/zprofile NORMAL
/etc/zshrc NORMAL
/etc/zlogin NORMAL
/etc/zlogout NORMAL
/etc/profile.d/ NORMAL
/etc/X11/ NORMAL
# Ignore logs
!/var/lib/pacman/.*
!/var/cache/.*
!/var/log/.*
!/var/run/.*
!/var/spool/.*
+27
View File
@@ -0,0 +1,27 @@
---
- name: Copy the key
become: true
copy:
dest: /home/aether/.ssh/aether
content: "{{ aether_key.stdout }}"
- name: Copy the public key
become: true
copy:
dest: /home/aether/.ssh/aether.pub
content: "{{ aether_key.stdout }}"
- name: Enable the service
become: yes
service:
name: aether.timer
state: enabled
running: yes
- name: Enable the service - 2
become: yes
service:
name: aether-gen.timer
state: disabled
running: no
+64
View File
@@ -0,0 +1,64 @@
---
- name: Install the package
become: true
ignore_errors: true
package:
name: Aether
state: present
- name: Validate the user
vars:
service_account: aether
include_tasks: ../roles/common/service_account.yml
- name: Ensure the Aether identity is protected.
become: true
file:
path: "{{ item }}"
state: directory
owner: aether
group: aether
mode: 0700
loop:
- /home/aether/.ssh
- /usr/local/etc/Aether
- /usr/local/etc/Aether/backup-entries
- /usr/local/backup
- name: Ensure the Aether identity exists
delegate_to: Core # Core will track the identity that will then be shared to everyone else.
become: true
command:
creates: /home/aether/.ssh/aether
chdir: /home/aether/.ssh/
cmd: ssh-keygen -t ed25519 -N "" -f ./aether
- name: Read the Aether identity
become: true
delegate_to: '{{ aether_primary }}'
command: cat /home/aether/.ssh/aether
register: aether_key
- name: Read the Aether public identity
become: true
delegate_to: '{{ aether_primary }}'
command: cat /home/aether/.ssh/aether.pub
register: aether_pubkey
- include_tasks: source.yml
when: "{{ inventory_hostname }} is {{ aether_primary }}"
- include_tasks: client.yml
when: "{{ inventory_hostname }} is {{ aether_primary }}"
- name: Ensure the Aether identity files are protected.
become: true
file:
path: "{{ item }}"
owner: aether
group: aether
mode: 0600
loop:
- /home/aether/.ssh/aether
- /home/aether/.ssh/aether.pub
+42
View File
@@ -0,0 +1,42 @@
---
- name: Copy the backup scripts
become: yes
copy:
src: "backup-entries/{{ inventory_hostname }}"
dest: "/usr/local/etc/Aether/backup-entries"
owner: aether
group: aether
- name: Seed the backup passphrase
become: yes
copy:
content: "{{ passwords['Aether'] }}"
dest: "/usr/local/etc/Aether/pass.txt"
owner: aether
group: aether
mode: 0600
- name: Enable the generation service
become: yes
when: "{{ inventory_hostname }} == 'Core'"
service:
name: aether-gen.timer
state: enabled
running: yes
- name: Enable the generation service - 2
become: yes
when: "{{ inventory_hostname }} == 'Core'"
service:
name: aether.timer
state: disabled
running: no
- name: Set up the authorized_keys
template:
src: authorized_keys.j2
dest: /home/aether/.ssh/authorized_keys
mode: 0600
owner: aether
group: aether
+18
View File
@@ -0,0 +1,18 @@
A Chappaai host is a gateway to accessing other hosts. It is a safeguard against admin error.
## Etymology
Chappaai hosts are named to follow the non-English naming of the Stargate network by the other denizens of the galaxy.
They are the first line of defense against administrative error -- similar to the way that [Stargate Command](https://stargate.fandom.com/wiki/Stargate_Command) was for Earth. They prevent admins from being locked out of correcting their changes and are connected to everything in the ecosystem. They also control DNS, which allows a sort of subliminal control of the entire ecosystem. This prevents infiltration by infections (similar to Goauld) and in fact can be the extinction of any DNS-enabled malware in the ecosystem by sinkholing the Command-and-Control.
## Capacity and Components
A Chappaai host needs minimal CPU or memory.
## Hosted Services and Entities
Chappaai should host a Pihole installation and [SSH](../Services/SSH.md). It should be linked by NAT to an obscure port to the outside world.
## Connections
Any host should be able to connect to a Chappaai with SSH and X11, and it should be able to dial to any service provider.
## Additional Reference
Chappaai hosts should be deployed alongside any Hypervisor. They can be as simple as a Pi-hole with SSH access, and they should be allowed to receive SSH connections from a non-tcp/22/ssh port.
+2
View File
@@ -0,0 +1,2 @@
PRIVACYLEVEL=0
RATE_LIMIT=1000/5
+80
View File
@@ -0,0 +1,80 @@
---
- name: Clone pi-hole
become: yes
git:
accept_newhostkey: yes
dest: /opt/pi-hole
repo: https://github.com/pi-hole/pi-hole.git
- name: Install pi-hole if needed
become: yes
register: pihole_install
command:
creates: /usr/bin/pihole-FTL
cmd: false # bash basic-install.sh
chdir: '/opt/pi-hole/automated install'
- name: Ensure pihole web admin password
become: yes
command: "pihole -a -p {{ passwords['Chappaai'] }}"
# when: pihole_install.changed
- name: Generate DNS/DHCP from inventory
delegate_to: localhost
run_once: true
command: "python3 ../bin/generate-pihole-dns-dhcp.py {{ inventory_file }}"
- name: Chappaai DNS
become: yes
register: dns_updated
copy:
dest: /etc/pihole/hosts/custom.list
src: dns
owner: pihole
group: pihole
mode: 0644
- name: Chappaai DHCP
become: yes
register: dhcp_updated
copy:
src: dhcp
dest: /etc/dnsmasq.d/04-pihole-static-dhcp.conf
owner: root
group: root
mode: 0644
- name: Chappaai Configuration
become: yes
register: conf_updated
copy:
src: pihole-FTL.conf
dest: /etc/pihole/pihole-FTL.conf
owner: root
group: root
mode: 0644
- name: Chappaai DHCP Leases dir
become: yes
file:
path: /var/lib/misc/
state: directory
owner: root
group: root
mode: 0777
- name: Chappaai DHCP Leases
become: yes
file:
path: /var/lib/misc/dnsmasq.leases
state: touch
owner: pihole
group: pihole
mode: 0660
- name: Reload services
become: yes
command: pihole restartdns
when: dns_updated.changed or dhcp_updated.changed or conf_updated.changed
+19
View File
@@ -0,0 +1,19 @@
Cyberbrain is a way to ensure that so long as a person is connected to the Internet and authorized, they're able to connect to, use, and control the AniNIX.
It can serve as an alternative to using the [Terminal & SSH add-on](https://www.home-assistant.io/common-tasks/supervised/#installing-and-using-the-ssh-add-on-requires-enabling-advanced-mode-for-the-ha-user) for [AniNIX/Geth](../Geth/) in cases where a separate security posture is needed for each.
# Etymology
A [cyberbrain](https://ghostintheshell.fandom.com/wiki/Cyberbrain) is a concept from the series *Ghost in the Shell*. It's the integration of a normal brain with electronic, usually networked components. Similarly, this app serves as a core bridge between the shell environment of the AniNIX and any authorized user.
# Relevant Files and Software
This service is deployed as a Docker image from [FileStash](https://www.filestash.app/docs/install-and-upgrade/). This image is pointed back at the AniNIX/Yggdrasil's SFTP service.
Configuration is done in [the app](http://10.0.1.8:8334/admin/). A unique password should be configured, and then the only authorized backend is SFTP with passthrough authentication on the 'username_and_password' strategy. The SFTP host is then jailed as AniNIX/Yggdrasil's internal IP and port, with the `{{ .user }}` and `{{ .password }}` attributes populated.
This app can be proxied to the outside world and protected by encryption & a web-application firewall. This happens through [a WebServer configuration file](/AniNIX/Ubiqtorate/src/branch/main/roles/WebServer/files/conf.d/Core/adhan.conf).
## Backups
No backup is needed.
# Available Clients
This uses the same clients as [AniNIX/WebServer](../WebServer). Any browser will do.
+27
View File
@@ -0,0 +1,27 @@
The DarkNet VM is the privacy protection of the AniNIX. The AniNIX does not believe in security by obscurity or in censorship; as such, everyone should have a voice. VPN access is an assurance to content despite censorship and obfuscation for cases where free speech would normally come with some form of repercussions, despite the UN standards for human rights.
# Etymology
The DarkNet is named for an anonymous network whose access is controlled only by the admins and whose usage is known only to them. It's entirely closed and anonymous.
# Capacity and Components
A basic VM to provide DarkNet functionality in an AniNIX replica only needs the following resources:
* [ShadowArch](/AniNIX/ShadowArch)
* 1 core
* 1024M of RAM
* Virtualized NIC
* 150G of storage for any [AniNIX/WolfPack](/AniNIX/WolfPack) downloads, preferably on a unique physical harddrive that can be pulled and drilled
# Hosted Services
The DarkNet uses a small package list. It uses a couple services to achieve its goals. First, it uses [NordVPN](http://nordvpn.com/) to protect all traffic -- very simply, all one has to do to connect to the VPN is to run `nordvpn connect` and provide your login credentials to the service. We also use TOR for further anonymity -- torsocks and tor-browser-en provide functionality to cover that.
We recommend whitelisting your replica's subnet so that NordVPN doesn't see local traffic and services like log aggregation and administration can happen without exposing access across the VPN.
```
nordvpn whitelist add subnet $subnet/$cidr
```
## Abilities
* Encrypted storage by default to a passphrase known only to admins.
* Tor proxy service, integrated with both text lynx and GUI tor-browser-en browsers.
* Lynx is aliased to "torsocks lynx" globally
* Anonymous VPN via NordVPN
+69
View File
@@ -0,0 +1,69 @@
---
- name: DarkNet packages
become: yes
package:
name:
- deluge
- deluge-gtk
- openvpn
- nordvpn-bin
- tor
- torsocks
- tor-browser-en
- name: OpenVPN config
become: yes
get_url:
url: "{{ secrets.DarkNet.vpnserver }}"
dest: /etc/openvpn/client/darknet.conf
mode: 0600
owner: openvpn
group: network
# Must ensure that we have the latest.
force: true
- name: OpenVPN Auth part 1
become: yes
lineinfile:
path: /etc/openvpn/client/darknet.conf
regexp: ^auth-user-pass
line: auth-user-pass /etc/openvpn/client/darknet.auth
- name: OpenVPN Auth part 2
become: yes
lineinfile:
path: /etc/openvpn/client/darknet.conf
regexp: ^dev
line: dev tun0
- name: OpenVPN Auth part 3
become: yes
copy:
dest: /etc/openvpn/client/darknet.auth
content: "{{ secrets.DarkNet.token }}"
mode: 0600
owner: openvpn
group: network
- name: "Enable daemons"
become: yes
service:
name: "{{ item }}"
state: started
enabled: yes
loop:
- tor.service
- nordvpnd.service
- deluged.service
- openvpn-client@darknet.service
- name: BashRC customization
become: yes
copy:
dest: /etc/profile.d/darknet
content: |
alias torlynx='torsocks elinks https://check.torproject.org/'
mode: 0644
owner: root
group: root
+8
View File
@@ -0,0 +1,8 @@
---
# Consider https://blackarch.org/blackarch-guide-en.pdf
- name: Install DedSec packages
become: yes
package:
name:
- tcpdump
- wireshark
+51
View File
@@ -0,0 +1,51 @@
The Foundation is a one-stop shop for source code from AniNIX developers -- it's an open repository form which people can pull source code and recreate the entities being used by the AniNIX. You can view its web frontend from [https://aninix.net/foundation this webpage].
# Etymology
The etymology of the Foundation is twofold. First and foremost, the AniNIX attempts to automate any new package it is using as much as possible, and as such the Foundation holds the very basis on which the AniNIX is built.
Secondly, the Foundation is the third piece of the charity trinity for the AniNIX, along with the Wiki and the [https://aninix.net/pages/charity.php short-term charity projects]. The AniNIX puts a lot of time into designing its projects and making sure they work. Rather than forcing others to redo this work, we offer commented code and documentation so that the process is transparent but the work-by-hand is minimized.
# Relevant Files and Software
The Git system was created by the Linux project to manage changes to the kernel and has been on the rise for some time among Version Control Systems (VCS's) with projects like GitHub. The AniNIX self-hosts the repositories in [the Foundation server folder](file:///srv/foundation/) on Yggdrasil for the sake of the largest filesystem.
[WebServer](../WebServer) is configured to translate the repository to [https://foundation.aninix.net/](foundation.aninix.net) via the Gitea package. AniNIX projects will live under that organization. Review the package list at that link and identify the source packages you want to use. The UI will tell you how to copy the link to clone.
New packages should make sure to refer to the [Development Best Practices](/AniNIX/Wiki/) to ensure they are compliant with standards; if you notice an issue with the Foundation's code, make sure to submit a [[QANs|QAN]]. [[TeamGreen|AniNIX::TeamGreen]] should be running regressions on these projects.
You can use [https://aur.archlinux.org/packages/hexedit-advanced-search/ Hexedit] to edit [file:///usr/share/webapps/cgit/cgit.cgi cgit.cgi] to have a different name, such as "AniNIX::Foundation Web".
## Dependencies
*Note:* We used to declare the INSTALLER variable at the top of Makefiles, but no longer do. Non-ShadowArch installs should double check dependencies against the PKGBUILD files manually. We will try to keep this list short.
# Available Clients
To get a client to access the Foundation, use one of the following or visit
* ArchLinux: pacman -S git
* Ubuntu: apt-get install git
* RHEL/CentOS: yum install git
* Windows: [https://git-scm.com/download/win Git-Bash] is the recommended client.
* Please be aware that file paths and such are coded for Linux. Windows users will need to conduct extensive code review to install these packages.
* Users are also strongly recommended to install [https://www.gpg4win.org/index.html gpg4win] in order to sign commits with their GPG key.
* Mac: [https://git-scm.com/download/mac Go here]
Each package will need to be checked out individually.
# Equivalents or Competition
The most famous equivalent is [https://github.com](GitHub). Other source code control systems exist, including some provided by employers or academic institutions -- GitLab provides an enterprise-style implementation. Other protocol implementations vary widely -- Mercurial, Bazaar, and SVN are other revision control systems others use. We appreciate the flexibility of Git.
# Additional Reference
Some core Git tools are leveraged in specific ways for the AniNIX.
## Config for Author
[We don't use SMTP.](/AniNIX/Wiki/issues/8) We recommend GPG keys be created with your IRC address included, in the format `ircs://aninix.net:6697/$username`. This will throw some complaints if your project gets mirrored to GitHub, as GitHub wants your key to be verified through email, but within our ecosystem the commits will be verified.
To do this, see [our encryption article](https://aninix.net/AniNIX/Wiki/src/branch/main/Articles/Getting_Started_With_Encryption.md#GPG_Keys).
## Development Standards
If you are developing projects for the AniNIX organization or want to use our standards, ensure that the project is cloned with [AniNIX/Uniglot](/AniNIX/Uniglot)'s `uniglot-clone`. This will run pre-commit hooks to check your project.
## Branches for Functional Improvements
All major functional improvements being worked should be tracked in a branch. The branch name should be linked to the issue for which the branch was started or the functional concept's shortname.
## Filter-branch to Prune
Git maintains a history of all files. If you need to remove files permanently, GitHub maintains [an article](https://help.github.com/articles/removing-sensitive-data-from-a-repository/) on how to use `git filter-branch` to purge it.
@@ -0,0 +1,67 @@
#!/bin/bash
URI=https://aninix.net/assets/css/theme-gitea-dark.css
# Gitea arc-green palette
BOLDTEXT='#87ab63'
TEXT='#9e9e9e'
BGCOLOR='#383c4a'
ACCENTBG='#353945'
HEADERBG='#404552'
ROW='#2a2e3a'
HOVER='#a0cc75'
NAV='#2e323e'
# AniNIX palette
ANINIXBOLD='#df0000'
ANINIXTEXT='#ffffff'
ANINIXBG='#000000'
ANINIXACCENTBG='#303030'
ANINIXHEADERBG='#151515'
ANINIXROW='#2a2a2a'
ANINIXHOVER='#af0000'
ANINIXNAV='#000000'
(curl -ks "$URI"; echo; echo ".home a {
color: $ANINIXBOLD;
}
.bounding {
border: 1px solid #FFF;
border-radius: 15px;
margin: 0;
margin-top: 20px;
padding: 10px;
background-color: #000;
margin-bottom: 30px;
display: block;
}
body {
background-color: $ANINIXBG;
color: $ANINIXTEXT;
}
a {
color: $ANINIXBOLD;
}
") \
| sed "s/$BOLDTEXT/$ANINIXBOLD/gI" \
| sed "s/$TEXT/$ANINIXTEXT/gI" \
| sed "s/$ACCENTBG/$ANINIXACCENTBG/gI" \
| sed "s/$HEADERBG/$ANINIXHEADERBG/gI" \
| sed "s/$ROW/$ANINIXROW/gI" \
| sed "s/$NAV/$ANINIXNAV/gI" \
| sed "s/$HOVER/$ANINIXHOVER/gI" \
| sed "s/$BGCOLOR/$ANINIXBG/gI" > /var/lib/gitea/custom/public/assets/css/theme-aninix.css
cd /var/lib/gitea/web-snippets
head="$(curl -ks https://aninix.net/ | grep -B 99999 -E '^<div class="home"')"
foot="$(curl -ks https://aninix.net/ | grep -A 99999 -E '<footer>')"
for i in `find . -type f`; do
(echo "$head"
cat "$i"
echo "$foot") > /var/lib/gitea/custom/public/assets/"$i".html
done
# AniNIX Martial Arts Special Sauce
sed -i 's#/user/login?redirect_to=%2f#/user/login?redirect_to=%2FMartialArts#g' /var/lib/gitea/custom/public/assets/martialarts/index.html
@@ -0,0 +1,32 @@
<?php
/*
* Build a sitemap dynamically.
* Update Gitea's sitemap with: `php ./sitemap.php > /var/lib/gitea/custom/sitemap.xml`
*
* Builds according to https://www.sitemaps.org/protocol.html
*/
/* Globals */
$path="/srv/http/aninix.net/";
echo '<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
';
exec("(echo /srv/http/aninix.net/index.php; find /srv/http/aninix.net/pages -type f; find /srv/http/aninix.net/martialarts/ -type f) | grep -E \.php\$ | grep -vE ^./unlisted\|^./errors/\|head.php\|foot.php\|test\|Template\|darknet", $output);
foreach ($output as &$file) {
echo ' <url>
';
echo ' <loc>https://aninix.net/'.substr($file,strlen($path)).'</loc>
';
echo ' <lastmod>'.date('Y-m-d',filemtime($file)).'</lastmod>
';
echo ' </url>
';
}
/* Print footer */
echo '</urlset>
';
?>
@@ -0,0 +1,7 @@
#e11d21 Blocked ; There are functional or technical reasons this can't be implemented yet
#eb6420 Duplicate ; Another issue or PR already describes this issue
#bfd4f2 On-hold ; Evaluated but not enough resources to complete now
#009800 Peer-review ; Being reviewed for quality prior to merge
#207de5 RFC ; More information and feedback is needed
#fbca04 Wontfix ; Not a bug -- way it works
#9c4ac2 In-progress ; Being worked.
@@ -0,0 +1,31 @@
# http://www.wtfpl.net/about/
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
Version 2, December 2004
Copyright (C) 2004 Sam Hocevar <sam@hocevar.net>
Everyone is permitted to copy and distribute verbatim or modified
copies of this license document, and changing it is allowed as long
as the name is changed.
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. You just DO WHAT THE FUCK YOU WANT TO.
ANINIX ADDENDUM
Trademark 2017 (https://aninix.net/)
The "AniNIX" name and |> logo are trademarked as of 2017/11/21.
AniNIX materials may be reproduced and re-used (though you must
contact the admins of the network to get written permission to use
the AniNIX name or logo) so long as such reproduction or re-use
does not inhibit the original AniNIX use of the same.
Attribution is appreciated for other materials but not legally
required or necessary.
"AniNIX" trademark serial: 87177883
|> Logo trademark serial: 87177887
@@ -0,0 +1,31 @@
/* RSS Reading */
function insertNewsSnippet(snippet,tag) {
/* DOM XML handling has been too problematic, so we are now using git-hooks to pre-generate the snippet. This function injects that snippet.
* param snippet: URI for the snippet
* param tag: div tag to overwrite
*/
var http_request = false;
http_request = new XMLHttpRequest();
http_request.open("GET",snippet,true);
http_request.setRequestHeader("Cache-Control", "no-cache");
http_request.setRequestHeader("Pragma", "no-cache");
http_request.onreadystatechange = function() {
if (http_request.readyState == 4) {
if (http_request.status == 200) {
if (http_request.responseText != null) {
document.getElementById(tag).innerHTML = http_request.responseText;
} else {
alert("Failed to receive RSS file from the server - file not found.");
return false;
}
}
}
}
http_request.send(null);
}
/* Contact Obfuscation */
function insertContactInfo() {
document.getElementById('contact-insert').innerHTML = '<b>Contact Us:</b><br/>Emai' + 'l: aninix' + '@' + 'proto' + 'n.me <br/>Phone: (60' + '8) 56' + '1-3607';
}
+55
View File
@@ -0,0 +1,55 @@
<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<url>
<loc>https://aninix.net/</loc>
<lastmod>2020-09-20</lastmod>
</url>
<url>
<loc>https://aninix.net/martialarts/index.html</loc>
<lastmod>2020-09-20</lastmod>
</url>
<url>
<loc>https://foundation.aninix.net/</loc>
<lastmod>2020-09-20</lastmod>
</url>
<url>
<loc>https://foundation.aninix.net/explore/repos</loc>
<lastmod>2020-09-20</lastmod>
</url>
<url>
<loc>https://foundation.aninix.net/AniNIX/Wiki</loc>
<lastmod>2020-09-20</lastmod>
</url>
<url>
<loc>https://irc.aninix.net/</loc>
<lastmod>2020-09-20</lastmod>
</url>
<url>
<loc>https://password.aninix.net/</loc>
<lastmod>2020-09-20</lastmod>
</url>
<url>
<loc>https://maat.aninix.net/index.html</loc>
<lastmod>2020-09-20</lastmod>
</url>
<url>
<loc>https://singularity.aninix.net/</loc>
<lastmod>2020-09-20</lastmod>
</url>
<url>
<loc>https://wolfpack.aninix.net/</loc>
<lastmod>2020-09-20</lastmod>
</url>
<url>
<loc>https://yggdrasil.aninix.net/</loc>
<lastmod>2020-09-20</lastmod>
</url>
<url>
<loc>https://sharingan.aninix.net</loc>
<lastmod>2020-09-20</lastmod>
</url>
<!-- Unlisted:
lykos.aninix.net
adhan.aninix.net
-->
</urlset>
+9
View File
@@ -0,0 +1,9 @@
User-agent: *
Allow: /$
Allow: /issues
Allow: /pulls
Allow: /explore
Allow: /AniNIX/
Allow: /martialarts/
Allow: /sitemap.xml
Disallow: /
+47
View File
@@ -0,0 +1,47 @@
<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<url>
<loc>https://aninix.net/index.php</loc>
<lastmod>2019-10-24</lastmod>
</url>
<url>
<loc>https://aninix.net/pages/legal.php</loc>
<lastmod>2018-01-24</lastmod>
</url>
<url>
<loc>https://aninix.net/pages/wiki.php</loc>
<lastmod>2017-05-09</lastmod>
</url>
<url>
<loc>https://aninix.net/pages/martialarts.php</loc>
<lastmod>2018-09-18</lastmod>
</url>
<url>
<loc>https://aninix.net/pages/qr.php</loc>
<lastmod>2016-11-01</lastmod>
</url>
<url>
<loc>https://aninix.net/pages/social.php</loc>
<lastmod>2019-10-04</lastmod>
</url>
<url>
<loc>https://aninix.net/pages/webapps.php</loc>
<lastmod>2018-10-11</lastmod>
</url>
<url>
<loc>https://aninix.net/pages/downloads.php</loc>
<lastmod>2018-04-06</lastmod>
</url>
<url>
<loc>https://aninix.net/pages/charity.php</loc>
<lastmod>2018-04-06</lastmod>
</url>
<url>
<loc>https://aninix.net/pages/chatroom.php</loc>
<lastmod>2017-05-09</lastmod>
</url>
<url>
<loc>https://aninix.net/martialarts/index.php</loc>
<lastmod>2019-08-26</lastmod>
</url>
</urlset>
@@ -0,0 +1,3 @@
<a class="item" target="_blank" id="chat" href="https://irc.aninix.net/">Chat</a>
<a class="item" target="_blank" id="pwdchange" href="https://password.aninix.net/">Change Password</a>
<a class="item" id="martialarts" href="{{AppSubUrl}}/martialarts/">Martial Arts</a>
@@ -0,0 +1,9 @@
<!-- Replace Gitea icon with AniNIX -->
<script type="text/javascript">
document.getElementById('navbar').children[0].children[0].children[0].src="/assets/img/AniNIX.png";
$('meta[property=og\\:image]').attr('content', '/assets/img/AniNIX.png');
$('link[rel="mask-icon"]').attr('href', '/assets/img/AniNIX.png');
$('link[rel="mask-icon"]').attr('color', '#000000');
document.getElementById("pwdchange").setAttribute("target","_blank");
document.getElementById("chat").setAttribute("target","_blank");
</script>
@@ -0,0 +1,5 @@
<link rel="icon" type="image/png" href="/assets/img/AniNIX.png" />
<link rel="alternate" type="application/rss+xml" title="AniNIX/RSS" href="/aninix.xml" />
<link rel='apple-touch-icon' sizes='180x180' href='/assets/img/AniNIX.png' />
<meta name='apple-mobile-web-app-capable' content='yes' />
<script src="/assets/js/aninix.js"></script>
@@ -0,0 +1,123 @@
{{template "base/head" .}}
<!-- BEGIN CUSTOM HOME -->
<div class="home">
<!-- Title/Logo -->
<div class="ui stackable middle very relaxed page grid">
<div class="sixteen wide center aligned centered column">
<div>
<img class="logo" src="/assets/img/avatar_default.png" />
</div>
<div class="hero">
<h1 class="ui icon header title"> AniNIX </h1>
<h2>Welcome to the network</h2>
</div>
</div>
</div>
<!-- End title/logo -->
<!-- Top row -->
<div class="ui stackable middle very relaxed page grid">
<!-- Open-source widget -->
<div class="eight wide center column">
<h1 class="hero ui icon header">
<img width=20px height=20px src='/assets/img/icons/Foundation.png'/>
<a href="/explore/repos">Open source security</a>
</h1>
<p class="large">
The AniNIX's primary goal is to ensure everyone has access to the knowledge they need to build a low-cost, secure platform. We make all our source-code accessible and open-source.
</p>
</div>
<!-- IRC Widget -->
<div class="eight wide center column">
<h1 id="contact" class="hero ui icon header">
<img width=20px height=20px src='/assets/img/icons/IRC.png'/>
<a href='ircs://aninix.net:6697/#lobby'>Contact us anytime</a>
</h1>
<p class="large">
We run an open IRC network -- we'd love to connect with you there. Not familiar with IRC? No worries -- we have a <a href="https://irc.aninix.net/" target=_blank alt="AniNIX/IRC (Web)" id="webchat">webchat</a> available.
</p>
</div>
</div>
<!-- End top row -->
<!-- Bottom row -->
<div class="ui stackable middle very relaxed page grid">
<!-- AniNIX/Wiki widget -->
<div class="eight wide center column">
<h1 class="hero ui icon header">
<img width=20px height=20px src="/assets/img/icons/Wiki.png"/>
<a href="/AniNIX/Wiki">Open documentation</a>
</h1>
<p class="large">
We maintain a Wiki to document how and why we do what we do. Hopefully, it can both help others to learn more about computing and spark discussion with the community at large.
</p>
</div>
<!-- AniNIX/Maat widget -->
<div class="eight wide center column">
<h1 class="hero ui icon header">
<img width=20px height=20x src="/assets/img/icons/Maat.png"/>
<a href="https://maat.aninix.net/">Downloads</a>
</h1>
<p class="large">
We offer downloads from our AniNIX/Maat continuous-deployment system, including static files and packages for <a href="https://archlinux.org/">ArchLinux-style distributions.</a>
</p>
</div>
</div>
<!-- End bottom row -->
<hr style="margin-top: 50px;" />
<!-- Apps -->
<div class="ui stackable middle very relaxed page grid">
<div class="sixteen wide center aligned centered column hero">
<h2 id="apps">Webapps</h2>
<p>We host a number of web apps to make our users' lives easier.
</div>
<div class="four wide center column"><a title="AniNIX/Singularity" href="https://singularity.aninix.net"><img style="width: 50px; height:auto; margin: 0; padding: 0 auto;" alt=RSS src="/assets/img/icons/Singularity.png" /><p>Singularity</p></a><p>News powered by TT-RSS</p></div>
<div class="four wide center column"><a title="AniNIX/Yggdrasil" href="https://yggdrasil.aninix.net"><img style="width: 50px; height:auto; margin: 0; padding: 0 auto;" src="/assets/img/icons/Yggdrasil.png" /><p>Yggdrasil</p></a><p>Media powered by Emby</p></div>
<div class="four wide center column"><a title="AniNIX/Sharingan" href="https://sharingan.aninix.net"><img src="/assets/img/icons/Sharingan.png" style="width: 50px; height:auto; margin: 0; padding: 0 auto;" /><p>Sharingan</p></a><p>Monitoring powered by Graylog</p></div>
<div class="four wide center column"><a title="AniNIX/Cyberbrain" href="https://cyberbrain.aninix.net"><img src="/assets/img/icons/Cyberbrain.png" style="width: 50px; height:auto; margin: 0; padding: 0 auto;" /><p>Cyberbrain</p></a><p>SFTP Dropbox</p></div>
</div>
<!-- End apps -->
<hr style="margin-top: 50px;" />
<!-- News -->
<div class="ui stackable middle very relaxed page grid">
<div class="sixteen wide center aligned centered column">
<div class="hero" id="news"></div>
<script type="text/javascript">
insertNewsSnippet("https://aninix.net/assets/rss-snippets/aninix","news");
</script>
</div>
</div>
</div>
<!-- Social -->
<div class="ui stackable middle very relaxed page grid">
<div class="sixteen wide center aligned centered column">
<div class="hero" id="social">
<h2>Follow us on social media</h2>
<p>We want to stay in touch with you, so we are present on the social media platforms we find applicable.<br/> Have one you want us on? Contact us and let us know!</p>
</div>
</div>
<div class="two wide center column"><!--placeholder--><p>&nbsp;</p></div>
<div class="two wide center column"><a title=AniNIX/RSS href="/assets/aninix.xml"><img style="width: 50px; height:auto; margin: 0; padding: 0 auto;" alt=RSS src="/assets/img/social/rss.png" /></a></div>
<div class="two wide center column"><a title=Discord href="https://discord.gg/2bmggfR"><img alt=Discord style="width: 50px; height:auto; margin: 0; padding: 0 auto;" src="/assets/img/social/discord.ico" /></a></div>
<div class="two wide center column"><a title=GitHub href="https://github.com/AniNIX"><img alt=GitHub src="/assets/img/social/github.png" style="width: 50px; height:auto; margin: 0; padding: 0 auto;" /></a></div>
<div class="two wide center column"><a title=YouTube href="https://www.youtube.com/channel/UCe-WNM2mbI51xoVZp3K_wFQ"><img src="/assets/img/social/youtube.png" style="width: 50px; height:auto; margin: 0; padding: 0 auto;" /></a></div>
<div class="two wide center column"><a title=LinkedIn href="https://www.linkedin.com/groups/13577720"><img style="width: 50px; height:auto; margin: 0; padding: 0 auto;" src="/assets/img/social/linkedin.png" /></a></div>
<div class="two wide center column"><a title=Facebook href="https://facebook.com/aninixnetwork"><img style="width: 50px; height:auto; margin: 0; padding: 0 auto;" src="/assets/img/social/facebook.png" /></a></div>
<div class="two wide center column"><!--placeholder--><p>&nbsp;</p></div>
</div>
</div>
<!-- END CUSTOM HOME -->
{{template "base/footer" .}}
+51
View File
@@ -0,0 +1,51 @@
[Unit]
Description=Gitea (Git with a cup of tea)
After=syslog.target
After=network.target
After=mysqld.service
After=postgresql.service
After=memcached.service
After=redis.service
[Service]
User=gitea
Group=gitea
Type=simple
WorkingDirectory=~
RuntimeDirectory=gitea
LogsDirectory=gitea
StateDirectory=gitea
Environment=USER=gitea HOME=/var/lib/gitea GITEA_WORK_DIR=/var/lib/gitea GITEA_CUSTOM=/var/lib/gitea/custom/
ExecStart=/usr/bin/gitea web -c /var/lib/gitea/custom/conf/app.ini --custom-path=/var/lib/gitea/custom/
Restart=always
RestartSec=2s
ReadWritePaths=/var/lib/gitea/custom/conf/app.ini
AmbientCapabilities=
CapabilityBoundingSet=
LockPersonality=true
#Required by commit search
#MemoryDenyWriteExecute=true
NoNewPrivileges=True
#SecureBits=noroot-locked
PrivateDevices=true
PrivateTmp=true
PrivateUsers=true
ProtectClock=true
ProtectControlGroups=true
ProtectHome=true
ProtectHostname=true
ProtectKernelLogs=true
ProtectKernelModules=true
ProtectKernelTunables=true
ProtectProc=invisible
ProtectSystem=strict
RestrictAddressFamilies=AF_INET AF_INET6 AF_NETLINK AF_UNIX
RestrictNamespaces=true
RestrictRealtime=true
RestrictSUIDSGID=true
SystemCallArchitectures=native
SystemCallFilter=@system-service
SystemCallErrorNumber=EPERM
[Install]
WantedBy=multi-user.target
+10
View File
@@ -0,0 +1,10 @@
[Trigger]
Operation = Install
Operation = Upgrade
Type = Package
Target = gitea
[Action]
Description = Updating Gitea Custom Pages
When = PostTransaction
Exec = /usr/bin/runuser -u gitea -- /usr/bin/bash /var/lib/gitea/custom/bin/gen-aninix-custom
+10
View File
@@ -0,0 +1,10 @@
[Trigger]
Operation = Install
Operation = Upgrade
Type = Package
Target = gitea
[Action]
Description = Updating Gitea Custom Pages
When = PostTransaction
Exec = /usr/bin/runuser -u gitea -- /usr/bin/bash /var/lib/gitea/custom/bin/gen-aninix-custom
@@ -0,0 +1,117 @@
<!-- Title/logo-->
<div class="ui stackable middle very relaxed page grid">
<div class="sixteen wide center aligned centered column">
<!--<div class="ui negative message"><p>We are open despite COVID-19 -- those attending in person will need to sign a waiver of health and follow all state requirements, including wearing a mask.</p></div>-->
<div>
<img class="logo" src="/assets/img/icons/MartialArts.png" />
</div>
<div class="hero">
<h1 class="ui icon header title">
AniNIX Martial Arts
</h1>
<h2>Open-source, research-driven self-defense and personal health</h2>
<p>AniNIX Martial Arts is a small martial arts collective focusing on research-driven martial arts. Our core style is USHF HapKiDo, but we are influenced by many other systems. We are a research-driven group -- we encourage cross-training with other systems and will bring in new concepts regularly. The class is open to all experience levels, gender identity, gender expression, sexual orientation, religious or cultural identity, socioecomic status, or age (above 14), in Southcentral Wisconsin -- we will fit your training to your needs and goals.</p><p>Drop-ins are welcome, and registration is cheap. We hope you'll give us a chance to show you what we can do.</p>
</div>
</div>
</div>
<!-- End title/logo -->
<!-- Top row -->
<div class="ui stackable middle very relaxed page grid">
<!-- Open-source widget -->
<div class="eight wide center column">
<h1 class="hero ui icon header">
<img width=20px height=20px src='/assets/img/icons/Foundation.png'/>
<a href="/MartialArts/Wiki/src/branch/main/README.md">Open-source</a>
</h1>
<p>
We want your training with our system to become a part of your life. This means that we provide access to a revision-controlled copy of our notes that all our students can download, keep, and contribute to. We're tired of the old era where how the system works is kept hidden from students and piecemealed out as a marketing ploy -- we want to be as trasparent as possible in how our program and our martial art function. Transparency keeps our instructors honest and our students engaged -- this means a better martial arts experience for everyone.
</p>
</div>
<!-- Research widget -->
<div class="eight wide center column">
<h1 class="hero ui icon header">
<img width=20px height=20px src='/assets/img/ushf.jpg'/>
<a href='https://ushapkidofederation.wordpress.com/'>Research-driven</a>
</h1>
<p>
Our system is always growing. We are a United States HapKiDo Federation (USHF) school, and that gives us access to high-quality instructors and seminar material each year from across the US. We also maintain good relationships with other schools in our area -- we want our students to examine what they're learing and make sure that it works, and that means looking at different perspectives.
</p>
</div>
</div>
<!-- End top row -->
<!-- Bottom row -->
<div class="ui stackable middle very relaxed page grid">
<!-- Low-cost widget -->
<div class="eight wide center column">
<h1 class="hero ui icon header">
<img width=20px height=20px src="/assets/img/icons/MartialArts.png"/>
<a href="/martialarts/index.html#storefront">Low-cost</a>
</h1>
<p>We are non-profit group -- we train because we feel like it makes life better, not to make money. As such, our costs are publicly documented and our rates match the same. Classes will be informed of potential changes to costs well in advance, and we use recurring payments. We want you thinking about your training, not how you're going to pay for it.</p>
<p>
<ul style="text-align: left;">
<li><b>Cost:</b> Free</li>
<li><b>Open-mat:</b> Tuesdays 6-7 p.m.</li>
<li><b>Lessons:</b> Tuesdays 7-8:30 p.m.</li>
<li><b>Shaolin Workouts:</b> Saturday mornings at 8 a.m. </li>
<li><b>Location:</b> <a href="https://g.page/aninix-martial-arts?share">225 Blaser Drive, Belleville, WI</a></li>
<li><b>What to bring:</b> Exercise clothes and water</li>
<li id='contact-insert'>
<script type="text/javascript">
insertContactInfo();
</script>
</li>
</ul></p>
</div>
<!-- Real-life widget -->
<div class="eight wide center column">
<h1 class="hero ui icon header">
<img width=20px height=20x src="/assets/img/icons/IRC.png"/>
<a href="/martialarts/index.html#social">Real-life First</a>
</h1>
<p>
Everyone is welcome! Class attendance is not mandated and belt-testing is not required to train. As a courtesy, please inform the class of your absence or intended late arrival -- real-life comes first, and we're happy to work with your needs. As long as one person shows, we'll have class -- the smaller the class, the more tailored it is, but the bigger classes mean more partners and body types.</p>
<p>
Our focus is also on what you will actually use. While we appreciate traditional and esoteric training for self-development, our weekly classes are focused on modern techniques and training methods so that you get the most out of your time. Our goal is to help create a community of prepared and healthy citizens, and we believe martial arts helps build that in a way no other activity can.
</p>
</div>
</div>
<!-- End bottom row -->
<!-- News -->
<hr style="margin-top: 50px;" />
<div class="ui stackable middle very relaxed page grid">
<div class="sixteen wide center aligned centered column">
<div class=hero id=news>
<script type="text/javascript">
insertNewsSnippet("https://aninix.net/assets/rss-snippets/maqotw","news");
</script>
</div>
</div>
</div>
<!-- Social -->
<div class="ui stackable middle very relaxed page grid">
<div class="sixteen wide center aligned centered column">
<div class="hero" id=social>
<h2>Follow us on social media</h2>
<p class=large>We want to stay in touch with you, so we are present on the social media platforms we find applicable.<br/> Have one you want us on? Contact us and let us know!</p>
</div>
</div>
<div class="two wide center column"><p>&nbsp;</p></div>
<div class="two wide center column"><a title=RSS href="/martialarts/maqotw.xml"><img style="width: 50px; height:auto; margin: 0; padding: 0 auto;" alt=RSS src="/assets/img/social/rss.png" /></a></div>
<div class="two wide center column"><a title=Discord href="https://discord.gg/2bmggfR"><img alt=Discord style="width: 50px; height:auto; margin: 0; padding: 0 auto;" src="/assets/img/social/discord.ico" /></a></div>
<div class="two wide center column"><a title=NextDoor href="https://nextdoor.com/news_feed/?post=112835813"><img alt=NextDoor src="/assets/img/social/nextdoor.png" style="width: 50px; height:auto; margin: 0; padding: 0 auto;" /></a></div>
<div class="two wide center column"><a title=YouTube href="https://www.youtube.com/channel/UCVAkee-WaInnZbPn16bqzrw/about?view_as=subscriber"><img src="/assets/img/social/youtube.png" style="width: 50px; height:auto; margin: 0; padding: 0 auto;" /></a></div>
<div class="two wide center column"><a title=Strava href="https://www.strava.com/clubs/aninixmartialarts"><img style="width: 50px; height:auto; margin: 0; padding: 0 auto;" src="/assets/img/social/strava.png" /></a></div>
<div class="two wide center column"><a title=Facebook href="https://www.facebook.com/groups/aninixmartialarts/"><img style="width: 50px; height:auto; margin: 0; padding: 0 auto;" src="/assets/img/social/facebook.png" /></a></div>
<div class="two wide center column"><p>&nbsp;</p></div>
</div>
+73
View File
@@ -0,0 +1,73 @@
---
- name: Base packages
become: yes
package:
name:
- gitea
- name: Make directories
become: yes
file:
path: "/var/lib/gitea/{{ item }}"
owner: gitea
group: gitea
mode: 0750
loop:
- "custom/bin"
- "web-snippets"
- name: Populate config
become: yes
register: config
template:
src: app.ini.j2
dest: /etc/gitea/app.ini
owner: gitea
group: gitea
mode: 0750
- name: Copy web-snippets
become: yes
copy:
src: web-snippets/
dest: /var/lib/gitea/web-snippets
owner: gitea
group: gitea
mode: 0640
- name: Copy scripts
become: yes
copy:
src: custom/
dest: /var/lib/gitea/custom/
owner: gitea
group: gitea
- name: Publish AniNIX/Yggdrasil CSS
become: yes
get_url:
url: https://github.com/BenZuser/Emby-Web-Dark-Themes-CSS/raw/master/RED/theme.css
dest: /var/lib/gitea/custom/public/assets/css/emby-web-dark-theme-BenZuser.css
owner: gitea
group: gitea
- name: Copy hook
become: yes
copy:
src: gitea.hook
dest: /etc/pacman.d/hooks/gitea.hook
owner: gitea
group: gitea
- name: Generate pages
become: yes
register: custompages
command: /usr/bin/runuser -u gitea -- /usr/bin/bash /var/lib/gitea/custom/bin/gen-aninix-custom
- name: Restart service
become: yes
when: config.changed or custompages.changed
service:
name: gitea
state: restarted
enabled: yes
+741
View File
@@ -0,0 +1,741 @@
; This file lists the default values used by Gitea
; Copy required sections to your own app.ini (default is custom/conf/app.ini)
; and modify as needed.
; see https://docs.gitea.io/en-us/config-cheat-sheet/ for additional documentation.
; App name that shows in every page title
APP_NAME = AniNIX
; Change it if you run locally
RUN_USER = gitea
; Either "dev", "prod" or "test", default is "dev"
RUN_MODE = prod
WORK_PATH = /var/lib/gitea
[repository]
ROOT = repos
SCRIPT_TYPE = bash
; Default ANSI charset
ANSI_CHARSET =
; Force every new repository to be private
FORCE_PRIVATE = false
; Default privacy setting when creating a new repository, allowed values: last, private, public. Default is last which means the last setting used.
DEFAULT_PRIVATE = last
; Global limit of repositories per user, applied at creation time. -1 means no limit
MAX_CREATION_LIMIT = -1
; Preferred Licenses to place at the top of the List
; The name here must match the filename in conf/license or custom/conf/license
PREFERRED_LICENSES = AniNIX-WTFPL
; Disable the ability to interact with repositories using the HTTP protocol
DISABLE_HTTP_GIT = false
; Value for Access-Control-Allow-Origin header, default is not to present
; WARNING: This maybe harmful to you website if you do not give it a right value.
ACCESS_CONTROL_ALLOW_ORIGIN =
; Force ssh:// clone url instead of scp-style uri when default SSH port is used
USE_COMPAT_SSH_URI = false
; Close issues as long as a commit on any branch marks it as fixed
DEFAULT_CLOSE_ISSUES_VIA_COMMITS_IN_ANY_BRANCH = false
[repository.editor]
; List of file extensions for which lines should be wrapped in the CodeMirror editor
; Separate extensions with a comma. To line wrap files without an extension, just put a comma
LINE_WRAP_EXTENSIONS = .txt,.md,.markdown,.mdown,.mkd,
; Valid file modes that have a preview API associated with them, such as api/v1/markdown
; Separate the values by commas. The preview tab in edit mode won't be displayed if the file extension doesn't match
PREVIEWABLE_FILE_MODES = markdown
[repository.local]
; Path for local repository copy. Defaults to `tmp/local-repo`
LOCAL_COPY_PATH = tmp/local-repo
; Path for local wiki copy. Defaults to `tmp/local-wiki`
LOCAL_WIKI_PATH = tmp/local-wiki
[repository.upload]
; Whether repository file uploads are enabled. Defaults to `true`
ENABLED = true
; Path for uploads. Defaults to `data/tmp/uploads` (tmp gets deleted on gitea restart)
TEMP_PATH = data/tmp/uploads
; One or more allowed types, e.g. image/jpeg|image/png. Nothing means any file type
ALLOWED_TYPES =
; Max size of each file in megabytes. Defaults to 3MB
FILE_MAX_SIZE = 3
; Max number of files per upload. Defaults to 5
MAX_FILES = 5
[repository.pull-request]
; List of prefixes used in Pull Request title to mark them as Work In Progress
WORK_IN_PROGRESS_PREFIXES = WIP:,[WIP]
[repository.issue]
; List of reasons why a Pull Request or Issue can be locked
LOCK_REASONS = Too heated,Off-topic,Resolved,Spam
[cors]
; More information about CORS can be found here: https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#The_HTTP_response_headers
; enable cors headers (disabled by default)
ENABLED = false
; scheme of allowed requests
SCHEME = http
; list of requesting domains that are allowed
ALLOW_DOMAIN = *
; allow subdomains of headers listed above to request
ALLOW_SUBDOMAIN = false
; list of methods allowed to request
METHODS = GET,HEAD,POST,PUT,PATCH,DELETE,OPTIONS
; max time to cache response
MAX_AGE = 10m
; allow request with credentials
ALLOW_CREDENTIALS = false
[ui]
; Number of repositories that are displayed on one explore page
EXPLORE_PAGING_NUM = 20
; Number of issues that are displayed on one page
ISSUE_PAGING_NUM = 10
; Number of maximum commits displayed in one activity feed
FEED_MAX_COMMIT_NUM = 5
; Number of maximum commits displayed in commit graph.
GRAPH_MAX_COMMIT_NUM = 100
; Number of line of codes shown for a code comment
CODE_COMMENT_LINES = 4
; Value of `theme-color` meta tag, used by Android >= 5.0
; An invalid color like "none" or "disable" will have the default style
; More info: https://developers.google.com/web/updates/2014/11/Support-for-theme-color-in-Chrome-39-for-Android
THEME_COLOR_META_TAG = `#ff0000`
; Max size of files to be displayed (default is 8MiB)
MAX_DISPLAY_FILE_SIZE = 8388608
; Whether the email of the user should be shown in the Explore Users page
SHOW_USER_EMAIL = true
; Set the default theme for the Gitea install
DEFAULT_THEME = aninix
; All available themes. Allow users select personalized themes regardless of the value of `DEFAULT_THEME`.
THEMES = gitea-light,gitea-dark,aninix
; Whether the full name of the users should be shown where possible. If the full name isn't set, the username will be used.
DEFAULT_SHOW_FULL_NAME = false
; Disabling since we can check as a pre-commit hook
AMBIGUOUS_UNICODE_DETECTION = false
[ui.admin]
; Number of users that are displayed on one page
USER_PAGING_NUM = 50
; Number of repos that are displayed on one page
REPO_PAGING_NUM = 50
; Number of notices that are displayed on one page
NOTICE_PAGING_NUM = 25
; Number of organizations that are displayed on one page
ORG_PAGING_NUM = 50
[ui.user]
; Number of repos that are displayed on one page
REPO_PAGING_NUM = 15
[ui.meta]
AUTHOR = AniNIX/Foundation
DESCRIPTION = AniNIX/Foundation | Code, documentation, and information sharing powered by Gitea (git with a cup of tea)
KEYWORDS = go,git,self-hosted,gitea,aninix,aninix::foundation
[markdown]
; Enable hard line break extension
ENABLE_HARD_LINE_BREAK = false
; List of custom URL-Schemes that are allowed as links when rendering Markdown
; for example git,magnet
CUSTOM_URL_SCHEMES =
; List of file extensions that should be rendered/edited as Markdown
; Separate the extensions with a comma. To render files without any extension as markdown, just put a comma
FILE_EXTENSIONS = .md,.markdown,.mdown,.mkd
[server]
; The protocol the server listens on. One of 'http', 'https', 'unix' or 'fcgi'.
PROTOCOL = http
DOMAIN = {{ external_domain }}
ROOT_URL = https://{{ external_domain }}/
; The address to listen on. Either a IPv4/IPv6 address or the path to a unix socket.
HTTP_ADDR = 0.0.0.0
HTTP_PORT = 3000
; If REDIRECT_OTHER_PORT is true, and PROTOCOL is set to https an http server
; will be started on PORT_TO_REDIRECT and it will redirect plain, non-secure http requests to the main
; ROOT_URL. Defaults are false for REDIRECT_OTHER_PORT and 80 for
; PORT_TO_REDIRECT.
REDIRECT_OTHER_PORT = false
PORT_TO_REDIRECT = 3000
; Permission for unix socket
UNIX_SOCKET_PERMISSION = 660
; Local (DMZ) URL for Gitea workers (such as SSH update) accessing web service.
; In most cases you do not need to change the default value.
; Alter it only if your SSH server node is not the same as HTTP node.
; Do not set this variable if PROTOCOL is set to 'unix'.
LOCAL_ROOT_URL = %(PROTOCOL)s://%(HTTP_ADDR)s:%(HTTP_PORT)s/
; Disable SSH feature when not available
DISABLE_SSH = false
; Whether to use the builtin SSH server or not.
START_SSH_SERVER = false
; Username to use for the builtin SSH server. If blank, then it is the value of RUN_USER.
BUILTIN_SSH_SERVER_USER =
; Domain name to be exposed in clone URL
SSH_DOMAIN = foundation.aninix.net
; The network interface the builtin SSH server should listen on
SSH_LISTEN_HOST =
; Port number to be exposed in clone URL
SSH_PORT = 22
; The port number the builtin SSH server should listen on
SSH_LISTEN_PORT = %(SSH_PORT)s
; Root path of SSH directory, default is '~/.ssh', but you have to use '/home/git/.ssh'.
SSH_ROOT_PATH =
; Gitea will create a authorized_keys file by default when it is not using the internal ssh server
; If you intend to use the AuthorizedKeysCommand functionality then you should turn this off.
SSH_CREATE_AUTHORIZED_KEYS_FILE = true
; For the built-in SSH server, choose the ciphers to support for SSH connections,
; for system SSH this setting has no effect
SSH_SERVER_CIPHERS = aes128-ctr, aes192-ctr, aes256-ctr, aes128-gcm@openssh.com, arcfour256, arcfour128
; For the built-in SSH server, choose the key exchange algorithms to support for SSH connections,
; for system SSH this setting has no effect
SSH_SERVER_KEY_EXCHANGES = diffie-hellman-group1-sha1, diffie-hellman-group14-sha1, ecdh-sha2-nistp256, ecdh-sha2-nistp384, ecdh-sha2-nistp521, curve25519-sha256@libssh.org
; For the built-in SSH server, choose the MACs to support for SSH connections,
; for system SSH this setting has no effect
SSH_SERVER_MACS = hmac-sha2-256-etm@openssh.com, hmac-sha2-256, hmac-sha1, hmac-sha1-96
; Directory to create temporary files in when testing public keys using ssh-keygen,
; default is the system temporary directory.
SSH_KEY_TEST_PATH =
; Path to ssh-keygen, default is 'ssh-keygen' which means the shell is responsible for finding out which one to call.
SSH_KEYGEN_PATH = ssh-keygen
; Enable SSH Authorized Key Backup when rewriting all keys, default is true
SSH_BACKUP_AUTHORIZED_KEYS = true
; Enable exposure of SSH clone URL to anonymous visitors, default is false
SSH_EXPOSE_ANONYMOUS = false
; Indicate whether to check minimum key size with corresponding type
MINIMUM_KEY_SIZE_CHECK = false
; Disable CDN even in "prod" mode
OFFLINE_MODE = true
DISABLE_ROUTER_LOG = false
; Generate steps:
; $ ./gitea cert -ca=true -duration=8760h0m0s -host=myhost.example.com
;
; Or from a .pfx file exported from the Windows certificate store (do
; not forget to export the private key):
; $ openssl pkcs12 -in cert.pfx -out cert.pem -nokeys
; $ openssl pkcs12 -in cert.pfx -out key.pem -nocerts -nodes
CERT_FILE = custom/https/cert.pem
KEY_FILE = custom/https/key.pem
; Root directory containing templates and static files.
; default is the path where Gitea is executed
STATIC_ROOT_PATH = /usr/share/gitea
; Default path for App data
APP_DATA_PATH = data
; Application level GZIP support
ENABLE_GZIP = false
; Application profiling (memory and cpu)
; For "web" command it listens on localhost:6060
; For "serve" command it dumps to disk at PPROF_DATA_PATH as (cpuprofile|memprofile)_<username>_<temporary id>
ENABLE_PPROF = false
; PPROF_DATA_PATH, use an absolute path when you start gitea as service
PPROF_DATA_PATH = data/tmp/pprof
; Landing page, can be "home", "explore", or "organizations"
LANDING_PAGE = home
; Enables git-lfs support. true or false, default is false.
LFS_START_SERVER = true
; Where your lfs files reside, default is data/lfs.
; LFS authentication secret, change this yourself
LFS_JWT_SECRET = {{ secrets.Foundation.lfs_jwt_secret }}
; LFS authentication validity period (in time.Duration), pushes taking longer than this may fail.
LFS_HTTP_AUTH_EXPIRY = 20m
[lfs]
PATH = data/lfs
; Define allowed algorithms and their minimum key length (use -1 to disable a type)
[ssh.minimum_key_sizes]
ED25519 = 256
ECDSA = 256
RSA = 2048
DSA = 1024
[database]
; Either "mysql", "postgres", "mssql" or "sqlite3", it's your choice
DB_TYPE = postgres
HOST = 127.0.0.1:5432
NAME = gitea
USER = gitea
; Use PASSWD = `your password` for quoting if you use special characters in the password.
PASSWD = {{ secrets.Foundation.database_password }}
; For Postgres, either "disable" (default), "require", or "verify-full"
; For MySQL, either "false" (default), "true", or "skip-verify"
SSL_MODE = disable
; For MySQL only, either "utf8" or "utf8mb4", default is "utf8".
; NOTICE: for "utf8mb4" you must use MySQL InnoDB > 5.6. Gitea is unable to check this.
CHARSET = utf8
; For "sqlite3" and "tidb", use an absolute path when you start gitea as service
PATH = data/gitea.db
; For "sqlite3" only. Query timeout
SQLITE_TIMEOUT = 500
; For iterate buffer, default is 50
ITERATE_BUFFER_SIZE = 50
; Show the database generated SQL
LOG_SQL = false
; Maximum number of DB Connect retries
DB_RETRIES = 10
; Backoff time per DB retry (time.Duration)
DB_RETRY_BACKOFF = 3s
[indexer]
; Issue indexer type, currently support: bleve or db, default is bleve
ISSUE_INDEXER_TYPE = bleve
; Issue indexer storage path, available when ISSUE_INDEXER_TYPE is bleve
ISSUE_INDEXER_PATH = indexers/issues.bleve
; When `ISSUE_INDEXER_QUEUE_TYPE` is `redis`, this will store the redis connection string.
; repo indexer by default disabled, since it uses a lot of disk space
REPO_INDEXER_ENABLED = false
REPO_INDEXER_PATH = indexers/repos.bleve
MAX_FILE_SIZE = 1048576
[admin]
; Disallow regular (non-admin) users from creating organizations.
DISABLE_REGULAR_ORG_CREATION = true
[security]
; Whether the installer is disabled
INSTALL_LOCK = true
; !!CHANGE THIS TO KEEP YOUR USER DATA SAFE!!
SECRET_KEY = {{ secrets.Foundation.secret_key }}
; How long to remember that an user is logged in before requiring relogin (in days)
LOGIN_REMEMBER_DAYS = 7
COOKIE_USERNAME = gitea_awesome
COOKIE_REMEMBER_NAME = gitea_incredible
; Reverse proxy authentication header name of user name
REVERSE_PROXY_AUTHENTICATION_USER = X-WEBAUTH-USER
REVERSE_PROXY_AUTHENTICATION_EMAIL = X-WEBAUTH-EMAIL
; The minimum password length for new Users
MIN_PASSWORD_LENGTH = 6
; Set to true to allow users to import local server paths
IMPORT_LOCAL_PATHS = false
; Set to true to prevent all users (including admin) from creating custom git hooks
DISABLE_GIT_HOOKS = false
INTERNAL_TOKEN = {{ secrets.Foundation.internal_token }}
[openid]
;
; OpenID is an open, standard and decentralized authentication protocol.
; Your identity is the address of a webpage you provide, which describes
; how to prove you are in control of that page.
;
; For more info: https://en.wikipedia.org/wiki/OpenID
;
; Current implementation supports OpenID-2.0
;
; Tested to work providers at the time of writing:
; - Any GNUSocial node (your.hostname.tld/username)
; - Any SimpleID provider (http://simpleid.koinic.net)
; - http://openid.org.cn/
; - openid.stackexchange.com
; - login.launchpad.net
; - <username>.livejournal.com
;
; Whether to allow signin in via OpenID
ENABLE_OPENID_SIGNIN = FALSE
; Whether to allow registering via OpenID
; Do not include to rely on rhw DISABLE_REGISTRATION setting
; ENABLE_OPENID_SIGNUP = true
; Allowed URI patterns (POSIX regexp).
; Space separated.
; Only these would be allowed if non-blank.
; Example value: trusted.domain.org trusted.domain.net
WHITELISTED_URIS =
; Forbidden URI patterns (POSIX regexp).
; Space separated.
; Only used if WHITELISTED_URIS is blank.
; Example value: loadaverage.org/badguy stackexchange.com/.*spammer
BLACKLISTED_URIS =
ENABLE_OPENID_SIGNUP = false
[service]
; Time limit to confirm account/email registration
ACTIVE_CODE_LIVE_MINUTES = 180
; Time limit to perform the reset of a forgotten password
RESET_PASSWD_CODE_LIVE_MINUTES = 180
; Whether a new user needs to confirm their email when registering.
REGISTER_EMAIL_CONFIRM = false
; List of domain names that are allowed to be used to register on a Gitea instance
; gitea.io,example.com
EMAIL_DOMAIN_ALLOWLIST =
; Disallow registration, only allow admins to create accounts.
DISABLE_REGISTRATION = true
; Allow registration only using third-party services, it works only when DISABLE_REGISTRATION is false
ALLOW_ONLY_EXTERNAL_REGISTRATION = false
; User must sign in to view anything.
REQUIRE_SIGNIN_VIEW = false
; Mail notification
ENABLE_NOTIFY_MAIL = false
; More detail: https://github.com/gogits/gogs/issues/165
ENABLE_REVERSE_PROXY_AUTHENTICATION = false
ENABLE_REVERSE_PROXY_AUTO_REGISTRATION = false
ENABLE_REVERSE_PROXY_EMAIL = false
; Enable captcha validation for registration
ENABLE_CAPTCHA = false
; Type of captcha you want to use. Options: image, recaptcha
CAPTCHA_TYPE = image
; Enable recaptcha to use Google's recaptcha service
; Go to https://www.google.com/recaptcha/admin to sign up for a key
RECAPTCHA_SECRET =
RECAPTCHA_SITEKEY =
; Change this to use recaptcha.net or other recaptcha service
RECAPTCHA_URL = https://www.google.com/recaptcha/
; Default value for KeepEmailPrivate
; Each new user will get the value of this setting copied into their profile
DEFAULT_KEEP_EMAIL_PRIVATE = false
; Default value for AllowCreateOrganization
; Every new user will have rights set to create organizations depending on this setting
DEFAULT_ALLOW_CREATE_ORGANIZATION = false
; Either "public", "limited" or "private", default is "public"
; Limited is for signed user only
; Private is only for member of the organization
; Public is for everyone
DEFAULT_ORG_VISIBILITY = public
; Default value for EnableDependencies
; Repositories will use dependencies by default depending on this setting
DEFAULT_ENABLE_DEPENDENCIES = true
; Enable heatmap on users profiles.
ENABLE_USER_HEATMAP = true
; Enable Timetracking
ENABLE_TIMETRACKING = true
; Default value for EnableTimetracking
; Repositories will use timetracking by default depending on this setting
DEFAULT_ENABLE_TIMETRACKING = true
; Default value for AllowOnlyContributorsToTrackTime
; Only users with write permissions can track time if this is true
DEFAULT_ALLOW_ONLY_CONTRIBUTORS_TO_TRACK_TIME = true
; Default value for the domain part of the user's email address in the git log
; if he has set KeepEmailPrivate to true. The user's email will be replaced with a
; concatenation of the user name in lower case, "@" and NO_REPLY_ADDRESS.
NO_REPLY_ADDRESS = noreply.aninix.net
; Show Registration button
SHOW_REGISTRATION_BUTTON = true
; Default value for AutoWatchNewRepos
; When adding a repo to a team or creating a new repo all team members will watch the
; repo automatically if enabled
AUTO_WATCH_NEW_REPOS = true
[webhook]
; Hook task queue length, increase if webhook shooting starts hanging
QUEUE_LENGTH = 1000
; Deliver timeout in seconds
DELIVER_TIMEOUT = 5
; Allow insecure certification
SKIP_TLS_VERIFY = false
; Number of history information in each page
PAGING_NUM = 10
ALLOWED_HOST_LIST = ::1/128, 127.0.0.1/32
; We don't use mail
[mailer]
ENABLED = false
[cache]
; Either "memory", "redis", or "memcache", default is "memory"
ADAPTER = memory
; For "memory" only, GC interval in seconds, default is 60
INTERVAL = 60
; For "redis" and "memcache", connection host address
; redis: network=tcp,addr=:6379,password=macaron,db=0,pool_size=100,idle_timeout=180
; memcache: `127.0.0.1:11211`
HOST =
; Time to keep items in cache if not used, default is 16 hours.
; Setting it to 0 disables caching
ITEM_TTL = 16h
[session]
; Either "memory", "file", or "redis", default is "memory"
PROVIDER = file
; Provider config options
; memory: doesn't have any config yet
; file: session file path, e.g. `data/sessions`
; redis: network=tcp,addr=:6379,password=macaron,db=0,pool_size=100,idle_timeout=180
; mysql: go-sql-driver/mysql dsn config string, e.g. `root:password@/session_table`
PROVIDER_CONFIG = data/sessions
; Session cookie name
COOKIE_NAME = i_like_gitea
; If you use session in https only, default is false
COOKIE_SECURE = true
; Enable set cookie, default is true
ENABLE_SET_COOKIE = true
; Session GC time interval in seconds, default is 86400 (1 day)
GC_INTERVAL_TIME = 86400
; Session life time in seconds, default is 86400 (1 day)
SESSION_LIFE_TIME = 86400
[picture]
AVATAR_UPLOAD_PATH = avatars
REPOSITORY_AVATAR_UPLOAD_PATH = repo-avatars
; How Gitea deals with missing repository avatars
; none = no avatar will be displayed; random = random avatar will be displayed; image = default image will be used
REPOSITORY_AVATAR_FALLBACK = none
REPOSITORY_AVATAR_FALLBACK_IMAGE = /img/repo_default.png
; Max Width and Height of uploaded avatars.
; This is to limit the amount of RAM used when resizing the image.
AVATAR_MAX_WIDTH = 4096
AVATAR_MAX_HEIGHT = 3072
; Maximum alloved file size for uploaded avatars.
; This is to limit the amount of RAM used when resizing the image.
AVATAR_MAX_FILE_SIZE = 1048576
; Chinese users can choose "duoshuo"
; or a custom avatar source, like: http://cn.gravatar.com/avatar/
GRAVATAR_SOURCE = gravatar
; This value will always be true in offline mode.
DISABLE_GRAVATAR = true
; Federated avatar lookup uses DNS to discover avatar associated
; with emails, see https://www.libravatar.org
; This value will always be false in offline mode or when Gravatar is disabled.
ENABLE_FEDERATED_AVATAR = false
[attachment]
; Whether attachments are enabled. Defaults to `true`
ENABLED = true
; Path for attachments. Defaults to `data/attachments`
PATH = data/attachments
; One or more allowed types, e.g. image/jpeg|image/png
ALLOWED_TYPES = image/jpeg|image/png|application/zip|application/gzip
; Max size of each file. Defaults to 4MB
MAX_SIZE = 4
; Max number of files per upload. Defaults to 5
MAX_FILES = 5
[time]
; Specifies the format for fully outputted dates. Defaults to RFC1123
; Special supported values are ANSIC, UnixDate, RubyDate, RFC822, RFC822Z, RFC850, RFC1123, RFC1123Z, RFC3339, RFC3339Nano, Kitchen, Stamp, StampMilli, StampMicro and StampNano
; For more information about the format see http://golang.org/pkg/time/#pkg-constants
FORMAT =
[log]
ROOT_PATH = /var/log/gitea/
; Either "console", "file", "conn", "smtp" or "database", default is "console"
; Use comma to separate multiple modes, e.g. "console, file"
MODE = console
; Either "Trace", "Debug", "Info", "Warn", "Error", "Critical", default is "Trace"
LEVEL = Warn
; Either "Trace", "Debug", "Info", "Warn", "Error", "Critical", default is "None"
STACKTRACE_LEVEL = None
logger.router.MODE = ,
logger.xorm.MODE = ,
logger.access.MODE = console
; Buffer length of the channel, keep it as it is if you don't know what it is.
BUFFER_LEN = 10000
; Either "Trace", "Debug", "Info", "Warn", "Error", "Critical", default is "Info"
;ACCESS_LOG_TEMPLATE =
; Generic log modes
[log.x]
FLAGS = stdflags
EXPRESSION =
PREFIX =
COLORIZE = false
; For "console" mode only
[log.console]
MODE = console
FLAGS = stdflags
PREFIX =
COLORIZE = true
; For "file" mode only
[log.file]
LEVEL =
; Set the file_name for the logger. If this is a relative path this
; will be relative to ROOT_PATH
FILE_NAME =
; This enables automated log rotate(switch of following options), default is true
LOG_ROTATE = true
; Max number of lines in a single file, default is 1000000
MAX_LINES = 1000000
; Max size shift of a single file, default is 28 means 1 << 28, 256MB
MAX_SIZE_SHIFT = 28
; Segment log daily, default is true
DAILY_ROTATE = true
; delete the log file after n days, default is 7
MAX_DAYS = 7
; compress logs with gzip
COMPRESS = true
; compression level see godoc for compress/gzip
COMPRESSION_LEVEL = -1
; For "conn" mode only
[log.conn]
LEVEL =
; Reconnect host for every single message, default is false
RECONNECT_ON_MSG = false
; Try to reconnect when connection is lost, default is false
RECONNECT = false
; Either "tcp", "unix" or "udp", default is "tcp"
PROTOCOL = tcp
; Host address
ADDR =
; For "smtp" mode only
[log.smtp]
LEVEL =
; Name displayed in mail title, default is "Diagnostic message from server"
SUBJECT = Diagnostic message from server
; Mail server
HOST =
; Mailer user name and password
USER =
; Use PASSWD = `your password` for quoting if you use special characters in the password.
PASSWD =
; Receivers, can be one or more, e.g. 1@example.com,2@example.com
RECEIVERS =
[cron]
; Enable running cron tasks periodically.
ENABLED = true
; Run cron tasks when Gitea starts.
RUN_AT_START = false
; Update mirrors
[cron.update_mirrors]
SCHEDULE = @every 10m
; Repository health check
[cron.repo_health_check]
SCHEDULE = @every 24h
TIMEOUT = 60s
; Arguments for command 'git fsck', e.g. "--unreachable --tags"
; see more on http://git-scm.com/docs/git-fsck
ARGS =
; Check repository statistics
[cron.check_repo_stats]
RUN_AT_START = true
SCHEDULE = @every 24h
; Clean up old repository archives
[cron.archive_cleanup]
; Whether to enable the job
ENABLED = true
; Whether to always run at least once at start up time (if ENABLED)
RUN_AT_START = true
; Time interval for job to run
SCHEDULE = @every 24h
; Archives created more than OLDER_THAN ago are subject to deletion
OLDER_THAN = 24h
; Synchronize external user data (only LDAP user synchronization is supported)
[cron.sync_external_users]
; Synchronize external user data when starting server (default false)
RUN_AT_START = false
; Interval as a duration between each synchronization (default every 24h)
SCHEDULE = @every 24h
; Create new users, update existing user data and disable users that are not in external source anymore (default)
; or only create new users if UPDATE_EXISTING is set to false
UPDATE_EXISTING = true
[git]
; Disables highlight of added and removed changes
DISABLE_DIFF_HIGHLIGHT = false
; Max number of lines allowed in a single file in diff view
MAX_GIT_DIFF_LINES = 1000
; Max number of allowed characters in a line in diff view
MAX_GIT_DIFF_LINE_CHARACTERS = 5000
; Max number of files shown in diff view
MAX_GIT_DIFF_FILES = 100
; Arguments for command 'git gc', e.g. "--aggressive --auto"
; see more on http://git-scm.com/docs/git-gc/
GC_ARGS =
; If use git wire protocol version 2 when git version >= 2.18, default is true, set to false when you always want git wire protocol version 1
EnableAutoGitWireProtocol = true
; Operation timeout in seconds
[git.timeout]
DEFAULT = 360
MIGRATE = 600
MIRROR = 300
CLONE = 300
PULL = 300
GC = 60
[mirror]
; Default interval as a duration between each check
DEFAULT_INTERVAL = 8h
; Min interval as a duration must be > 1m
MIN_INTERVAL = 10m
[api]
; Enables Swagger. True or false; default is true.
ENABLE_SWAGGER = true
; Max number of items in a page
MAX_RESPONSE_ITEMS = 50
; Default paging number of api
DEFAULT_PAGING_NUM = 30
; Default and maximum number of items per page for git trees api
DEFAULT_GIT_TREES_PER_PAGE = 1000
; Default size of a blob returned by the blobs API (default is 10MiB)
DEFAULT_MAX_BLOB_SIZE = 10485760
[oauth2]
; Enables OAuth2 provider
ENABLE = true
; Lifetime of an OAuth2 access token in seconds
ACCESS_TOKEN_EXPIRATION_TIME = 3600
; Lifetime of an OAuth2 access token in hours
REFRESH_TOKEN_EXPIRATION_TIME = 730
; Check if refresh token got already used
INVALIDATE_REFRESH_TOKENS = false
; OAuth2 authentication secret for access and refresh tokens, change this a unique string.
JWT_SECRET = {{ secrets.Foundation.jwt_secret }}
[i18n]
LANGS = en-US,zh-CN,zh-HK,zh-TW,de-DE,fr-FR,nl-NL,lv-LV,ru-RU,uk-UA,ja-JP,es-ES,pt-BR,pl-PL,bg-BG,it-IT,fi-FI,tr-TR,cs-CZ,sr-SP,sv-SE,ko-KR
NAMES = English,简体中文,繁體中文(香港),繁體中文(台灣),Deutsch,français,Nederlands,latviešu,русский,Українська,日本語,español,português do Brasil,polski,български,italiano,suomi,Türkçe,čeština,српски,svenska,한국어
; Used for datetimepicker
[i18n.datelang]
en-US = en
zh-CN = zh
zh-HK = zh-HK
zh-TW = zh-TW
de-DE = de
fr-FR = fr
nl-NL = nl
lv-LV = lv
ru-RU = ru
uk-UA = uk
ja-JP = ja
es-ES = es
pt-BR = pt-BR
pl-PL = pl
bg-BG = bg
it-IT = it
fi-FI = fi
tr-TR = tr
cs-CZ = cs-CZ
sr-SP = sr
sv-SE = sv
ko-KR = ko
[U2F]
; NOTE: THE DEFAULT VALUES HERE WILL NEED TO BE CHANGED
; Two Factor authentication with security keys
; https://developers.yubico.com/U2F/App_ID.html
; APP_ID = http://localhost:3000/
; Comma seperated list of trusted facets
; TRUSTED_FACETS = http://localhost:3000/
; Extension mapping to highlight class
; e.g. .toml=ini
[highlight.mapping]
[other]
SHOW_FOOTER_BRANDING = false
; Show version information about Gitea and Go in the footer
SHOW_FOOTER_VERSION = false
; Show template execution time in the footer
SHOW_FOOTER_TEMPLATE_LOAD_TIME = true
[markup.asciidoc]
ENABLED = false
; List of file extensions that should be rendered by an external command
FILE_EXTENSIONS = .adoc,.asciidoc
; External command to render all matching extensions
RENDER_COMMAND = asciidoc --out-file=- -
; Don't pass the file on STDIN, pass the filename as argument instead.
IS_INPUT_FILE = false
[metrics]
; Enables metrics endpoint. True or false; default is false.
ENABLED = false
; If you want to add authorization, specify a token here
TOKEN =
+10
View File
@@ -0,0 +1,10 @@
---
- name: Install Games packages
become: yes
package:
name:
- mgba-qt
- steam
- steam-native-runtime
- discord
+30
View File
@@ -0,0 +1,30 @@
Geolocation by IP is a methodology
# Etymology
GeoIP is a shortening of geolocation by IP.
# Relevant Files and Software
This content is derived & packed by Arch, pulling regularly from [MaxMind](https://maxmind.com).
# Available Clients
The Python `geoip2` library can be used with snippets like below:
```
#!/usr/bin/env python3
import geoip2.database
import sys
with geoip2.database.Reader('/etc/nginx/conf/maxmind-geoip2.mmdb') as reader:
response = reader.country(sys.argv[1])
print(response.country.iso_code)
```
We also install the `geoiplookup` client from the GeoIP client.
# Equivalents or Competition
Whois and other tools can also provide corroboration or alternate responses for these queries.
+22
View File
@@ -0,0 +1,22 @@
---
- name: Install components
become: yes
package:
name: "{{ item }}"
state: present
loop:
- geoip
- geoip-database
- geoip-database-extra
- libmaxminddb
# This is a hack while geoip-database only provides the legacy version.
- name: Ensure GeoIP2 database is present
become: yes
file:
path: /usr/share/GeoIP/GeoIP2.mmdb
owner: root
group: root
mode: 0755
state: file
+24
View File
@@ -0,0 +1,24 @@
Geth is a collective ecosystem for aggregating compute across many cheap nodes for small tasks.
Thanks to NetworkChuck's [tutorial](https://www.youtube.com/watch?v=X9fSMGkjtug) for helping to get this started and the Antsle nano models for the hardware to run this.
# Etymology
The [Geth](http://masseffect.wikia.com/wiki/Geth) are a fictional race in the Mass Effect universe. Geth are individual processes running on many platforms. The more devices, the smarter the collective or gestalt consciousness of the entity becomes.
# Relevant Files and Software
This is a Rancher orchestration of Kubernetes. This allows us to centrally manage a lot of small processes, such as CTF images, without the weight of managing full virtual machines.
Note: containers make it easier to isolate dependencies, especially for less-maintained apps or when we want to set up an isolated network ecosystem. However, they do introduce performance overhead. This is helpful for micro-services, but it's not helpful for heavy, oft-used or data-intensive applications. Some articles with tracking on the wasted compute using containers are below.
* https://pythonspeed.com/articles/docker-performance-overhead/
* https://www.torizon.io/blog/containers-in-linux-and-performance-impact
# Available Clients
This system does not have a client itself, but the containers managed in it may provide SSH or Web clients.
# Equivalents or Competition
There are many ways to run containers other than Rancher/k3s:
* Self-hosted: RedHat OpenShift, [Antsle antMan](https://antsle.com), and raw Docker
* Cloud: [Containers on Azure](https://azure.microsoft.com/en-us/products/category/containers/), [AWS Containers](https://aws.amazon.com/containers/)
File diff suppressed because it is too large Load Diff
+213
View File
@@ -0,0 +1,213 @@
#!/bin/bash
# Downloaded via `curl -sfL https://get.rancher.io`
set -e
if [ "${DEBUG}" = 1 ]; then
set -x
fi
# Usage:
# curl ... | ENV_VAR=... sh -
# or
# ENV_VAR=... ./install.sh
#
# Environment variables:
#
# - INSTALL_RANCHERD_CHANNEL
# Channel to use for fetching RANCHERD download URL.
# Defaults to 'testing'.
#
# - INSTALL_RANCHERD_TYPE
# Type of RANCHERD service. Can be either "server" or "agent".
# Default is "server".
#
# - INSTALL_RANCHERD_VERSION
# Version of RANCHERD to download from github.
#
# info logs the given argument at info log level.
info() {
echo "[INFO] " "$@"
}
# warn logs the given argument at warn log level.
warn() {
echo "[WARN] " "$@" >&2
}
# fatal logs the given argument at fatal log level.
fatal() {
echo "[ERROR] " "$@" >&2
if [ -n "${SUFFIX}" ]; then
echo "[ALT] Please visit 'https://github.com/rancher/rancher/releases' directly and download the latest rancherd-installer.${SUFFIX}.run" >&2
fi
exit 1
}
# setup_env defines needed environment variables.
setup_env() {
INSTALL_RANCHERD_GITHUB_URL="https://github.com/rancher/rancher"
# --- bail if we are not root ---
if [ ! $(id -u) -eq 0 ]; then
fatal "You need to be root to perform this install"
fi
# --- make sure install channel has a value
if [ -z "${INSTALL_RANCHERD_CHANNEL}" ]; then
INSTALL_RANCHERD_CHANNEL="v2.5"
fi
# --- make sure install type has a value
if [ -z "${INSTALL_RANCHERD_TYPE}" ]; then
INSTALL_RANCHERD_TYPE="server"
fi
}
# setup_arch set arch and suffix,
# fatal if architecture not supported.
setup_arch() {
case ${ARCH:=$(uname -m)} in
amd64)
ARCH=amd64
SUFFIX=${ARCH}
;;
x86_64)
ARCH=amd64
SUFFIX=${ARCH}
;;
*)
fatal "unsupported architecture ${ARCH}"
;;
esac
}
# verify_downloader verifies existence of
# network downloader executable.
verify_downloader() {
cmd="$(command -v "${1}")"
if [ -z "${cmd}" ]; then
return 1
fi
if [ ! -x "${cmd}" ]; then
return 1
fi
# Set verified executable as our downloader program and return success
DOWNLOADER=${cmd}
return 0
}
# setup_tmp creates a temporary directory
# and cleans up when done.
setup_tmp() {
TMP_DIR=$(mktemp -d -t rancherd-install.XXXXXXXXXX)
TMP_CHECKSUMS=${TMP_DIR}/rancherd.checksums
TMP_TARBALL=${TMP_DIR}/rancherd.tarball
cleanup() {
code=$?
set +e
trap - EXIT
rm -rf "${TMP_DIR}"
exit $code
}
trap cleanup INT EXIT
}
# --- use desired rancherd version if defined or find version from channel ---
get_release_version() {
if [ -n "${INSTALL_RANCHERD_VERSION}" ]; then
version=${INSTALL_RANCHERD_VERSION}
else
info "finding release for channel ${INSTALL_RANCHERD_CHANNEL}"
INSTALL_RANCHERD_CHANNEL_URL=${INSTALL_RANCHERD_CHANNEL_URL:-'https://update.rancher.io/v1-release/channels'}
version_url="${INSTALL_RANCHERD_CHANNEL_URL}/${INSTALL_RANCHERD_CHANNEL}"
case ${DOWNLOADER} in
*curl)
version=$(${DOWNLOADER} -w "%{url_effective}" -L -s -S ${version_url} -o /dev/null | sed -e 's|.*/||')
;;
*wget)
version=$(${DOWNLOADER} -SqO /dev/null ${version_url} 2>&1 | grep -i Location | sed -e 's|.*/||')
;;
*)
fatal "Unsupported downloader executable '${DOWNLOADER}'"
;;
esac
INSTALL_RANCHERD_VERSION="${version}"
fi
info "using ${INSTALL_RANCHERD_VERSION} as release"
}
# download downloads from github url.
download() {
if [ $# -ne 2 ]; then
fatal "download needs exactly 2 arguments"
fi
case ${DOWNLOADER} in
*curl)
curl -o "$1" -fsSL "$2"
;;
*wget)
wget -qO "$1" "$2"
;;
*)
fatal "downloader executable not supported: '${DOWNLOADER}'"
;;
esac
# Abort if download command failed
if [ $? -ne 0 ]; then
fatal "download failed"
fi
}
# download_checksums downloads hash from github url.
download_checksums() {
CHECKSUMS_URL=${INSTALL_RANCHERD_GITHUB_URL}/releases/download/${INSTALL_RANCHERD_VERSION}/sha256sum.txt
info "downloading checksums at ${CHECKSUMS_URL}"
download "${TMP_CHECKSUMS}" "${CHECKSUMS_URL}"
CHECKSUM_EXPECTED=$(grep "rancherd.${SUFFIX}.tar.gz" "${TMP_CHECKSUMS}" | awk '{print $1}')
}
# download_tarball downloads binary from github url.
download_tarball() {
TARBALL_URL=${INSTALL_RANCHERD_GITHUB_URL}/releases/download/${INSTALL_RANCHERD_VERSION}/rancherd-${SUFFIX}.tar.gz
info "downloading tarball at ${TARBALL_URL}"
download "${TMP_TARBALL}" "${TARBALL_URL}"
}
# verify_tarball verifies the downloaded installer checksum.
verify_tarball() {
info "verifying installer"
CHECKSUM_ACTUAL=$(sha256sum "${TMP_TARBALL}" | awk '{print $1}')
if [ "${CHECKSUM_EXPECTED}" != "${CHECKSUM_ACTUAL}" ]; then
fatal "download sha256 does not match ${CHECKSUM_EXPECTED}, got ${CHECKSUM_ACTUAL}"
fi
}
unpack_tarball() {
info "unpacking tarball file"
mkdir -p /usr/local
tar xzf $TMP_TARBALL -C /usr/local
}
do_install_tar() {
verify_downloader curl || verify_downloader wget || fatal "can not find curl or wget for downloading files"
setup_tmp
get_release_version
download_checksums
download_tarball
verify_tarball
unpack_tarball
}
do_install() {
setup_env
setup_arch
do_install_tar
}
do_install
exit 0
+40
View File
@@ -0,0 +1,40 @@
---
- name: Copy install script
become: yes
ansible.builtin.copy:
src: get-k3s.sh
dest: /usr/local/sbin/get-k3s.sh
owner: root
group: root
mode: 0750
- name: Ensure cgroup
become: yes
register: cgroup_changed
ignore_errors: true
ansible.builtin.command:
cmd: /bin/bash -c "grep 'cgroup_memory=1 cgroup_enable=memory' /boot/firmware/cmdline.txt || (sed -i 's/$/ cgroup_memory=1 cgroup_enable=memory/' /boot/firmware/cmdline.txt && /bin/false)"
- name: Disable swap
become: yes
register: swap_changed
ansible.builtin.lineinfile:
path: /etc/rpi/swap.conf
regex: 'Mechanism='
line: 'Mechanism=none'
- name: Reboot if there was a change.
become: yes
ansible.builtin.command: "/usr/sbin/reboot"
async: 1
poll: 0
when: cgroup_changed is failed or swap_changed is changed
- name: Wait for the reboot to complete if there was a change.
wait_for_connection:
connect_timeout: 20
sleep: 5
delay: 5
timeout: 300
when: cgroup_changed is failed or swap_changed is changed
+16
View File
@@ -0,0 +1,16 @@
---
- name: General tasks
include_tasks: general.yml
- name: Primary tasks
include_tasks: primary.yml
when: "inventory_hostname == geth_primary "
# - name: Rancher tasks
# include_tasks: rancher.yml
# when: "inventory_hostname == geth_primary "
- name: Worker tasks
include_tasks: worker.yml
when: "not inventory_hostname == geth_primary"
+24
View File
@@ -0,0 +1,24 @@
---
- name: Set up primary
become: yes
ansible.builtin.command:
cmd: '/bin/bash -c "K3S_KUBECONFIG_MODE=644 /usr/local/sbin/get-k3s.sh"'
creates: /etc/systemd/system/k3s.service
- name: Check the token
become: yes
ansible.builtin.command:
cmd: 'cat /var/lib/rancher/k3s/server/node-token'
register: k3s_token_cat
- name: Ensure the token is in vault
assert:
that: k3s_token_cat.stdout_lines[0] is in secrets['Geth']['k3s_token']
- name: Enable k3s
become: yes
ansible.builtin.service:
name: k3s
state: restarted
enabled: yes
+46
View File
@@ -0,0 +1,46 @@
---
- name: Rancher directories
become: yes
ansible.builtin.file:
state: directory
path: "{{ item }}"
mode: 0750
owner: root
group: root
loop:
- '/etc/rancher'
- '/etc/rancher/rke2'
- name: Rancher config
become: true
ansible.builtin.template:
src: rancher.config.yaml.j2
dest: /etc/rancher/rke2/config.yaml
owner: root
group: root
mode: 0750
- name: Copy install script
become: yes
ansible.builtin.copy:
src: get-rancher.sh
dest: /usr/local/sbin/get-rancher.sh
owner: root
group: root
mode: 0750
- name: Run install script
become: yes
ansible.builtin.command:
cmd: /usr/local/sbin/get-rancher.sh
- name: Enable rancherd
become: yes
ansible.builtin.service:
name: rancherd
state: restarted
enabled: yes
- debug:
msg: 'Make sure to run `rancherd reset-admin` if this is a new cluster.'
+14
View File
@@ -0,0 +1,14 @@
---
- name: Set up worker
become: yes
ansible.builtin.command:
cmd: /bin/bash -c "K3S_TOKEN={{ secrets['Geth']['k3s_token'] }} K3S_URL=https://{{ geth_primary }}:6443 K3S_NODE_NAME=${HOSTNAME} /usr/local/sbin/get-k3s.sh"
creates: /etc/systemd/system/k3s-agent.service
- name: Enable k3s-agent
become: yes
ansible.builtin.service:
name: k3s-agent
state: restarted
enabled: yes
@@ -0,0 +1,5 @@
token: '{{ secrets['Geth']['rancher_token'] }}'
tls-san:
- {{ inventory_hostname }}
- {{ inventory_hostname }}.{{ replica_domain }}
- {{ ip }}
+22
View File
@@ -0,0 +1,22 @@
Grimoire is a PostgreSQL database underlying other systems on the AniNIX, including [AniNIX/Singularity](../Singularity)
# Etymology
A [grimoire](http://en.wikipedia.org/wiki/Grimoire) is historically a collection of magical knowledge and the ability summon spirits or daemons. Similarly, Singularity adds knowledge to be read from the Grimoire, and Wiki includes the methodology to start the daemon processes being run on the network.
# Relevant Files and Software
Grimoire has a user, postgres, with a home directory of `/var/lib/postgres/`. This user's bashrc contains some help text on how to reset passwords and backup databases in PostgreSQL.
## Backups
Backups are provided by [AniNIX/Aether](../Aether). They can be restored with the following:
```
psql -U dbuser -d db -f backup.sql
```
# Available Clients
There are no clients for the Grimoire -- Singularity and Wiki maintain their tables.
# Additional Reference
Make sure to read the [PostgreSQL page on ArchWiki](https://wiki.archlinux.org/index.php/PostgreSQL) to understand how to maintain this system.
# Tables
* Singularity controls the ttrss database.
+8
View File
@@ -0,0 +1,8 @@
---
- name: Grimoire packages
become: yes
package:
name:
- postgresql
+64
View File
@@ -0,0 +1,64 @@
IRC is a chat system used by members of the AniNIX network.
# Etymology
[IRC](https://en.wikipedia.org/wiki/IRC) stands for Internet Relay Chat -- it is a method of text-based communication across the network via various servers. IRC has long been the self-hosted communication medium of choice for hackers, developers, and the fringe -- though overall adoption has dropped a bit with the rise of other social media, networks like [Libera](https://libera.chat/) are [still growing](https://royal.pingdom.com/2012/04/24/irc-is-dead-long-live-irc/). IRC is moving to the hacker niche, and we follow along.
# Relevant Files and Software
The configuration for the IRC service is divided into two parts -- the daemon and services.
## InspIRCd
The IRC daemon is powered by [InspIRCd](https://inspircd.org/). Relevant configuration is in `/etc/inspircd/` and it logs to journald.
## Anope
The services component is supplied by [Anope](https://www.anope.org/). Relevant configuration is in [the services.conf](file:///etc/anope/services.conf) and it logs to the [its own log](file:///var/log/anope/).
Anope also takes backups of [the anope database](file:///var/db/anope/anope.db) to the backups folder in the same location.
<b>Caution:</b> Anope with version 2.0.3 has some issues with gcc6. If you start encountering segmentation faults with Anope, sign in to `irc://anope.org#anope` (the Anope support IRC network). Script a run of "sudo -u ircd gdb /usr/bin/services core". Enter `r <your flags>` and when it crashes run `bt full`. Quit out of everything and pastebin the file. Provide this to the support staff.
<b>Caution:</b> Arch's packaged version of Anope may be missing critical LDAP modules. We still install the package, but you may need to use a localized install in /opt to get it working.
Anope Services' NickServ authentication can be linked to [[Sora|AniNIX::Sora]] for unified credentials.[[Category:LDAP]]
### Service entities
The following entities can be messaged personally (PM'ed) for help with `/msg <entity> help` from inside an IRC client.
* NickServ will manage IRC nicknames.
* HostServ will manage IRC virtual hosts, to mask IP's.
* ChanServ will manage IRC channels -- new channels can be registered on the network here.
* MemoServ will manage IRC memos (short text-message-like messages between users).
### Bots
#### Bitbot
BitBot is a webhook engine -- we tie it into AniNIX/Yggdrasil and AniNIX/Foundation.
### discord-irc
Discord-IRC acts as a bridge between our IRC network and Discord -- this lets us integrate with mobile push notifications & lowers the barrier to entry to the network.
# Available Clients
A [simple web client](https://irc.aninix.net) is hosted.
For more advanced options like logging, you will need to use your own client. All IRC clients will connect to the service by providing the following information:
* Host: aninix.net
* Port: 6697
* The client should accept only valid certificates.
* The client should automatically join the #lobby channel.
* The client should provide a nickname and NickServ password that the user intends to use.
### Clients by OS
Some example clients can be found here.
* Linux hosts are strongly recommended to use [weechat](https://wiki.archlinux.org/index.php/Weechat) inside [tmux](https://wiki.archlinux.org/index.php/Tmux).
* Windows hosts can connect to this service using [HexChat](https://hexchat.github.io/).
* Mac and iOS hosts can use [Colloquy](http://colloquy.info/downloads.html).
* Android hosts can use [AndChat](http://www.duckspike.net/andchat/).
# Equivalents or Competition
Rivals to IRC include other IRC networks like Libera, mail services like [Gmail](https://mail.google.com), and other chat systems like Slack, Microsoft Teams, Discord, Snapchat, WhatsApp, etc. We use Discord to provide new users with a Web-only bridge to the IRC network, but most features are only available within our own network.
# Additional Reference
* [IRCHelp.org for operators](https://www.irchelp.org/ircd/ircopguide.html)
* [InspIRCd modes reference](https://docs.inspircd.org/3/user-modes/)
+16
View File
@@ -0,0 +1,16 @@
[Unit]
Description=AniNIX/IRC | Anope Services
Requires=network.target
After=network.target
[Service]
Type=simple
PIDFile=/run/anope/anope.pid
ExecStart=/usr/bin/services --confdir=/etc/anope/ --dbdir=/opt/anope/data --logdir=/var/log/anope --localedir=/usr/lib/anope/locale --modulesdir=/usr/lib/anope --nofork
ExecReload=/bin/kill -1 $MAINPID
Restart=always
User=anope
Group=ircd
[Install]
WantedBy=multi-user.target
+17
View File
@@ -0,0 +1,17 @@
[Unit]
Description=AniNIX/IRC daemon
Requires=network.target
After=network.target
[Service]
Type=forking
PIDFile=/var/lib//inspircd.pid
ExecStart=/usr/bin/
ExecReload=kill -HUP $MAINPID
ExecStop=kill $MAINPID
Restart=always
User=inspircd
Group=ircd
[Install]
WantedBy=multi-user.target
+29
View File
@@ -0,0 +1,29 @@
---
- user:
name: "{{ item }}"
state: present
shell: "{{ daemon_shell | default('/sbin/nologin') }}"
local: yes
groups: ircd
loop:
- bitbot
- dsbridge
- theraven
- werewolf
# Install TheRaven package
- package:
name:
- TheRaven
- git:
repo: 'https://github.com/jesopo/bitbot.git'
dest: /usr/local/src/bitbot/
clone: yes
update: yes
- git:
repo:
-
+87
View File
@@ -0,0 +1,87 @@
---
- name: Ensure directory permissions
become: yes
file:
state: directory
path: "{{ item }}"
owner: inspircd
group: ircd
mode: 0750
loop:
- "/var/log/inspircd"
- "/etc/inspircd"
- "/etc/inspircd/data/"
- name: Socket directory permissions
become: yes
file:
state: directory
path: /run/inspircd
owner: inspircd
group: ircd
mode: 0755
- name: Generate dhparam
become: yes
command:
cmd: openssl dhparam -out /etc/inspircd/dhparams.pem 2048
creates: /etc/inspircd/dhparams.pem
- name: Permissions on dhparam
become: yes
file:
state: file
path: /etc/inspircd/dhparams.pem
owner: inspircd
group: ircd
mode: 0640
- name: Add inspircd user to ssl
become: yes
user:
name: inspircd
groups: ssl,ircd
append: yes
- name: Copy config and fill in attributes
register: templatefiles
become: yes
template:
src: "inspircd/{{ item }}.j2"
dest: "/etc/inspircd/{{ item }}"
owner: inspircd
group: ircd
mode: 0600
loop:
- inspircd.conf
- modules.conf
- links.conf
- opers.conf
- rules.txt
- motd.txt
- name: Ensure tracking files
become: yes
file:
dest: "/etc/inspircd/{{ item }}"
owner: inspircd
group: ircd
mode: 0600
loop:
- 'data/xline.db'
- 'data/permchannels.conf'
- name: Ensure service running
become: yes
service:
name: inspircd
state: started
enabled: yes
- name: Reload on config change
become: yes
when: templatefiles.changed
service:
name: inspircd
state: reloaded
+18
View File
@@ -0,0 +1,18 @@
---
- name: IRC packages
become: yes
package:
name:
- inspircd
- anope
- TheRaven
- include_tasks: daemon.yml
- include_tasks: services.yml
- include_tasks: web.yml
#- include_tasks: bots.yml
+72
View File
@@ -0,0 +1,72 @@
---
- name: Add anope user to ircd
become: yes
user:
name: anope
groups: ircd
append: yes
- name: Ensure directory permissions
become: yes
file:
state: directory
path: "{{ item }}"
owner: anope
group: ircd
mode: 0700
loop:
- "/etc/anope"
- "/opt/anope"
- "/opt/anope/data"
- "/var/log/anope"
- name: Copy config and fill in attributes
register: templatefiles
become: yes
template:
src: "anope/{{ item }}.j2"
dest: "/etc/anope/{{ item }}"
owner: anope
group: ircd
mode: 0600
loop:
- botserv.conf
- chanserv.conf
- global.conf
- hostserv.conf
- memoserv.conf
- modules.conf
- nickserv.conf
- operserv.conf
- services.conf
- name: Copy service file
become: yes
register: servicesfile
copy:
src: services/anope.service
dest: /usr/lib/systemd/system/anope.service
owner: root
group: root
mode: 0644
- name: Reload services
when: servicesfile.changed
become: yes
systemd:
daemon_reload: true
- name: Ensure service running
become: yes
service:
name: anope
state: started
enabled: yes
- name: Reload on config change
become: yes
when: templatefiles.changed or servicesfile.changed
service:
name: anope
state: reloaded
+30
View File
@@ -0,0 +1,30 @@
---
- name: KiwiIRC Packages
become: yes
package:
name:
- kiwiirc-server-bin
state: present
- name: Update permissions
become: yes
file:
path: "{{ item }}"
recurse: yes
owner: ircd
group: http
loop:
- /etc/kiwiirc
- /usr/share/kiwiirc
- name: Populate config
become: yes
template:
src: "kiwiirc/{{ item }}.j2"
dest: "/etc/kiwiirc/{{ item }}"
owner: ircd
group: http
mode: 0640
loop:
- "client.json"
+404
View File
@@ -0,0 +1,404 @@
/*
* Example configuration file for BotServ.
*/
/*
* First, create the service. If you do not want to have a 'BotServ', but do want the ability to have
* ChanServ assigned to channels for the use of fantasy commands, you may delete the below 'service' block.
*
* Note that deleting a 'service' block for a pseudoclient that is already online will not remove the
* client, the client becomes no different from a normal service bot, so you will have to use botserv/bot
* to manually delete the client.
*
* You may then want to map some of the below commands to other services, like placing botserv/bot on
* OperServ so you can delete the below client, and mapping assign and unassign to ChanServ so users are
* able to control whether or not ChanServ is in the channel. You may also want to map botserv/set/nobot
* to OperServ so you can restrict who can assign the other core service clients.
*/
service
{
/*
* The name of the BotServ client.
* If you change this value, you probably want to change the client directive in the configuration for the botserv module too.
*/
nick = "BotServ"
/*
* The username of the BotServ client.
*/
user = "services"
/*
* The hostname of the BotServ client.
*/
host = "ircservices.{{ external_domain }}"
/*
* The realname of the BotServ client.
*/
gecos = "Bot Service"
/*
* The modes this client should use.
* Do not modify this unless you know what you are doing.
*
* These modes are very IRCd specific. If left commented, sane defaults
* are used based on what protocol module you have loaded.
*
* Note that setting this option incorrectly could potentially BREAK some, if
* not all, usefulness of the client. We will not support you if this client is
* unable to do certain things if this option is enabled.
*/
#modes = "+o"
/*
* An optional comma separated list of channels this service should join. Outside
* of log channels this is not very useful, as the service will just idle in the
* specified channels, and will not accept any types of commands.
*
* Prefixes may be given to the channels in the form of mode characters or prefix symbols.
*/
#channels = "@#services,#mychan"
}
/*
* Core BotServ module.
*
* Provides essential functionality for BotServ.
*/
module
{
name = "botserv"
/*
* The name of the client that should be BotServ.
*
* This directive is optional.
*/
client = "BotServ"
/*
* The default bot options for newly registered channels. Note that changing these options
* will have no effect on channels which are already registered. The list must be separated
* by spaces.
*
* The options are:
* - dontkickops: Channel operators will be protected against BotServ kicks
* - dontkickvoices: Voiced users will be protected against BotServ kicks
* - greet: The channel's BotServ bot will greet incoming users that have set a greet
* in their NickServ settings
* - fantasy: Enables the use of BotServ fantasy commands in the channel
*
* This directive is optional, if left blank, there will be no defaults.
*/
defaults = "greet fantasy"
/*
* The minimum number of users there must be in a channel before the bot joins it. The best
* value for this setting is 1 or 2. This can be 0, the service bots will not part unless
* specifically unassigned, and will keep the channel open.
*/
minusers = 1
/*
* The bots are currently not affected by any modes or bans when they try to join a channel.
* But some people may want to make it act like a real bot, that is, for example, remove all
* the bans affecting the bot before joining the channel, remove a ban that affects the bot
* set by a user when it is in the channel, and so on. Since it consumes a bit more CPU
* time, you should not enable this on larger networks.
*
* This directive is optional.
*/
#smartjoin = yes
/*
* Modes to set on service bots when they join channels, comment this out for no modes
*
* This directive is optional.
*/
botmodes = "ao"
/*
* User modes to set on service bots. Read the comment about the service:modes directive
* on why this can be a bad idea to set.
*/
#botumodes = "i"
}
/*
* Core BotServ commands.
*
* In Anope modules can provide (multiple) commands, each of which has a unique command name. Once these modules
* are loaded you can then configure the commands to be added to any client you like with any name you like.
*
* Additionally, you may provide a permission name that must be in the opertype of users executing the command.
*
* Sane defaults are provided below that do not need to be edited unless you wish to change the default behavior.
*/
/* Give it a help command. */
command { service = "BotServ"; name = "HELP"; command = "generic/help"; }
/*
* bs_assign
*
* Provides the commands:
* botserv/assign - Used to assign BotServ bots to channels
* botserv/unassign - Used to unassign BotServ bots
* botserv/set/nobot - Used to prohibit channels from being assigned BotServ bots.
*
* Used for assigning and unassigning bots to channels.
*/
module { name = "bs_assign" }
command { service = "BotServ"; name = "ASSIGN"; command = "botserv/assign"; }
command { service = "BotServ"; name = "UNASSIGN"; command = "botserv/unassign"; }
command { service = "BotServ"; name = "SET NOBOT"; command = "botserv/set/nobot"; permission = "botserv/set/nobot"; }
/*
* bs_autoassign
*
* Allows service bots to be automatically assigned to channels upon registration.
*/
#module
{
name = "bs_autoassign"
/*
* Automatically assign ChanServ to channels upon registration.
*/
bot = "ChanServ"
}
/*
* bs_badwords
*
* Provides the command botserv/badwords.
*
* Used for controlling the channel badword list.
*/
module
{
name = "bs_badwords"
/*
* The maximum number of entries a single bad words list can have.
*/
badwordsmax = 32
/*
* If set, BotServ will use case sensitive checking for badwords.
*
* This directive is optional.
*/
#casesensitive = yes
}
command { service = "BotServ"; name = "BADWORDS"; command = "botserv/badwords"; }
/*
* bs_bot
*
* Provides the command botserv/bot.
*
* Used for administrating BotServ bots.
*/
module { name = "bs_bot" }
command { service = "BotServ"; name = "BOT"; command = "botserv/bot"; permission = "botserv/bot"; }
/*
* bs_botlist
*
* Provides the command botserv/botlist.
*
* Used for listing all available bots.
*/
module { name = "bs_botlist" }
command { service = "BotServ"; name = "BOTLIST"; command = "botserv/botlist"; }
/*
* bs_control
*
* Provides the commands botserv/act and botserv/say.
*
* Used for making the bot message a channel.
*/
module { name = "bs_control" }
command { service = "BotServ"; name = "ACT"; command = "botserv/act"; }
command { service = "BotServ"; name = "SAY"; command = "botserv/say"; }
/*
* bs_info
*
* Provides the command botserv/info.
*
* Used for getting information on bots or channels.
*/
module { name = "bs_info" }
command { service = "BotServ"; name = "INFO"; command = "botserv/info"; }
/*
* bs_kick
*
* Provides the commands:
* botserv/kick - Dummy help wrapper for the KICK command.
* botserv/kick/amsg - Configures BotServ's AMSG kicker.
* botserv/kick/badwords - Configures BotServ's badwords kicker.
* botserv/kick/bolds - Configures BotServ's bold text kiceker.
* botserv/kick/caps - Configures BotServ's capital letters kicker.
* botserv/kick/colors - Configures BotServ's color kicker.
* botserv/kick/flood - Configures BotServ's flood kicker.
* botserv/kick/italics - Configures BotServ's italics kicker.
* botserv/kick/repeat - Configures BotServ's repeat kicker.
* botserv/kick/reverses - Configures BotServ's reverse kicker.
* botserv/kick/underlines - Configures BotServ's reverse kicker.
* botserv/set/dontkickops - Used for preventing BotServ from kicking channel operators.
* botserv/set/dontkickvoices - Used for preventing BotServ from kicking voices.
*
* Used for configuring what bots should kick for.
*/
module
{
name = "bs_kick"
/*
* The amount of time that data for a user is valid in BotServ. If the data exceeds this time,
* it is reset or deleted depending on the case. Do not set it too high, otherwise your
* resources will be slightly affected.
*/
keepdata = 10m
/*
* If set, the bots will use a kick reason that does not state the word when it is kicking.
* This is especially useful if you have young people on your network.
*
* This directive is optional.
*/
gentlebadwordreason = yes
}
command { service = "BotServ"; name = "KICK"; command = "botserv/kick"; }
command { service = "BotServ"; name = "KICK AMSG"; command = "botserv/kick/amsg"; }
command { service = "BotServ"; name = "KICK BADWORDS"; command = "botserv/kick/badwords"; }
command { service = "BotServ"; name = "KICK BOLDS"; command = "botserv/kick/bolds"; }
command { service = "BotServ"; name = "KICK CAPS"; command = "botserv/kick/caps"; }
command { service = "BotServ"; name = "KICK COLORS"; command = "botserv/kick/colors"; }
command { service = "BotServ"; name = "KICK FLOOD"; command = "botserv/kick/flood"; }
command { service = "BotServ"; name = "KICK ITALICS"; command = "botserv/kick/italics"; }
command { service = "BotServ"; name = "KICK REPEAT"; command = "botserv/kick/repeat"; }
command { service = "BotServ"; name = "KICK REVERSES"; command = "botserv/kick/reverses"; }
command { service = "BotServ"; name = "KICK UNDERLINES"; command = "botserv/kick/underlines"; }
command { service = "BotServ"; name = "SET DONTKICKOPS"; command = "botserv/set/dontkickops"; }
command { service = "BotServ"; name = "SET DONTKICKVOICES"; command = "botserv/set/dontkickvoices"; }
/*
* bs_set
*
* Provides the commands:
* botserv/set/private - Used to prohibit specific BotServ bots from being assigned to channels.
*/
module { name = "bs_set" }
command { service = "BotServ"; name = "SET"; command = "botserv/set"; }
command { service = "BotServ"; name = "SET BANEXPIRE"; command = "botserv/set/banexpire"; }
command { service = "BotServ"; name = "SET PRIVATE"; command = "botserv/set/private"; permission = "botserv/set/private"; }
/*
* greet
*
* Provides the commands:
* botserv/set/greet - Used for enabling or disabling BotServ's greet messages in a channel.
* nickserv/set/greet, nickserv/saset/greet - Used for changing a users greet message, which is displayed when they enter channels.
*/
module { name = "greet" }
command { service = "BotServ"; name = "SET GREET"; command = "botserv/set/greet"; }
command { service = "NickServ"; name = "SET GREET"; command = "nickserv/set/greet"; }
command { service = "NickServ"; name = "SASET GREET"; command = "nickserv/saset/greet"; permission = "nickserv/saset/greet"; }
/*
* GREET privilege.
*
* Used by 'greet'.
*
* Users with this privilege have their greet shown when they join channels.
*/
privilege
{
name = "GREET"
rank = 40
level = 5
flag = "g"
xop = "AOP"
}
/*
* fantasy
*
* Allows 'fantaisist' commands to be used in channels.
*
* Provides the commands:
* botserv/set/fantasy - Used for enabling or disabling BotServ's fantasist commands.
*/
module
{
name = "fantasy"
/*
* Defines the prefixes for fantasy commands in channels. One of these characters will have to be prepended
* to all fantasy commands. If you choose "!", for example, fantasy commands will be "!kick",
* "!op", etc. This directive is optional, if left out, the default fantasy character is "!".
*/
#fantasycharacter = "!."
}
command { service = "BotServ"; name = "SET FANTASY"; command = "botserv/set/fantasy"; }
/*
* Fantasy commands
*
* Fantasy commands can be executed in channels that have a BotServ bot by prefixing the
* command with one of the fantasy characters configured in botserv's fantasycharacter
* directive.
*
* Sane defaults are provided below that do not need to be edited unless you wish to change the default behavior.
*/
fantasy { name = "ACCESS"; command = "chanserv/access"; }
fantasy { name = "AKICK"; command = "chanserv/akick"; }
fantasy { name = "AOP"; command = "chanserv/xop"; }
fantasy { name = "BAN"; command = "chanserv/ban"; }
fantasy { name = "CLONE"; command = "chanserv/clone"; }
fantasy { name = "DEHALFOP"; command = "chanserv/modes"; }
fantasy { name = "DEOP"; command = "chanserv/modes"; }
fantasy { name = "DEOWNER"; command = "chanserv/modes"; }
fantasy { name = "DEPROTECT"; command = "chanserv/modes"; }
fantasy { name = "DEVOICE"; command = "chanserv/modes"; }
fantasy { name = "DOWN"; command = "chanserv/down"; }
fantasy { name = "ENFORCE"; command = "chanserv/enforce"; }
fantasy { name = "ENTRYMSG"; command = "chanserv/entrymsg"; }
fantasy { name = "FLAGS"; command = "chanserv/flags"; }
fantasy { name = "HALFOP"; command = "chanserv/modes"; }
fantasy { name = "HELP"; command = "generic/help"; prepend_channel = false; }
fantasy { name = "HOP"; command = "chanserv/xop"; }
fantasy { name = "INFO"; command = "chanserv/info"; prepend_channel = false; }
fantasy { name = "INVITE"; command = "chanserv/invite"; }
fantasy { name = "K"; command = "chanserv/kick"; }
fantasy { name = "KB"; command = "chanserv/ban"; }
fantasy { name = "KICK"; command = "chanserv/kick"; }
fantasy { name = "LEVELS"; command = "chanserv/levels"; }
fantasy { name = "LIST"; command = "chanserv/list"; prepend_channel = false; }
fantasy { name = "LOG"; command = "chanserv/log"; }
fantasy { name = "MODE"; command = "chanserv/mode"; }
fantasy { name = "MUTE"; command = "chanserv/ban"; kick = no; mode = "QUIET"; }
fantasy { name = "OP"; command = "chanserv/modes"; }
fantasy { name = "OWNER"; command = "chanserv/modes"; }
fantasy { name = "PROTECT"; command = "chanserv/modes"; }
fantasy { name = "QOP"; command = "chanserv/xop"; }
fantasy { name = "SEEN"; command = "chanserv/seen"; prepend_channel = false; }
fantasy { name = "SOP"; command = "chanserv/xop"; }
fantasy { name = "STATUS"; command = "chanserv/status"; }
fantasy { name = "SUSPEND"; command = "chanserv/suspend"; permission = "chanserv/suspend"; }
fantasy { name = "SYNC"; command = "chanserv/sync"; }
fantasy { name = "TOPIC"; command = "chanserv/topic"; }
fantasy { name = "UNBAN"; command = "chanserv/unban"; }
fantasy { name = "UNSUSPEND"; command = "chanserv/unsuspend"; permission = "chanserv/suspend"; }
fantasy { name = "UP"; command = "chanserv/up"; }
fantasy { name = "VOICE"; command = "chanserv/modes"; }
fantasy { name = "VOP"; command = "chanserv/xop"; }
File diff suppressed because it is too large Load Diff
+115
View File
@@ -0,0 +1,115 @@
/*
* Example configuration file for Global.
*/
/*
* First, create the service.
*/
service
{
/*
* The name of the Global client.
* If you change this value, you probably want to change the client directive in the configuration for the global module too.
*/
nick = "Global"
/*
* The username of the Global client.
*/
user = "services"
/*
* The hostname of the Global client.
*/
host = "ircservices.{{ external_domain }}"
/*
* The realname of the Global client.
*/
gecos = "Global Noticer"
/*
* The modes this client should use.
* Do not modify this unless you know what you are doing.
*
* These modes are very IRCd specific. If left commented, sane defaults
* are used based on what protocol module you have loaded.
*
* Note that setting this option incorrectly could potentially BREAK some, if
* not all, usefulness of the client. We will not support you if this client is
* unable to do certain things if this option is enabled.
*/
#modes = "+o"
/*
* An optional comma separated list of channels this service should join. Outside
* of log channels this is not very useful, as the service will just idle in the
* specified channels, and will not accept any types of commands.
*
* Prefixes may be given to the channels in the form of mode characters or prefix symbols.
*/
#channels = "@#services,#mychan"
}
/*
* Core Global module.
*
* Provides essential functionality for Global.
*/
module
{
name = "global"
/*
* The name of the client that should be Global.
*/
client = "Global"
/*
* This is the global message that will be sent when Services are being
* shutdown/restarted.
*
* This directive is optional.
*/
#globaloncycledown = "Services are restarting, they will be back shortly - please be good while we're gone"
/*
* This is the global message that will be sent when Services (re)join the
* network.
*
* This directive is optional.
*/
#globaloncycleup = "Services are now back online - have a nice day"
/*
* If set, Services will hide the IRC Operator's nick in a global
* message/notice.
*
* This directive is optional.
*/
#anonymousglobal = yes
}
/*
* Core Global commands.
*
* In Anope modules can provide (multiple) commands, each of which has a unique command name. Once these modules
* are loaded you can then configure the commands to be added to any client you like with any name you like.
*
* Additionally, you may provide a permission name that must be in the opertype of users executing the command.
*
* Sane defaults are provided below that do not need to be edited unless you wish to change the default behavior.
*/
/* Give it a help command. */
command { service = "Global"; name = "HELP"; command = "generic/help"; }
/*
* gl_global
*
* Provides the command global/global.
*
* Used for sending a message to every online user.
*/
module { name = "gl_global" }
command { service = "Global"; name = "GLOBAL"; command = "global/global"; permission = "global/global"; }
+188
View File
@@ -0,0 +1,188 @@
/*
* Example configuration file for HostServ.
*/
/*
* First, create the service.
*/
service
{
/*
* The name of the HostServ client.
* If you change this value, you probably want to change the client directive in the configuration for the hostserv module too.
*/
nick = "HostServ"
/*
* The username of the HostServ client.
*/
user = "services"
/*
* The hostname of the HostServ client.
*/
host = "ircservices.{{ external_domain }}"
/*
* The realname of the HostServ client.
*/
gecos = "vHost Service"
/*
* The modes this client should use.
* Do not modify this unless you know what you are doing.
*
* These modes are very IRCd specific. If left commented, sane defaults
* are used based on what protocol module you have loaded.
*
* Note that setting this option incorrectly could potentially BREAK some, if
* not all, usefulness of the client. We will not support you if this client is
* unable to do certain things if this option is enabled.
*/
#modes = "+o"
/*
* An optional comma separated list of channels this service should join. Outside
* of log channels this is not very useful, as the service will just idle in the
* specified channels, and will not accept any types of commands.
*
* Prefixes may be given to the channels in the form of mode characters or prefix symbols.
*/
#channels = "@#services,#mychan"
}
/*
* Core HostServ module.
*
* Provides essential functionality for HostServ.
*/
module
{
name = "hostserv"
/*
* The name of the client that should be HostServ.
*/
client = "HostServ"
/*
* If enabled, vhosts are activated on users immediately when they are set.
*/
activate_on_set = false
}
/*
* Core HostServ commands.
*
* In Anope modules can provide (multiple) commands, each of which has a unique command name. Once these modules
* are loaded you can then configure the commands to be added to any client you like with any name you like.
*
* Additionally, you may provide a permission name that must be in the opertype of users executing the command.
*
* Sane defaults are provided below that do not need to be edited unless you wish to change the default behavior.
*/
/* Give it a help command. */
command { service = "HostServ"; name = "HELP"; command = "generic/help"; }
/*
* hs_del
*
* Provides the commands hostserv/del and hostserv/delall.
*
* Used for removing users' vHosts.
*/
module { name = "hs_del" }
command { service = "HostServ"; name = "DEL"; command = "hostserv/del"; permission = "hostserv/del"; }
command { service = "HostServ"; name = "DELALL"; command = "hostserv/delall"; permission = "hostserv/del"; }
/*
* hs_group
*
* Provides the command hostserv/group.
*
* Used for grouping one vHost to many nicks.
*/
module
{
name = "hs_group"
/*
* Upon nickserv/group, this option syncs the nick's main vHost to the grouped nick.
*/
syncongroup = false
/*
* This makes vhosts act as if they are per account.
*/
synconset = false
}
command { service = "HostServ"; name = "GROUP"; command = "hostserv/group"; }
/*
* hs_list
*
* Provides the command hostserv/list.
*
* Used for listing actively set vHosts.
*/
module { name = "hs_list" }
command { service = "HostServ"; name = "LIST"; command = "hostserv/list"; permission = "hostserv/list"; }
/*
* hs_off
*
* Provides the command hostserv/off.
*
* Used for turning off your vHost.
*/
module { name = "hs_off" }
command { service = "HostServ"; name = "OFF"; command = "hostserv/off"; }
/*
* hs_on
*
* Provides the command hostserv/on.
*
* Used for turning on your vHost.
*/
module { name = "hs_on" }
command { service = "HostServ"; name = "ON"; command = "hostserv/on"; }
/*
* hs_request
*
* Provides the commands hostserv/request, hostserv/activate, hostserv/reject, and hostserv/waiting.
*
* Used to manage vHosts requested by users.
*/
module
{
name = "hs_request"
/*
* If set, Services will send a memo to the user requesting a vHost when it's been
* approved or rejected.
*/
memouser = yes
/*
* If set, Services will send a memo to all Services staff when a new vHost is requested.
*/
memooper = yes
}
command { service = "HostServ"; name = "REQUEST"; command = "hostserv/request"; }
command { service = "HostServ"; name = "ACTIVATE"; command = "hostserv/activate"; permission = "hostserv/set"; }
command { service = "HostServ"; name = "REJECT"; command = "hostserv/reject"; permission = "hostserv/set"; }
command { service = "HostServ"; name = "WAITING"; command = "hostserv/waiting"; permission = "hostserv/set"; }
/*
* hs_set
*
* Provides the commands hostserv/set and hostserv/setall.
*
* Used for setting users' vHosts.
*/
module { name = "hs_set" }
command { service = "HostServ"; name = "SET"; command = "hostserv/set"; permission = "hostserv/set"; }
command { service = "HostServ"; name = "SETALL"; command = "hostserv/setall"; permission = "hostserv/set"; }

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