24 Commits

Author SHA1 Message Date
ad6e48d7e0 Adding geoip module and instituting a deny variable for vhosts to consume 2025-12-02 14:43:49 -06:00
31992aa487 Moving KiwiIRC websocket behind Nginx instead of dedicated external port 2025-10-21 15:31:32 -05:00
571455802b Catchup 2025-10-21 14:04:09 -05:00
4df485af5d Updates for requirements 2025-10-21 13:55:07 -05:00
365e476b82 Update for internal subdomains as well as external 2025-10-21 13:54:23 -05:00
c7f88d988b IRC Update for KiwiIRC 1.7 2025-10-21 13:52:25 -05:00
333a987dac Moving these hooks to AniNIX/Uniglot 2025-10-09 20:37:39 -05:00
40355ea6e0 Updates for Foundation JS 2025-10-09 20:36:31 -05:00
b50de1e4f7 Styling updates for Gitea upgrades 2025-09-30 17:14:49 -05:00
25c9872a0a Updates for AniNIX/Password 2025-09-29 16:33:35 -05:00
78af592485 Updates for latest inspircd & anope 2025-09-29 16:33:05 -05:00
a14dfd6562 Password package update 2025-04-27 15:25:54 -05:00
6864492ce4 Community is gone. https://archlinux.org/news/cleaning-up-old-repositories/ 2025-04-15 14:33:51 -05:00
35eabff91a Removing unneeded packages 2025-04-15 14:32:41 -05:00
16ed6e85dc Need latest on config 2025-04-15 14:31:23 -05:00
02bf4326a3 Deprecating wolfpack.aninix.net subdomain 2025-04-15 14:24:56 -05:00
405fcb4447 Formatting 2025-04-15 14:03:32 -05:00
5089c82710 Inventory sanity checks 2025-04-15 13:59:53 -05:00
7962727fb3 Updates for yggdrasil 2025-04-15 13:58:49 -05:00
a82bd54091 Linting 2025-04-12 06:58:34 -05:00
17f900003f Moving WolfPack output to /home instead of /srv for users to access with SFTP & Cyberbrain 2025-04-12 06:42:45 -05:00
9f131ca0a9 Adding AIDE to HIDS tools 2025-04-12 04:36:22 -05:00
b6692593a3 Fixing text 2025-04-12 02:59:24 -05:00
81960d92b0 Updating generate-monitoring to use TrackIPEntries 2025-04-12 02:58:38 -05:00
94 changed files with 1611 additions and 1201 deletions

1
.gitignore vendored
View File

@@ -8,6 +8,7 @@ roles/Sharingan/files/monit/checks/availability
roles/Foundation/files/custom/public/img/**
roles/Maat/files/pacoloco.yaml
venv/**
wiki/
wiki/**
**/pkg/**
**/src/**

View File

@@ -1,10 +1,6 @@
pkgname="$(git config remote.origin.url | rev | cut -f 1 -d '/' | rev | sed 's/.git$//')"
pkgver="$(git describe --tag --abbrev=0)"."$(git rev-parse --short HEAD)"
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
pkgrel() {
git log "$(git describe --tag --abbrev=0)"..HEAD | grep -c commit
}
epoch="$(git log | grep -c commit)"
pkgdesc="$(head -n 1 README.md)"
arch=("x86_64")
url="$(git config remote.origin.url | sed 's/.git$//')"

View File

@@ -28,7 +28,7 @@ fi
while [ ! -d .git ]; do
cd ..
if [ "$PWD" == '/' ]; then
echo "This needs to be run from the Ubiqtorate checkout"
echo "This needs to be run from the Kapisi checkout"
exit 3
fi
done

52
bin/deploy-tasks Executable file
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 $?

View File

@@ -17,7 +17,7 @@ fi
while [ ! -d .git ]; do
cd ..
if [ "$PWD" == '/' ]; then
echo "This needs to be run from the Ubiqtorate checkout"
echo "This needs to be run from the Kapisi checkout"
exit 3
fi
done

View File

@@ -3,7 +3,7 @@
#
# Description: This file generates the DNS and DHCP files for pihole.
#
# Package: AniNIX/Ubiqtorate
# Package: AniNIX/Kapisi
# Copyright: WTFPL
#
# Author: DarkFeather <darkfeather@aninix.net>
@@ -13,43 +13,38 @@ import subprocess
import sys
import re
import yaml
from kapisi_lib import *
rolepath='../roles/Sharingan/files'
monfilepath=rolepath+"/monit/checks/availability"
def WriteMonitoringEntry(content,hosttype,hostclass):
def WriteMonitoringEntry(entryset):
### Create the ping-based monitoring entry
# param content: the yaml content to parse
# param hosttype: managed or unmanaged
# param hostclass: the type of host as classified in the yaml
# param entryset: Entries matched from the inventory
global monfile
with open(monfilepath,'a') as monfile:
# Write host entries
for host in content['all']['children'][hosttype]['children'][hostclass]['hosts']:
for host in entryset:
try:
hostname= host + '.' + content['all']['vars']['replica_domain']
monfile.write('check program ' + host + '_ping_mon with path "/usr/lib/monitoring-plugins/check_ping -H ' + hostname + ' -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 ' + hostname + ' is not online."\n\n')
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(content,hosttype,hostclass):
def WriteSSHMonitoringEntry(entryset):
### Create the ping-based monitoring entry
# param content: the yaml content to parse
# param hosttype: managed or unmanaged
# param hostclass: the type of host as classified in the yaml
# param entryset: Entries matched from the inventory
global monfile
with open(monfilepath,'a') as monfile:
# Write host entries
for host in content['all']['children'][hosttype]['children'][hostclass]['hosts']:
for host in entryset:
try:
hostname= host + '.' + content['all']['vars']['replica_domain']
monfile.write('check program ' + host + '_ssh_mon with path "/usr/lib/monitoring-plugins/check_ssh -H ' + hostname + '"\n')
monfile.write(' if status != 0 for 3 times within 5 cycles then exec "/etc/monit.d/scripts/critical ' + hostname + ' is not responding to SSH."\n\n')
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.')
@@ -62,19 +57,12 @@ def GenerateFiles(file):
os.mkdir(rolepath)
# Parse the yaml
with open(file, 'r') as stream:
content = yaml.safe_load(stream)
entryset = TrackIPEntries(file,searchstring='all.children.managed.**.ip')
if os.path.isfile(monfilepath): os.remove(monfilepath)
# Add DNS entries for each host
hosttype = 'managed'
for hostclass in ['physical','virtual','geth_hubs']:
#WriteMonitoringEntry(content,hosttype,hostclass)
WriteSSHMonitoringEntry(content,hosttype,hostclass)
hosttype = 'unmanaged'
for hostclass in ['ovas','appliances']:
WriteMonitoringEntry(content,hosttype,hostclass)
WriteSSHMonitoringEntry(entryset)
WriteMonitoringEntry(entryset)
if __name__ == '__main__':
if len(sys.argv) != 2:

View File

@@ -4,7 +4,7 @@
# Description: This file generates the DNS and DHCP files for pihole.
# It expects that the inventory has two levels of grouping.
#
# Package: AniNIX/Ubiqtorate
# Package: AniNIX/Kapisi
# Copyright: WTFPL
#
# Author: DarkFeather <darkfeather@aninix.net>
@@ -20,7 +20,7 @@ dnsfilepath=rolepath+"/dns"
dhcpfilepath=rolepath+"/dhcp"
entryset={}
def WriteDHCPEntries(replica_domain,dhcpfile):
def WriteDHCPEntries(dhcpfile):
### Create the DHCP entry
# param content: the yaml content to parse
# param hosttype: managed or unmanaged
@@ -29,9 +29,9 @@ def WriteDHCPEntries(replica_domain,dhcpfile):
for host in entryset:
# Entries should be:
# dhcp-host=mac,ip,fqdn
dhcpfile.write('dhcp-host=' + entryset[host][1] + ',' + entryset[host][0] + ',' + host + '.' + replica_domain + '\n')
dhcpfile.write('dhcp-host=' + entryset[host][1] + ',' + entryset[host][0] + ',' + entryset[host][2] + '\n')
def WriteDNSEntries(replica_domain,dnsfile):
def WriteDNSEntries(dnsfile):
### Create the DNS entry
# param content: the yaml content to parse
# param hosttype: managed or unmanaged
@@ -40,7 +40,7 @@ def WriteDNSEntries(replica_domain,dnsfile):
for host in entryset:
# Entries should be:
# ip host fqdn
dnsfile.write(entryset[host][0] + ' ' + host + '.' + replica_domain + ' ' + host + '\n')
dnsfile.write(entryset[host][0] + ' ' + entryset[host][2] + ' ' + host + '\n')
def GenerateFiles(file):
### Open the file and parse it
@@ -53,7 +53,6 @@ def GenerateFiles(file):
# Parse the yaml
with open(file, 'r') as stream:
content = yaml.safe_load(stream)
replica_domain = content['all']['vars']['replica_domain']
external_domain = content['all']['vars']['external_domain']
# Clear the DNS file
@@ -61,10 +60,10 @@ def GenerateFiles(file):
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(replica_domain,dhcpfile)
WriteDHCPEntries(dhcpfile)
with open(dnsfilepath,'w') as dnsfile:
dnsfile.write(content['all']['vars']['webfront']+' '+external_domain+' '+content['all']['vars']['external_subdomains'].replace(' ','.'+external_domain+' ')+'.'+external_domain+' '+content['all']['vars']['hosted_domains']+"\n")
WriteDNSEntries(replica_domain,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

View File

@@ -3,7 +3,7 @@
#
# Description: This file generates the systemd.service files that run our VM's
#
# Package: AniNIX/Ubiqtorate
# Package: AniNIX/Kapisi
# Copyright: WTFPL
#
# Author: DarkFeather <darkfeather@aninix.net>

View File

@@ -10,11 +10,12 @@ 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]},...]
# 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.
@@ -32,7 +33,7 @@ def TrackIPEntries(yaml_file,searchstring='all.children.**.ip'):
yaml_path = YAMLPath(searchstring)
# Create a regex pattern to remove the end of the path
ippattern = re.compile('\.ip$')
ippattern = re.compile('\\.ip$')
try:
for node_coordinate in processor.get_nodes(yaml_path, mustexist=True):
# Strip the path to the host entry.
@@ -54,10 +55,18 @@ def TrackIPEntries(yaml_file,searchstring='all.children.**.ip'):
log.error(ex)
# Add the host to the entryset.
entryset.update({ hostname : [ip,mac] })
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']

View File

@@ -3,10 +3,12 @@ all:
# 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'
@@ -23,6 +25,7 @@ all:
static: false
wireless_ssid: 'Shadownet'
ansible_python_interpreter: auto_silent
aether_primary: 'Yggdrasil'
ldap:
server: "10.0.1.3"
orgdn: "dc=aninix,dc=net"
@@ -38,6 +41,11 @@ all:
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'
children:
managed:
children:
@@ -46,7 +54,7 @@ all:
Chappaai:
ipinterface: eth0
ip: 10.0.1.2
mac: B8:27:EB:B6:AA:0C
mac: e4:5f:01:01:ff:9b
static: true
children:
Node:
@@ -54,7 +62,7 @@ all:
Node1:
ipinterface: enp1s0
ip: 10.0.1.5
mac: FA:EC:43:87:4D:2D
mac: fa:ec:43:87:4d:2d
tap: true
ups: 'aps'
active_vms:
@@ -72,7 +80,7 @@ all:
Node3:
ipinterface: enp1s0
ip: 10.0.1.8
mac: B2:C6:2C:02:B2:6E
mac: b2:c6:2c:02:b2:6e
tap: true
active_vms:
- TDS-Jump
@@ -81,33 +89,33 @@ all:
Geth0:
ipinterface: eth0
ip: 10.0.1.9
mac: 84:16:F9:14:15:C5
mac: b8:27:eb:09:a1:a0
static: true
k3s_primary: true
Geth1:
ipinterface: eth0
ip: 10.0.1.10
mac: E4:5F:01:01:FF:9C
mac: e4:5f:01:01:ff:9c
static: true
Geth2:
ipinterface: eth0
ip: 10.0.1.11
mac: E4:5F:01:01:FF:D5
mac: e4:5f:01:01:ff:d5
static: true
Geth3:
ipinterface: eth0
ip: 10.0.1.12
mac: E4:5F:01:01:FF:96
mac: e4:5f:01:01:ff:96
static: true
Geth4:
ipinterface: eth0
ip: 10.0.1.13
mac: E4:5F:01:01:FF:E4
mac: e4:5f:01:01:ff:e4
static: true
Geth5:
ipinterface: eth0
ip: 10.0.1.14
mac: B8:27:EB:B6:AA:0D
mac: b8:27:eb:81:f5:4b
static: true
virtual: # 10.0.1.16/28
vars:
@@ -115,9 +123,9 @@ all:
Sharingan:
ip: 10.0.1.16
ipinterface: ens3
mac: 00:15:5D:01:02:10
mac: 00:15:5d:01:02:10
cores: 4
memory: 4
memory: 6
vnc: 8
bridge: br0
uefi: true
@@ -129,9 +137,9 @@ all:
DarkNet:
ipinterface: ens3
ip: 10.0.1.17
mac: 00:15:5D:01:02:05
cores: 4
memory: 4
mac: 00:15:5d:01:02:05
cores: 2
memory: 2
vnc: 9
bridge: br0
disks:
@@ -153,12 +161,12 @@ all:
ip: 10.0.1.3
mac: 00:25:90:0d:6e:86
static: true
sslidentity: aninix.net-0001
sslidentity: aninix.net-0002
secdetection: true
iptv_location: "Milwaukee|Madison"
iptv_location: "ToonamiAftermathEast.us|TVSClassicMovies.us|UniversalComedy|ABCNewsLive"
aether_source: true
cores: 8
memory: 16
memory: 10
bridge: br0
vnc: 1
vscan_enabled: true
@@ -173,12 +181,12 @@ all:
hosts:
Vergil1:
ip: 10.0.1.32
mac: b8:27:eb:9a:73:dd
mac: b8:27:eb:e3:ff:59
rotate: 0
remote: NS-RC4NA-14
Vergil2:
ip: 10.0.1.33
mac: 84:16:F9:13:B6:E6
mac: b8:27:eb:cf:26:88
motion_enabled: no
rotate: 180
remote: NS-RC4NA-14
@@ -194,7 +202,7 @@ all:
hosts:
Superintendent:
ip: 10.0.1.49
mac: DE:8B:9E:19:55:1E
mac: de:8b:9e:19:55:1e
cores: 2
memory: 2
vnc: 6
@@ -271,10 +279,10 @@ all:
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
mac: 00:80:92:77:ce:e4
Geth-Eyes:
ip: 10.0.1.68
mac: 9C:A3:AA:33:A3:99
mac: 9c:a3:aa:33:a3:99
# "Core-Console":
# ip: 10.0.1.74
# mac: 00:25:90:0D:82:5B
@@ -288,38 +296,43 @@ all:
mac: f4:2b:8c:10:31:44
Lykos:
ip: 10.0.1.65
mac: 70:74:14:4F:8E:42
mac: 70:74:14:4f:8e:42
Node0:
ip: 10.0.1.66
mac: E0:BE:03:77:0E:88
mac: 70:32:17:46:49:89
LivingRoomTV:
ip: 10.0.1.69
mac: 80:D2:1D:17:63:0E
mac: 80:d2:1d:17:63:0e
BedRoomTV:
ip: 10.0.1.70
mac: 80:D2:1D:17:63:0F
mac: a4:77:33:4c:2a:44
TrainingRoomTV:
ip: 10.0.1.71
mac: 80:D2:1D:17:63:10
mac: 80:d2:1d:17:63:10
BT:
ip: 10.0.1.72
mac: 8A:00:AA:7F:DF:D1
mac: 8a:00:aa:7f:df:d1
DedSec:
ip: 10.0.1.73
mac: 34:F6:4B:36:12:8F
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
mac: 64:16:66:08:57:f5
# Nest Protect
Monitor:
ip: 10.0.2.3
mac: 18:B4:30:2F:F1:37
mac: 18:b4:30:2f:f1:37
# Chamberlain My-Q
Gatekeeper:
ip: 10.0.2.4
mac: 64:52:99:14:28:2B
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
mac: 40:9f:38:95:06:34
# CaretakerCharlie has no network

View File

@@ -6,70 +6,35 @@
# Parameters:
# threads: Number of threads to use; default is 16.
#
- hosts: Nazara
order: sorted
serial: "{{ threads | default('16') }}"
gather_facts: true
ignore_unreachable: true
vars_files:
- "{{ lookup('env', 'ANSIBLE_VAULT_FILE') }}"
vars:
- ansible_password: "{{ passwords[inventory_hostname] }}"
- ansible_become_password: "{{ passwords[inventory_hostname] }}"
roles:
- Nazara
- hosts: managed
order: sorted
serial: "{{ threads | default('16') }}"
gather_facts: true
ignore_unreachable: true
vars_files:
- "{{ lookup('env', 'ANSIBLE_VAULT_FILE') }}"
vars: # This is the only segment that should need these variables, as the basics role should take care of sudo and the SSH key.
- ansible_password: "{{ passwords[inventory_hostname] }}"
- ansible_become_password: "{{ passwords[inventory_hostname] }}"
roles:
- ShadowArch
- SSH
- Sharingan
- hosts: physical
gather_facts: true
ignore_unreachable: true
roles:
- hardware
- hosts: Yggdrasil
order: sorted
serial: "{{ threads | default('16') }}"
gather_facts: true
ignore_unreachable: true
vars_files:
- "{{ lookup('env', 'ANSIBLE_VAULT_FILE') }}"
roles:
- hardware
- SSL
- WebServer
- IRC
- WolfPack
- Aether
- Foundation
- Yggrasil
- hosts: geth_hubs
order: sorted
serial: "{{ threads | default('16') }}"
gather_facts: true
ignore_unreachable: true
vars_files:
- "{{ lookup('env', 'ANSIBLE_VAULT_FILE') }}"
roles:
- Geth-Hub
- hosts: Node1,Node2,Node3
order: sorted
serial: "{{ threads | default('16') }}"
gather_facts: true
ignore_unreachable: true
vars_files:
- "{{ lookup('env', 'ANSIBLE_VAULT_FILE') }}"
roles:
- hardware
- Node
- Grimoire
- IRC
- Password
- SSL
- TheRaven
- WebServer
- WolfPack
- Yggdrasil
- hosts: DarkNet
order: sorted
@@ -81,3 +46,23 @@
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

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

View File

@@ -1,9 +0,0 @@
#!/bin/bash
result="$(find roles/*/{files,templates} -type f -exec file {} \; | grep -Ev ASCII\ text\|empty\|Unicode\ text | grep -v motd.txt.j2)"
if [ -n "$result" ]; then
echo "These files need to be evaluated -- generally, don't commit data files to Git."
echo "$result"
exit 1
fi
exit 0

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

View File

@@ -28,3 +28,14 @@ if [ $? -ne 1 ]; then
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

@@ -1,7 +0,0 @@
#!/bin/bash
# pre-commit hook to use ansible-lint to check our playbooks.
for file in `find ../playbooks/ -type f`; do
ansible-lint "$file"
done

View File

@@ -1,4 +1,5 @@
pyaml
yamlpath
pytest
python3-nmap
simplejson

View File

@@ -36,21 +36,21 @@
- name: Read the Aether identity
become: true
delegate_to: Core
delegate_to: '{{ aether_primary }}'
command: cat /home/aether/.ssh/aether
register: aether_key
- name: Read the Aether public identity
become: true
delegate_to: Core
delegate_to: '{{ aether_primary }}'
command: cat /home/aether/.ssh/aether.pub
register: aether_pubkey
- include_tasks: source.yml
when: "{{ inventory_hostname }} is 'Core'"
when: "{{ inventory_hostname }} is {{ aether_primary }}"
- include_tasks: client.yml
when: "{{ inventory_hostname }} is 'Core'"
when: "{{ inventory_hostname }} is {{ aether_primary }}"
- name: Ensure the Aether identity files are protected.
become: true

View File

@@ -20,6 +20,8 @@
mode: 0600
owner: openvpn
group: network
# Must ensure that we have the latest.
force: true
- name: OpenVPN Auth part 1
become: yes

View File

@@ -3,26 +3,18 @@ The Foundation is a one-stop shop for source code from AniNIX developers -- it's
# 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.[[Category:Charity]]
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 [file:///srv/foundation/ the Foundation server folder] on [[Core]].
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]] is configured to translate the repository to [https://aninix.net/foundation/ the Web-accessible format] via the ArchLinux cgit package. Review the package list at that link and identify the source packages you want to use. Then use the following to clone the source, generally best done to /usr/local/src/ on Linux. Please note that the AniNIX uses Webserver translation to eliminate the need for a .git suffix -- web requests will show in CGIT, while Git clone requests will pull the package all from the same URL. Right-click on your package of choice from the web interface's index page and then clone that address. <pre>
git clone https://aninix.net/foundation/<packagename>
</pre>
[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]] 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.
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
For CentOS, one needs to use the following steps to install Mono. Packages like Cryptoworkbench, Heartbeat, Cerberus, and others require this.
* yum install bison gettext glib2 freetype fontconfig libpng libpng-devel libX11 libX11-devel glib2-devel libgdi* libexif glibc-devel urw-fonts java unzip gcc gcc-c++ automake autoconf libtool make bzip2 wget
* [https://download.mono-project.com/sources/mono/ Download Mono source]
* tar xjvf the source package
* configure; make; make install
*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
@@ -30,36 +22,30 @@ 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 Go here], but 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.
* 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.
**Alternatively**: ArchLinux users can add the following segment to the bottom of pacman.conf to install the packages as bundled by the AniNIX. We're working on adding GPG signing -- in the meantime, security-conscious users should build from source anyway.
<pre>
[AniNIX::Foundation]
SigLevel = Optional TrustAll
Server = https://aninix.net/foundation/
</pre>
# 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.
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
Even though the [[Talk:IRC#Why_Not_SMTP|AniNIX doesn't use SMTP]], we still use the @aninix.net suffix for the user.email config property on branches. All commits, therefore, should have the proper-case of the user's [[IRC|AniNIX::IRC]] handle as the user.name attribute, and the lower-cased username followed by @aninix.net for the user.email attribute.
[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.
## Tags for Semantic Versioning
We version our projects according to [https://semver.org/ Semantic Versioning] -- this versioning is established using the git tag as major and minor version, the git commit as the patch, and the number of commits since the tag as the ArchLinux release note.
To do this, see [our encryption article](https://aninix.net/AniNIX/Wiki/src/branch/main/Articles/Getting_Started_With_Encryption.md#GPG_Keys).
[https://aninix.net/cgit/cgit.cgi/HelloWorld/tree/PKGBUILD Our HelloWorld PKGBUILD] demonstrates this -- most of the metadata for the package is populated directly by git, and only dependencies are tracked in the PKGBUILD itself.
## 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 the same as the [[QANs|QAN]] for which the branch was started or the functional concept's shortname.
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 [https://help.github.com/articles/removing-sensitive-data-from-a-repository/ an article] on how to use "git filter-branch" to purge it.
}}
[[Category:Public_Service]]
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.

View File

@@ -1,6 +1,6 @@
#!/bin/bash
URI=https://aninix.net/assets/css/theme-arc-green.css
URI=https://aninix.net/assets/css/theme-gitea-dark.css
# Gitea arc-green palette
BOLDTEXT='#87ab63'
@@ -62,3 +62,6 @@ for i in `find . -type f`; do
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

View File

@@ -24,3 +24,8 @@ function insertNewsSnippet(snippet,tag) {
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';
}

View File

@@ -1,39 +1,53 @@
{{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="{{AppSubUrl}}/assets/img/avatar_default.png" />
<img class="logo" src="/assets/img/avatar_default.png" />
</div>
<div class="hero">
<h1 class="ui icon header title">
AniNIX
</h1>
<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="https://foundation.aninix.net/explore/repos">Open source security</a>
<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 class="hero ui icon header">
<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>
</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"/>
@@ -43,6 +57,8 @@
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"/>
@@ -52,33 +68,47 @@
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;" />
<div class="sixteen wide center aligned centered column">
<div class="hero">
<h2>Webapps</h2>
<!-- 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="ui stackable middle very relaxed page grid">
<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>AniNIX/Singularity (News powered by TT-RSS)</p></a></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>AniNIX/Yggdrasil (Media powered by Emby)</p></a></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>AniNIX/Sharingan (Monitoring powered by Graylog)</p></a></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>AniNIX/Cyberbrain (SFTP Dropbox)</p></a></div>
</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="latest-news"></div>
<div class="hero" id="news"></div>
<script type="text/javascript">
insertNewsSnippet("https://aninix.net/assets/rss-snippets/aninix","latest-news");
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">
<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 class="ui stackable middle very relaxed page grid">
</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>
@@ -89,6 +119,5 @@
<div class="two wide center column"><!--placeholder--><p>&nbsp;</p></div>
</div>
</div>
</div>
<!-- END CUSTOM HOME -->
{{template "base/footer" .}}

View File

@@ -1,3 +1,4 @@
<!-- 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>-->
@@ -13,33 +14,47 @@
</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="/mawiki">Open-source</a>
<a href="/MartialArts/Wiki/src/branch/main/README.md">Open-source</a>
</h1>
<p class="large">
<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 class="large">
<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>
</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 class="large">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 class="large">
<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>Lessons:</b>Tuesdays 7-8:30 p.m.</li>
@@ -47,32 +62,50 @@
<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 class="large">
<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 class="large">
<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" id="latest-news"></div>
<script type="text/javascript">
insertNewsSnippet("https://aninix.net/assets/rss-snippets/maqotw","latest-news");
</script>
<div class="ui stackable middle very relaxed page grid" id="social">
<div class="ui stackable middle very relaxed page grid">
<div class="sixteen wide center aligned centered column">
<div class="hero">
<h2 id=social>Follow us on social media</h2>
<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 class="ui stackable middle very relaxed page grid" id="social">
</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>
@@ -82,5 +115,3 @@
<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>
</div>
</div>

View File

@@ -107,9 +107,11 @@ 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,arc-green,aninix
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

View File

@@ -6,10 +6,10 @@ After=network.target
[Service]
Type=simple
PIDFile=/run/anope/anope.pid
ExecStart=/opt/anope/bin/services --confdir=/etc/anope/ --dbdir=/opt/anope/data --localedir=/opt/anope/locale --logdir=/var/log/anope --modulesdir=/opt/anope/lib --nofork
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=ircd
User=anope
Group=ircd
[Install]

View File

@@ -5,12 +5,12 @@ After=network.target
[Service]
Type=forking
PIDFile=/var/lib/inspircd/inspircd.pid
ExecStart=/usr/bin/inspircd
PIDFile=/var/lib//inspircd.pid
ExecStart=/usr/bin/
ExecReload=kill -HUP $MAINPID
ExecStop=kill $MAINPID
Restart=always
User=ircd
User=inspircd
Group=ircd
[Install]

View File

@@ -1,15 +0,0 @@
[Unit]
Description=AniNIX/IRC Web Client
After=network.target irc.service ircservices.service
[Service]
WorkingDirectory=/usr/local/src/KiwiIRC/
ExecStart=/bin/sh ./kiwi -f
ExecReload=/bin/kill -HUP $MAINPID
KillMode=control-group
Restart=always
User=ircd
Group=ircd
[Install]
WantedBy=multi-user.target

View File

@@ -5,12 +5,22 @@
file:
state: directory
path: "{{ item }}"
owner: ircd
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
@@ -23,40 +33,24 @@
file:
state: file
path: /etc/inspircd/dhparams.pem
owner: ircd
owner: inspircd
group: ircd
mode: 0640
- name: Add ircd user to ssl
- name: Add inspircd user to ssl
become: yes
user:
name: ircd
groups: ssl
name: inspircd
groups: ssl,ircd
append: yes
- name: Copy service file
become: yes
register: servicesfile
copy:
src: services/inspircd.service
dest: /usr/lib/systemd/system/inspircd.service
owner: root
group: root
mode: 0644
- name: Reload services
when: servicesfile.changed
become: yes
systemd:
daemon_reload: true
- name: Copy config and fill in attributes
register: templatefiles
become: yes
template:
src: "inspircd/{{ item }}.j2"
dest: "/etc/inspircd/{{ item }}"
owner: ircd
owner: inspircd
group: ircd
mode: 0600
loop:
@@ -67,20 +61,11 @@
- rules.txt
- motd.txt
- name: Tracking directory
become: yes
file:
dest: "/etc/inspircd/data/"
owner: ircd
group: ircd
mode: 0750
state: directory
- name: Ensure tracking files
become: yes
file:
dest: "/etc/inspircd/{{ item }}"
owner: ircd
owner: inspircd
group: ircd
mode: 0600
loop:
@@ -96,7 +81,7 @@
- name: Reload on config change
become: yes
when: templatefiles.changed or servicesfile.changed
when: templatefiles.changed
service:
name: inspircd
state: reloaded

View File

@@ -1,11 +1,18 @@
---
- 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: ircd
owner: anope
group: ircd
mode: 0700
loop:
@@ -20,7 +27,7 @@
template:
src: "anope/{{ item }}.j2"
dest: "/etc/anope/{{ item }}"
owner: ircd
owner: anope
group: ircd
mode: 0600
loop:

View File

@@ -1,58 +1,30 @@
---
- name: Clone KiwiIRC
- name: KiwiIRC Packages
become: yes
git:
repo: https://github.com/prawnsalad/KiwiIRC.git
dest: /usr/local/src/KiwiIRC
update: no
# Need to capture AniNIX skinning of client as well as client build process.
package:
name:
- kiwiirc-server-bin
state: present
- name: Update permissions
become: yes
file:
path: /usr/local/src/KiwiIRC
path: "{{ item }}"
recurse: yes
owner: ircd
group: ircd
group: http
loop:
- /etc/kiwiirc
- /usr/share/kiwiirc
- name: Populate config
become: yes
register: config
template:
src: kiwiirc/config.js.j2
dest: /usr/local/src/KiwiIRC/config.js
src: "kiwiirc/{{ item }}.j2"
dest: "/etc/kiwiirc/{{ item }}"
owner: ircd
group: ircd
mode: 0600
- name: Copy service file
become: yes
register: servicesfile
copy:
src: services/kiwiirc.service
dest: /usr/lib/systemd/system/kiwiirc.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: kiwiirc
state: started
enabled: yes
- name: Reload on config change
become: yes
when: config.changed or servicesfile.changed
service:
name: kiwiirc
state: reloaded
group: http
mode: 0640
loop:
- "client.json"

View File

@@ -36,7 +36,7 @@ module
* Admin credentials used for performing searches and adding users.
*/
admin_binddn = "uid=binduser,{{ ldap['userou'] }},{{ ldap['orgdn'] }}"
admin_password = "{{ secrets['Sora']['bindpassword'] }}"
admin_password = "{{ secrets['Password']['bindpassword'] }}"
}
}
@@ -91,7 +91,7 @@ module
*
* If not set, then registration is not blocked.
*/
#disable_register_reason = "To register on this network, contact a netadmin in #lobby. They will need to add an AniNIX/Sora LDAP account for you."
#disable_register_reason = "To register on this network, contact a netadmin in #lobby. They will need to add an AniNIX/Password LDAP account for you."
/*
* If set, the reason to give the users who try to "/msg NickServ SET EMAIL".

View File

@@ -135,7 +135,7 @@ uplink
*
* NOTE: On some shell providers, this will not be an option.
*/
host = "10.0.1.3"
host = "127.0.0.1"
/*
* Enable if Services should connect using IPv6.
@@ -221,19 +221,10 @@ serverinfo
*
* This directive tells Anope which IRCd Protocol to speak when connecting.
* You MUST modify this to match the IRCd you run.
*
* Supported:
* - bahamut
* - inspircd11
* - inspircd12
* - inspircd20
* - plexus
* - ratbox
* - unreal
*/
module
{
name = "inspircd20"
name = "inspircd3"
/*
* Some protocol modules can enforce mode locks server-side. This reduces the spam caused by

View File

@@ -1,5 +1,4 @@
# Includes
<config format="xml">
<include file="/etc/inspircd/opers.conf">
<include file="/etc/inspircd/links.conf">
<include file="/etc/inspircd/modules.conf">
@@ -54,6 +53,7 @@
limit="500"
localmax="500"
maxconnwarn="on"
maxchans="20"
modes="+wx"
pingfreq="120"
port="6697"
@@ -81,7 +81,16 @@
tlsv13="yes">
<openssl onrehash="yes">
# Websockets
<connect
name="websockets"
allow="/run/inspircd/websocket.sock">
<bind
path="/run/inspircd/websocket.sock"
type="clients"
hook="websocket"
permissions="0777"
replace="yes">
# Performance
<performance
@@ -91,6 +100,8 @@
softlimit="1024"
quietbursts="yes">
<log method="file" type="* -USERINPUT -USEROUTPUT" level="default" target="/var/log/inspircd/inspircd.log" flush="1">
# If things aren't working as intended, flip the commenting of the lines above and below here. Make sure to remove /tmp/ircd.log afterwards.
#<log method="file" type="* -USERINPUT -USEROUTPUT" level="debug" target="/tmp/ircd.log" flush="5">
<pid file="/var/lib/inspircd/inspircd.pid">
<options
@@ -119,7 +130,7 @@
defaultmodes="not"
moronbanner="You're banned! Contact {{ organization['email'] }} with the ERROR line below for help."
xlinemessage="You're banned! Contact {{ organization['email'] }} with the ERROR line below for help."
exemptchanops="nonick:v flood:o"
invitebypassmodes="yes"
nosnoticestack="no"
@@ -134,7 +145,7 @@
hidemodes="eI"
hideulines="no"
flatlinks="no"
hidewhois=""
hideserver=""
hidebans="no"
hidekills=""
hidesplits="yes"
@@ -152,9 +163,8 @@
maxquit="255"
maxtopic="307"
maxkick="255"
maxgecos="128"
maxreal="128"
maxaway="200">
<channels users="20" opers="60">
<maxlist chan="*" limit="60">
<whowas
groupsize="10"

View File

@@ -3,7 +3,7 @@
<link name="ircservices.{{ external_domain }}"
ipaddr="core.{{ replica_domain }}"
port="8067"
allowmask="10.0.1.3/32"
allowmask="127.0.0.1"
sendpass="{{ secrets['IRC']['servicespass'] }}"
recvpass="{{ secrets['IRC']['servicespass'] }}">

View File

@@ -8,6 +8,8 @@
# SHA256 module: Allows other modules to generate SHA256 hashes,
# usually for cryptographic uses and security.
<module name="m_sha256.so">
# SHA1 module
<module name="m_sha1.so">
#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#
# Abbreviation module: Provides the ability to abbreviate commands a-la
@@ -54,8 +56,8 @@
#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#
# Block CAPS module: Adds channel mode +B, blocks all-CAPS messages.
<module name="m_blockcaps.so">
<blockcaps percent="50"
<module name="m_anticaps.so">
<anticaps percent="50"
minlen="5"
capsmap="ABCDEFGHIJKLMNOPQRSTUVWXYZ! ">
@@ -402,15 +404,20 @@
# integration with services packages.
<module name="m_topiclock.so">
#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#
# Userip module: Adds the /USERIP command.
# Allows users to query their own IP, also allows opers to query the IP
# of anyone else.
<module name="m_userip.so">
#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#
# Spanning tree module: Allows linking of servers using the spanning
# tree protocol (see the READ THIS BIT section above).
# You will almost always want to load this.
#
<module name="m_spanningtree.so">
#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#
# CBAN module: This module adds the /CBAN command which allows server
# operators to prevent channels matching a glob from being created.
<module name="cban">
#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#
# Websocket module: allow websocket clients to connect
<module name="websocket">
<wsorigin allow="https://irc.{{ external_domain }}">

View File

@@ -31,7 +31,7 @@ You should check which channels you want to join.
Type the following to get a list:
/list
You will need to request an AniNIX/Sora LDAP
You will need to request an AniNIX/Password LDAP
account from an op or founder in #lobby to be
able to log in. If you already have an account,
use the following to authenticate:

View File

@@ -8,5 +8,5 @@
# Operators are tracked in the vault.
{% for oper in secrets['IRC']['opers'] %}
<oper name="{{ oper }}" password="{{ secrets['IRC']['opers'][oper] }}" hash="sha256" host="*@127.0.0.1 *@10.0.1.* *@localhost *@aninix.net" type="NetAdmin">
<oper name="{{ oper }}" password="{{ secrets['IRC']['opers'][oper] }}" hash="sha256" host="*@127.0.0.1 *@10.0.1.* *@localhost *@{{ external_domain }}" type="NetAdmin" maxchans="60">
{% endfor %}

View File

@@ -0,0 +1,36 @@
{
"windowTitle": "{{ organization['displayname'] }}/IRC | Web IRC client",
"startupScreen": "welcome",
"kiwiServer": "https://irc.{{ external_domain }}/webirc/websocket/",
"restricted": true,
"hideSettings": false,
"hideAdvancedSettings": true,
"theme": "Dark",
"themes": [
{ "name": "Default", "url": "static/themes/default" },
{ "name": "Dark", "url": "static/themes/dark" },
{ "name": "Coffee", "url": "static/themes/coffee" },
{ "name": "GrayFox", "url": "static/themes/grayfox" },
{ "name": "Nightswatch", "url": "static/themes/nightswatch" },
{ "name": "Osprey", "url": "static/themes/osprey" },
{ "name": "Radioactive", "url": "static/themes/radioactive" },
{ "name": "Sky", "url": "static/themes/sky" },
{ "name": "Elite", "url": "static/themes/elite" }
],
"startupOptions" : {
"infoContent": "<img src='https://{{ external_domain }}/assets/img/AniNIX.png' style='width:100%;height:auto;' /><h3>{{ organization['displayname'] }}/IRC</h3>Log in with your AniNIX account.",
"channel": "#lobby",
"nick": "Guest?",
"server": "irc.{{ external_domain }}",
"direct_path": "/websocket/",
"port": 443,
"direct": true,
"tls": true
},
"embedly": {
"key": ""
},
"plugins": [
{ "name": "customise", "url": "static/plugins/customise.html" }
]
}

View File

@@ -1,259 +0,0 @@
var conf = {};
// Run the Kiwi server under a different user/group
conf.user = "ircd";
conf.group = "ircd";
// Log file location
conf.log = "kiwi.log";
/*
* Server listen blocks
*/
// Do not edit this line!
conf.servers = [];
// Example server block
conf.servers.push({
port: 7778,
address: "127.0.0.1"
});
// Example SSL server block
//conf.servers.push({
// port: 7777,
// address: "0.0.0.0",
//
// ssl: true,
// ssl_key: "server.key",
// ssl_cert: "cert.pem"
//});
// Network interface for outgoing connections
conf.outgoing_address = {
IPv4: '0.0.0.0'
//IPv6: '::'
};
// Do we want to enable the built in Identd server?
conf.identd = {
enabled: false,
port: 113,
address: "0.0.0.0"
};
// Where the client files are
conf.public_http = "client/";
// Transports available to the client.
// Behind an Apache reverse proxy? Uncomment the below - Apache does not support websockets!
//conf.client_transports = ['polling'];
// Max connections per connection. 0 to disable
conf.max_client_conns = 5;
// Max connections per server. 0 to disable.
// Setting is ignored if:
// - There is a WEBIRC password configured for the server,
// - Kiwi is configured to send the client's ip as a username for the server, or
// - Kiwi is running in restricted server mode.
conf.max_server_conns = 0;
/*
* Default encoding to be used by the server
* As specified and limited to iconv-lite library support.
*/
conf.default_encoding = 'utf8';
/*
* Default GECOS (real name) for IRC connections
* %n will be replaced with the users nick
* %h will be replaced with the users hostname
*/
conf.default_gecos = '%n@%h is using a Web IRC client';
/*
* Default ident / username for IRC connections
* %n will be replaced with the users nick
* %h will be replaced with the users hostname
* %i will be replaced with a hexed value of the users IP
*/
conf.default_ident = '%i';
/*
* Default quit message
* If a browser gets disconnected without sending a QUIT command, this
* message will be used instead.
*/
conf.quit_message = 'http://www.kiwiirc.com/ - A hand-crafted IRC client';
/*
* Auto reconnect if the IRC server disconnects a kiwi user
* Hundreds of connected users getting disconnected then reconnecting at once may see
* high CPU usage causing further dropouts. Set to false if under high usage.
*/
conf.ircd_reconnect = true;
/*
* Client side plugins
* Array of URLs that will be loaded into the browser when the client first loads up
* See http://github.com/prawnsalad/KiwiIRC/wiki/Client-plugins
*/
conf.client_plugins = [
// "http://server.com/kiwi/plugins/myplugin.html"
];
// Directory to find the server modules
conf.module_dir = "../server_modules/";
// Which modules to load
conf.modules = [
// Open a TCP port to control the Kiwi server (default port 8888)
// "control",
// Automatically reload CSS files when a theme changes
// "client_file_watcher",
];
// WebIRC password enabled for this server
conf.webirc_pass = "";
// Use the above *OR* the below webirc_pass option
// Multiple WebIRC passwords may be used for multiple servers
//conf.webirc_pass = {
// "irc.network.com": "configured_webirc_password",
// "127.0.0.1": "foobar"
//};
// Whether to verify IRC servers' SSL certificates against built-in well-known certificate authorities
conf.reject_unauthorised_certificates = false;
/*
* Reverse proxy settings
* Reverse proxies that have been reported to work can be found at:
* https://kiwiirc.com/docs/installing/proxies
*/
// Whitelisted HTTP proxies in CIDR format
conf.http_proxies = ["127.0.0.1/32"];
// Header that contains the real-ip from the HTTP proxy
conf.http_proxy_ip_header = "x-forwarded-for";
// Base HTTP path to the KIWI IRC client (eg. /kiwi)
conf.http_base_path = "/kiwi";
/*
* SOCKS (version 5) proxy settings
* This feature is only available on node 0.10.0 and above.
* Do not enable it if you're running 0.8 or below or Bad Things will happen.
*/
conf.socks_proxy = {};
// Enable proxying outbound connections through a SOCKS proxy
conf.socks_proxy.enabled = false;
// Proxy *all* outbound connections through a SOCKS proxy
conf.socks_proxy.all = false;
// Use SOCKS proxy for these hosts only (if conf.sock_proxy.all === false)
conf.socks_proxy.proxy_hosts = [
"irc.{{ external_domain }}"
];
// Host and port for the SOCKS proxy
conf.socks_proxy.address = '127.0.0.1';
conf.socks_proxy.port = 1080;
// Username and password for the SOCKS proxy
// Set user to null to disable password authentication
conf.socks_proxy.user = null;
conf.socks_proxy.pass = null;
// Default settings for the client. These may be changed in the browser
conf.client = {
server: 'localhost',
port: 6667,
ssl: false,
channel: '#lobby',
channel_key: '',
nick: 'kiwi_?',
settings: {
theme: 'cli',
text_theme: 'default',
channel_list_style: 'tabs',
scrollback: 250,
show_joins_parts: true,
show_timestamps: false,
use_24_hour_timestamps: true,
mute_sounds: false,
show_emoticons: true,
ignore_new_queries: false,
count_all_activity: false,
show_autocomplete_slideout: true,
locale: null // null = use the browser locale settings
},
window_title: '{{ organization['displayname'] }}/IRC | KiwiIRC Webchat'
};
// List of themes available for the user to choose from
conf.client_themes = [
'relaxed',
'mini',
'cli',
'basic'
];
// If set, the client may only connect to this 1 IRC server
conf.restrict_server = "127.0.0.1";
conf.restrict_server_port = 6667;
conf.restrict_server_ssl = false;
//conf.restrict_server_password = "";
/*
* If running multiple kiwi servers you may specify them here.
* Note: All kiwi servers must have the same conf.http_base_path config option.
*
* To force the client to connect to one other kiwi server, use:
* conf.client.kiwi_server = 'https://kiwi-server2.com';
*
* To force the client to connect to a random kiwi server from a list, use:
* conf.client.kiwi_server = ['https://kiwi-server1.com', 'https://kiwi-server2.com'];
*/
//conf.client.kiwi_server = '';
/*
* Do not amend the below lines unless you understand the changes!
*/
module.exports.production = conf;

View File

@@ -1,9 +1,9 @@
https://aur.archlinux.org/acidrip.git
https://aur.archlinux.org/aide.git
https://aur.archlinux.org/animecheck-git.git
https://aur.archlinux.org/anope.git
https://aur.archlinux.org/ascii-invaders.git
https://aur.archlinux.org/autopsy.git
https://aur.archlinux.org/brave-bin.git
https://aur.archlinux.org/brother-mfc-j430w.git
https://aur.archlinux.org/brscan4.git
https://aur.archlinux.org/carbonyl-bin.git
@@ -26,12 +26,9 @@ https://aur.archlinux.org/inspircd.git
https://aur.archlinux.org/irker.git
https://aur.archlinux.org/jmtpfs.git
https://aur.archlinux.org/js.git
https://aur.archlinux.org/lib32-glib.git
https://aur.archlinux.org/kiwiirc-server-bin.git
https://aur.archlinux.org/libdaq.git
https://aur.archlinux.org/libdwarf-20140413.git
https://aur.archlinux.org/libiconv.git
https://aur.archlinux.org/maya.git
https://aur.archlinux.org/meshlab.git
https://aur.archlinux.org/mkinitcpio-dropbear.git
https://aur.archlinux.org/mkinitcpio-netconf.git
https://aur.archlinux.org/mkinitcpio-utils.git

View File

@@ -1,134 +1,19 @@
Sora is the [https://en.wikipedia.org/wiki/LDAP LDAP]-enabled central crendential store of the AniNIX -- end users will have accounts here.
Sora is the [LDAP](https://en.wikipedia.org/wiki/LDAP)-enabled central credential store of the AniNIX -- end users will have accounts here.
# Etymology=Sora was the name of a pivotal character in the Kingdom of Hearts series. As Sora holds the "keys to the kingdom", the name fit.<!-- I've considered renaming this, but I'm kind of happy with it, even though I didn't follow the Kingdom of Hearts series. -->
# Etymology
A password is a ubiquitous method of asymmetric authentication. Militaries will use simple challenges & passwords to authenticate individuals b
# Relevant Files and Software
Most of the configuration initially is handled by the [https://aninix.net/foundation/ConfigPackages ConfigPackages'] Sora Makefile.
We use [file:///etc/openldap/users.d a users.d] folder to hold the default user definitions. uidNumber should generally start from 10000 and the .ldif files should never be deleted to track the maximum uidNumber.
We use [file:///etc/openldap/users.d](a users.d) folder to hold the default user definitions. uidNumber should generally start from 10000 and the .ldif files should never be deleted to track the maximum uidNumber.
# Available Clients
See [[:Category:LDAP]] for more information on the services that are clients of Sora.
Most services on AniNIX, ranging from SSH & IRC to web services like AniNIX/Foundation and AniNIX/Singularity, are LDAP clients. Our exceptions are below:
* MediaWiki (LDAP dropped out of support)
* AniNIX/Superintendent (client path not yet identified)
# Equivalents or Competition
Both [[:Category:Google|Google]] and Facebook offer distributed authentication systems. Google in particular is a good equivalent, as some of the services used by this network rely on its authentication for various products it provides internally.
Both Google and Facebook offer distributed authentication systems. Google in particular is a good equivalent, as some of the services used by this network rely on its authentication for various products it provides internally.
The AniNIX is not presently set up or planning to do distributed authentication.
}}
# Authorizing Other Services by Sora
## [[ShadowArch]] OS Authentication
You will need nss-pam-ldap as package installed. You will need to edit /etc/pam.d/su, /etc/pam.d/su-l, /etc/pam.d/system-auth, and /etc/nslcd.conf to match [https://eng.ucmerced.edu/soe/computing/services/ssh-based-service/ldap-ssh-access this link] and [https://wiki.archlinux.org/index.php/LDAP_authentication the Arch Wiki].
## [[Windows]] OS Authentication
We recommend the [https://pgina.org/ pGina] package -- this is a very smooth client.
## [[SSH]]
Edit /etc/ssh/sshd_config to allow PasswordAuthentication and PAM. This assumes the OS authentication is set up.
We recommend adding a passwdchange OS group on the external-facing SSH host and set up a ForceCommand around /usr/bin/passwd for users in that group. This allows you to enable centralized password changes from outside the command line for subscribing clients and then disable password changes in individual services.
## [[IRC|IRCServices]]
You will need to enable m_ldap and m_ldap_authentication in [file:///etc/anope/modules.aninix.conf the modules conf file]. The modules conf has the necessary parameters waiting to be filled in. We recommend updating the search_filter to "(&(!(shadowLastChange=0))(&(uid=%account)(objectClass=%object_class)))". This will prevent users from using a password reset by an administrator.
When you enable LDAP for IRCServices, we would recommend disabling email changes in m_ldap_authentication and disabling account creation in the NickServ configuration. Do not disable registration in m_ldap_authentication. This ensures that account provisioning is done by LDAP and users can group as necessary. Moreover, disable password changes by removing the NickServ set/*pass directives.
## [[Singularity]]
You'll need to update your plugins line in [file:///usr/share/webapps/tt-rss/config.php the config file] and add some parameters. Note: you'll be removing the auth_internal module, but you'll have to add it at least once to promote an LDAP user to admin.
<pre>
define('PLUGINS', 'auth_remote, note, updater, auth_ldap');
define('LDAP_AUTH_SERVER_URI', 'ldap://localhost:389/');
define('LDAP_AUTH_USETLS', FALSE); // Enable TLS Support for ldaps://
define('LDAP_AUTH_ALLOW_UNTRUSTED_CERT', TRUE); // Allows untrusted certificate
define('LDAP_AUTH_BINDDN', 'uid=binduser,ou=People,dc=aninix,dc=net');
define('LDAP_AUTH_BINDPW', 'secret');
define('LDAP_AUTH_BASEDN', 'ou=People,dc=aninix,dc=net');
define('LDAP_AUTH_ANONYMOUSBEFOREBIND', FALSE);
define('LDAP_AUTH_SEARCHFILTER', 'uid=???');
</pre>
## [[Wiki]]
Wiki is the most complicated to add with its multiple domain support, but the following snippet can be modified for a single domain. You'll need to comment out the fourth line at least once after logging in an LDAP user to promote that user to administrator.
<pre>
1. LDAP Modules
require_once( "extensions/LdapAuthentication/LdapAuthentication.php" );
require_once( "includes/AuthPlugin.php");
$wgAuth = new LdapAuthenticationPlugin();
1. LDAP Debugging
$wgLDAPDebug = 0;
$wgDebugLogGroups["ldap"] = "$IP/debug.log" ;
1. LDAP Connection info
$wgLDAPUseLocal = false;
$wgLDAPDomainNames = array( 'aninix.net', );
$wgLDAPServerNames = array( 'aninix.net' => 'localhost', );
$wgLDAPEncryptionType = array( 'aninix.net' => 'clear',
#'aninix.net' => 'tls',
);
1. $wgLDAPOptions = array( 'aninix.net' => array( LDAP_OPT_DEREF, 0 ), );
$wgLDAPPort = array( 'aninix.net' => 389, );
$wgLDAPProxyAgent = array( 'aninix.net' => 'uid=binduser,ou=People,dc=aninix,dc=net', );
$wgLDAPProxyAgentPassword = array( 'aninix.net' => 'secret', );
$wgLDAPSearchAttributes = array( 'aninix.net' => 'uid', );
$wgLDAPBaseDNs = array( 'aninix.net' => 'dc=aninix,dc=net', );
$wgLDAPGroupBaseDNs = array( 'aninix.net' => 'ou=Group,dc=aninix,dc=net', );
$wgLDAPUserBaseDNs = array( 'aninix.net' => 'ou=People,dc=aninix,dc=net', );
$wgLDAPAddLDAPUsers = array( 'aninix.net' => false, );
$wgLDAPUpdateLDAP = array( 'aninix.net' => false, );
$wgLDAPPreferences = array( 'aninix.net' => array( 'email' => 'mail','realname' => 'cn','nickname' => 'uid'), );
1. LDAP Access Only by Group Membership -- requires the memberOf overlay in Sora
1. $wgLDAPGroupUseFullDN = array( "aninix.net"=>false );
1. $wgLDAPGroupObjectclass = array( "aninix.net"=>"posixgroup" );
1. $wgLDAPGroupAttribute = array( "aninix.net"=>"memberuid" );
1. $wgLDAPGroupSearchNestedGroups = array( "aninix.net"=>false );
1. $wgLDAPGroupNameAttribute = array( "aninix.net"=>"cn" );
1. $wgLDAPRequiredGroups = array( "aninix.net"=>array("cn=wiki,ou=Group,dc=aninix,dc=net"));
1. Disable password changes.
$wgHooks['UserLoginForm'][] = 'lfChangeLoginPage';
function lfChangeLoginPage( &$template ) {
$template->set('canreset',false); // removes default reset password link
$template->set('resetlink',false);
// Use the following line to show your own 'reset password' link above the login fields
$template->set('link',"<a href='http://www.somedomain.org/lostpassword'>Forgot your password?</a>");
return true;
}
// Disallow password reset on password reset page
$wgHooks['UserLoginMailPassword'][] = 'MailPasswordIsAllowed';
function MailPasswordIsAllowed ( $username, $error ) {
$error = wfMsg( 'resetpass_forbidden' );
return false;
}
$wgHooks['PrefsPasswordAudit'][] = 'ChangePasswordIsAllowed';
function ChangePasswordIsAllowed ( $user ) {
throw new PasswordError( wfMsg( 'resetpass_forbidden' ));
return true;
}
$wgHooks['GetPreferences'][] = 'RemovePasswordChangeLink';
function RemovePasswordChangeLink ( $user, &$preferences ) {
unset($preferences['password']);
return true;
}
</pre>
# Making Changes
Ldapmodify will allow admins to change parts of Sora. Most user attributes can be updated like below.
<pre>
dn: uid=testuser,ou=People,dc=aninix,dc=net
changetype: modify
replace: mail
mail: blar@test.local
</pre>
Some properties are more intrinsic to the user object and require special handling.
<pre>
dn: uid=testuser1,ou=People,dc=aninix,dc=net
changetype: modrdn
newrdn: uid=testuser2
deleteoldrdn: 1
modifying rdn of entry "uid=testuser2,ou=People,dc=aninix,dc=net"
</pre>
[[Category:Security]]
[[Category:LDAP]]

View File

@@ -1 +0,0 @@
UiqiKXIU

View File

@@ -5,10 +5,10 @@ compile:
@echo Nothing to do
install: clean ${binlist} ${filelist}
mkdir -p ${pkgdir}/opt/aninix/Password/
mkdir -p ${pkgdir}/opt/aninix/Password/ ${pkgdir}/usr/lib/systemd/system ${pkgdir}/usr/local/sbin/
for i in ${filelist}; do install -m 0640 -o ldap -g ldap $$i ${pkgdir}/opt/aninix/Password/; done
mkdir -p ${pkgdir}/usr/local/sbin/
for i in ${binlist}; do install -m 0750 -o root -g root $$i ${pkgdir}/usr/local/sbin; done
for i in *.service *.timer; do install -m 0755 -o root -g root $$i ${pkgdir}/usr/lib/systemd/system; done
test: compile
@echo Nothing to do

View File

@@ -1,4 +1,4 @@
depends=('bash>=4.4' 'openldap')
depends=('bash>=4.4' 'openldap' 'ravensend' 'TheRaven')
makedepends=('make>=4.2')
checkdepends=()
optdepends=()

View File

@@ -1,5 +1,6 @@
#!/bin/bash
uid="$1"
if [ -z "$uid" ]; then
@@ -7,25 +8,33 @@ if [ -z "$uid" ]; then
exit 1
fi
# Get the bind password
read -sp 'cn=root,dc=aninix,dc=net Password: ' rootdnpw
printf "\n\n"
ldappasswd -D 'cn=root,dc=aninix,dc=net' -w "$rootdnpw" -H ldap://127.0.0.1 "uid=$uid,ou=People,dc=aninix,dc=net" && \
ldapmodify -D 'cn=root,dc=aninix,dc=net' -w "$rootdnpw" -H ldap://127.0.0.1 -f <(cat <<EOM
# Update the user password
tput setaf 1 1>&2; tput bold 1>&2;
/usr/bin/ldappasswd -D 'cn=root,dc=aninix,dc=net' -w "$rootdnpw" -H ldap://127.0.0.1 "uid=$uid,ou=People,dc=aninix,dc=net"
tput sgr0
# Ensure pwdReset is present
/usr/bin/ldapmodify -D 'cn=root,dc=aninix,dc=net' -w "$rootdnpw" -H ldap://127.0.0.1 -f <(cat <<EOM
dn: uid=$uid,ou=People,dc=aninix,dc=net
changetype: modify
add: pwdReset
pwdReset: TRUE
EOM
)
echo 'As cn=root,cn=config...' && ldapmodify -D 'cn=root,cn=config' -W -H ldap://127.0.0.1 -f <(cat <<EOM
# Remove pwdChangedTime for immediate update
/usr/bin/ldapmodify -e relax -D 'cn=root,dc=aninix,dc=net' -w "$rootdnpw" -H ldap://127.0.0.1 -f <(cat <<EOM
dn: uid=$uid,ou=People,dc=aninix,dc=net
changetype: modify
delete: pwdChangedTime
EOM
)
# Exit
exit $?

View File

@@ -9,10 +9,19 @@ function getLDAPAttr() {
ldapsearch -x "${filter}" "${attribute}" | grep -E "^${attribute}: " | sed "s/${attribute}: //"
}
# Clear cleanup files
ldif="/root/cleanup.ldif"
>"${ldif}"
bash="/root/cleanup.bash"
if [ "$1" == "-h" ]; then
cat <<EOM
Usage: $0
Add -m to mute the use of ravensend.
Writes ${ldif} and ${bash} for follow-up by admins.
EOM
exit 0
fi
# Clear cleanup files
>"${ldif}"
echo "#!/bin/bash" > "${bash}"
# Attributes
@@ -84,12 +93,12 @@ fi
# Report when users are expiring -- give them several notices to fix it.
if [ -n "${EXPIRING}" ]; then
echo "EXPIRING: ${EXPIRING}"
ravensend -c "#tech" -m "The following users are expiring: ${EXPIRING}"
if [ "$1" != '-m' ]; then ravensend -c "#tech" -m "The following users are expiring: ${EXPIRING}"; fi
fi
# Report users that have expired. These users should be contacted or removed.
if [ -n "${EXPIRED}" ]; then
echo "EXPIRED: ${EXPIRED}"
echo "Expired users can be cleaned up with ${ldif} and ${bash}"
ravensend -c "#sharingan" -m 'Users have expired and need attention.'
echo "Expired users can be cleaned up with ${ldif} and ${bash}. Run /usr/bin/pwck and /usr/bin/grpck afterwards."
if [ $1 != '-m' ]; then ravensend -c "#sharingan" -m 'The following users have expired and need attention.'; fi
fi

View File

@@ -0,0 +1,12 @@
[Unit]
Description=AniNIX/Password | LDAP User Report
After=network.target raven.service ravensend-daemon.service
[Service]
Type=oneshot
ExecStart=/bin/bash /usr/local/sbin/ldap-userreport
ExecReload=/bin/kill -HUP $MAINPID
KillMode=process
[Install]
WantedBy=multi-user.target

View File

@@ -0,0 +1,7 @@
[Unit]
Description=AniNIX/Password | LDAP User Report
[Timer]
OnCalendar=Mon *-*-* 09:00:00
RandomizedDelaySec=1m
Persistent=true

View File

@@ -0,0 +1,8 @@
---
- name: Enable timer for auditing Password
become: yes
service:
name: ldap-userreport.timer
state: started
enabled: yes

View File

@@ -1,14 +1,6 @@
---
- name: Create the base config
become: yes
template:
src: slapd.ldif
dest: /etc/openldap/slapd.ldif
owner: ldap
group: ldap
mode: 0640
- name: Create the directories
become: yes
file:
path: "{{ item }}"
owner: ldap
@@ -21,15 +13,25 @@
- /etc/openldap/groups.d
- /etc/openldap/slapd.d
- name: Initialize the instance
become: yes
command:
cmd: slapadd -n 0 -F /etc/openldap/slapd.d/ -l /etc/openldap/config.ldif && chown -R ldap: /etc/openldap
creates: /etc/openldap/slapd.d/cn=config
# - name: Create the base config
# become: yes
# template:
# src: slapd.ldif
# dest: /etc/openldap/slapd.ldif
# owner: ldap
# group: ldap
# mode: 0640
# - name: Initialize the instance
# become: yes
# command:
# cmd: "slapadd -n 0 -F /etc/openldap/slapd.d/ -l /etc/openldap/config.ldif && chown -R ldap: /etc/openldap"
# creates: /etc/openldap/slapd.d/cn=config
- name: Ensure the service
become: yes
ignore_errors: true
service:
name: slapd
state: restarted
state: started
enabled: yes

View File

@@ -4,6 +4,7 @@
package:
name:
- openldap
- freeradius
- Password-Scripts
- include_tasks: daemon.yml
@@ -11,3 +12,7 @@
- include_tasks: login.yml
- include_tasks: web.yml
- include_tasks: audit.yml
- include_tasks: freeradius.yml

View File

@@ -5,6 +5,7 @@
git:
repo: https://github.com/ltb-project/self-service-password
dest: /usr/share/webapps/self-service-password
update: no
- name: Ensure web portal ownership
file:
@@ -17,7 +18,7 @@
- name: Web portal config
become: yes
template:
src: config.inc.php.j2
src: ltb-ssp.config.inc.php.j2
dest: /usr/share/webapps/self-service-password/conf/config.inc.php
owner: http
group: http

View File

@@ -0,0 +1,31 @@
<?php
$lang = "en";
$show_menu = false;
$show_help = false;
$logo = "";
//$logo = "images/AniNIX.png";
$default_action = "change";
$notify_on_change = false;
$use_sms = false;
$ldap_url = "ldap://localhost:389";
$ldap_binddn = "{{ secrets['Password']['binduser'] }},{{ ldap['orgdn'] }}";
$ldap_bindpw = "{{ secrets['Password']['bindpassword'] }}";
$who_change_password = "user";
$ldap_base = "{{ ldap['orgdn'] }}";
$keyphrase = "";
// Requirements
$pwd_min_lower = 1;
$pwd_min_upper = 1;
$pwd_min_digit = 1;
$pwd_min_special = 1;
$pwd_complexity = 4;
$pwd_min_length = 8;
$hash = "ssha";
// Recaptcha currently doesn't work for changes in SameSite cookie attribute.
$use_recaptcha = false;
$recaptcha_publickey = "{{ secrets['Password']['recaptcha_publickey'] }}";
$recaptcha_privatekey = "{{ secrets['Password']['recaptcha_privatekey'] }}";
$recaptcha_theme = "dark";
$recaptcha_type = "image";
$recaptcha_size = "normal";
?>

View File

@@ -15,7 +15,7 @@ gid nslcd
#uri ldaps://127.0.0.1/
#uri ldapi://%2fvar%2frun%2fldapi_sock/
# Note: %2f encodes the '/' used as directory separator
uri ldap://{{ ldap['server'] }}/
uri ldap://127.0.0.1/
# The LDAP version to use (defaults to 3
# if supported by client library)
@@ -26,12 +26,12 @@ base {{ ldap['orgdn'] }}
# The distinguished name to bind to the server with.
# Optional: default is to bind anonymously.
binddn {{ ldap['binduser'] }},{{ ldap['userou'] }},{{ ldap['orgdn'] }}
binddn uid=binduser,{{ ldap['userou'] }},{{ ldap['orgdn'] }}
# The credentials to bind with.
# Optional: default is no credentials.
# Note that if you set a bindpw you should check the permissions of this file.
bindpw {{ secrets['Sora']['bindpassword'] }}
bindpw {{ secrets['Password']['bindpassword'] }}
# The distinguished name to perform password modifications by root by.
rootpwmoddn cn=root,{{ ldap['orgdn'] }}
@@ -43,9 +43,9 @@ scope sub
#scope base
# Customize certain database lookups.
base group {{ ldap['groupou'] }},{{ ldap['orgdn'] }}
base passwd {{ ldap['userou'] }},{{ ldap['orgdn'] }}
base shadow {{ ldap['userou'] }},{{ ldap['orgdn'] }}
base group ou=Group,{{ ldap['orgdn'] }}
base passwd ou=People,{{ ldap['orgdn'] }}
base shadow ou=People,{{ ldap['orgdn'] }}
#scope group onelevel
scope hosts sub

View File

@@ -44,6 +44,9 @@ GSSAPIAuthentication no
PermitRootLogin no
PermitEmptyPasswords no
# Allow other packages to ship snippets
Include /etc/ssh/includes/*
## By default, only ssh-allow or ldapusers are allowed to sftp
AllowGroups ssh sftp ldapuser
Match Group ldapuser,sftp
@@ -58,6 +61,3 @@ Match Group wheel,ssh-allow
X11Forwarding yes
ForceCommand none
ChrootDirectory none
# Allow other packages to ship snippets
Include /etc/ssh/includes/*

View File

@@ -79,12 +79,6 @@ Include = /etc/pacman.d/mirrorlist.shadowarch
[extra]
Include = /etc/pacman.d/mirrorlist.shadowarch
#[community-testing]
#Include = /etc/pacman.d/mirrorlist
[community]
Include = /etc/pacman.d/mirrorlist.shadowarch
# If you want to run 32 bit applications on your x86_64 system,
# enable the multilib repositories as required here.

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

View File

@@ -0,0 +1,89 @@
# Example configuration file for AIDE.
# More information about configuration options available in the aide.conf manpage.
@@define DBDIR /home/yggdrasil/.aide
@@define LOGDIR @@{DBDIR}
# The location of the database to be read.
database_in=file:@@{DBDIR}/aide.db.gz
database_out=file:@@{DBDIR}/aide.new.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
# 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.
/home/yggdrasil/ NORMAL
!/home/yggdrasil/.aide$

View File

@@ -1 +1,2 @@
include "/etc/monit.d/checks/system"
include "/etc/monit.d/checks/automated_response"

View File

@@ -1,2 +1,3 @@
include "/etc/monit.d/checks/system"
include "/etc/monit.d/checks/automated_response"
include "/etc/monit.d/checks/cyberpower"

View File

@@ -1 +1,2 @@
include "/etc/monit.d/checks/system"
include "/etc/monit.d/checks/automated_response"

View File

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

View File

@@ -0,0 +1,22 @@
compile:
@echo Nothing to do
install:
mkdir -p ${pkgdir}/usr/local/sbin/
for i in aidecheck aideinit; do install -m 0750 -o root -g http $$i ${pkgdir}/usr/local/sbin/; done
test: compile
@echo Nothing to do
clean:
git clean -fX
git clean -fd
diff:
@echo Nothing to do.
reverse:
@echo Nothing to do.
checkperm:
@echo Nothing to do.

View File

@@ -0,0 +1,46 @@
depends=('bash>=4.4' 'aide')
makedepends=('make>=4.2')
checkdepends=()
optdepends=()
pkgname="sharingan-scripts"
pkgver="$(git describe --tag --abbrev=0)"."$(git rev-parse --short HEAD)"
pkgrel=1
pkgrel() {
echo $(( `git log "$(git describe --tag --abbrev=0)"..HEAD | grep -c commit` + 1 ))
}
epoch="$(git log | grep -c commit)"
pkgdesc="$(head -n 1 README.md)"
arch=("x86_64")
url="$(git config remote.origin.url | sed 's/.git$//')"
license=('custom')
groups=()
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"
}

View File

@@ -0,0 +1,4 @@
This is a collection of scripts we use for managing HIDS data.
1. aideinit: Initialize, record, and sign a database
1. aidecheck: Verify there are no discrepancies from a database

View File

@@ -0,0 +1,59 @@
#!/usr/bin/bash
# File: aidecheck
#
# Description: This script checks a signed AIDE DB.
#
# Package: AniNIX/Sharingan
# Copyright: WTFPL
#
# Author: DarkFeather <ircs://aninix.net:6697/DarkFeather>
function usage() {
echo "Usage: $0 [ config reference ]"
exit $1
}
function main() {
### Initialize the DB
base="$1"
dbdir="$(grep -m 1 -E '^@@define DBDIR' "$base" | cut -f 3 -d ' ')"
dbin="$(grep -m 1 -E '^database_in' "$base" | cut -f 2 -d '=' | sed "s#file:...DBDIR.#${dbdir}#")"
dbout="$(grep -m 1 -E '^database_out' "$base" | cut -f 2 -d '=' | sed "s#file:...DBDIR.#${dbdir}#")"
set -x
if ! gpg --verify "$dbin".sig "$dbin"; then
echo "$dbin doesn't match signature."
exit 1
fi
sudo aide -c "$base" -C
}
### MAIN
if [ `basename "$0"` == "aidecheck" ]; then
# Allow -h for helptext
if [ "$1" == '-h' ]; then
echo "Checks an AIDE DB"
usage 0
else
# Find the config
if [ -z "${1}" ]; then
base='/etc/aide.conf'
else
base="/etc/aide/${1}.conf"
fi
if [ -f "$base" ]; then
main "$base"
else
# If it doesn't, explain and exit.
echo "$base does not exist"
usage 1
fi
fi
fi

View File

@@ -0,0 +1,59 @@
#!/usr/bin/bash
# File: aideinit
#
# Description: This script initializes an AIDE DB and signs it
#
# Package: AniNIX/Sharingan
# Copyright: WTFPL
#
# Author: DarkFeather <ircs://aninix.net:6697/DarkFeather>
function usage() {
echo "Usage: $0 [ config reference ]"
exit $1
}
function main() {
### Initialize the DB
base="$1"
dbdir="$(grep -m 1 -E '^@@define DBDIR' "$base" | cut -f 3 -d ' ')"
dbin="$(grep -m 1 -E '^database_in' "$base" | cut -f 2 -d '=' | sed "s#file:...DBDIR.#${dbdir}#")"
dbout="$(grep -m 1 -E '^database_out' "$base" | cut -f 2 -d '=' | sed "s#file:...DBDIR.#${dbdir}#")"
# sudo chattr -i "$dbin"*
sudo aide -c "$base" -i 2>&1 | sudo tee "$dbin".out
sudo mv "$dbout" "$dbin"
sudo chmod 0644 "$dbin"
gpg -bs --output - "$dbin" | sudo tee "$dbin".sig &>/dev/null
sudo chown root: "$dbin"*
sudo chmod 0755 "$dbin"*
# sudo chattr +i "$dbin"*
}
### MAIN
if [ `basename "$0"` == "aideinit" ]; then
# Allow -h for helptext
if [ "$1" == '-h' ]; then
echo "Initializes an AIDE DB"
usage 0
else
# Find the config
if [ -z "${1}" ]; then
base='/etc/aide.conf'
else
base="/etc/aide/${1}.conf"
fi
if [ -f "$base" ]; then
main "$base"
else
# If it doesn't, explain and exit.
echo "$base does not exist"
usage 1
fi
fi
fi

View File

@@ -5,10 +5,12 @@
register: package_install
package:
name:
- aide
- sshguard
- suricata
- oinkmaster
- rkhunter
- sharingan-scripts
state: present
# Network IPS
@@ -73,6 +75,15 @@
group: root
mode: 0644
- name: Create aide conf folder
become: yes
copy:
src: "aide/"
dest: /etc/aide
owner: root
group: root
mode: 0755
# Network IDS
- name: Copy oinkmaster conf
register: oinkmaster_conf

View File

@@ -4,7 +4,7 @@
register: sharingan_packages
package:
name:
- elasticsearch
- opensearch
- mongodb-bin
- mongodb-tools-bin
- graylog
@@ -13,7 +13,7 @@
- name: Sharingan services
become: yes
loop:
- elasticsearch
- opensearch
- mongodb
- graylog
service:
@@ -24,11 +24,11 @@
- name: Sharingan backups directory
become: yes
file:
path: /usr/local/backups/elasticsearch
path: /usr/local/backups/opensearch
state: directory
owner: elasticsearch
group: elasticsearch
mode: 0770
- name: Set Sharingan backups
command: "curl -X PUT localhost:9200/_snapshot/my_backup?pretty -H 'Content-Type: application/json' -d '{ type: fs, settings: { location: /usr/local/backup/elasticsearch, compress: true } }'"
command: "curl -X PUT localhost:9200/_snapshot/my_backup?pretty -H 'Content-Type: application/json' -d '{ type: fs, settings: { location: /usr/local/backup/opensearch, compress: true } }'"

View File

@@ -1,35 +1,39 @@
---
- name: Install Tachikoma packages
become: yes
package:
become: true
ansible.builtin.package:
name:
- wifi-menu
- weechat
- elinks
- wifi-menu # Needed XFCE4 add-ons
- conky
- xfce4
- xfce4-goodies
- xfce4-screenshooter
- xscreensaver
- libreoffice-still
- alsamixer
- sshfs # Mount helpers
- mtpfs
- libmtp
- libreoffice-still # Office
- hunspell
- hunspell-en_us
- google-chrome
- keepassxc
- sshfs
- vlc
- cups
- weechat # Clients
- elinks
- google-chrome
- vlc # Multimedia
- sound-juicer
- obs-studio
- kdenlive
- gimp
- cups # Printing
- brother-mfc-j430w
- brscan4
- xsane
- mtpfs
- libmtp
- alsamixer
- name: Remove deprecated packages
become: yes
package:
become: true
ansible.builtin.package:
name:
- chromium
- keepassx
@@ -38,10 +42,10 @@
- lynx
- name: Enable services
become: yes
service:
become: true
ansible.builtin.service:
name: "{{ item }}"
state: running
enabled: yes
enabled: true
with:
- cups.service

View File

@@ -8,10 +8,26 @@ server {
location /
{
proxy_set_header Host $http_host;
root /usr/share/kiwiirc;
autoindex on;
autoindex_format html;
}
location /websocket/ {
proxy_pass http://unix:/run/inspircd/websocket.sock;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header X-Original-Host $host;
proxy_set_header X-Original-Protocol $scheme;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://127.0.0.1:7778;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-For $remote_addr;
}
}

View File

@@ -1,16 +0,0 @@
server {
listen 443 ssl http2;
server_name wolfpack.aninix.net;
include conf/sec.conf;
include conf/default.csp.conf;
location /
{
root /srv/wolfpack;
autoindex on;
autoindex_format html;
}
include conf/letsencrypt.conf;
}

View File

@@ -7,6 +7,7 @@ error_log logs/error.log notice;
error_log logs/error.log info;
load_module /usr/lib/nginx/modules/ngx_http_modsecurity_module.so;
load_module /usr/lib/nginx/modules/ngx_http_geoip2_module.so;
events {
worker_connections 1024;
@@ -24,6 +25,8 @@ http {
keepalive_timeout 65;
gzip on;
include conf/geoip.conf;
# Redirect all HTTP to HTTPS
server {

View File

@@ -9,6 +9,7 @@
- nginx
- libmodsecurity
- nginx-mod-modsecurity
- nginx-mod-geoip2
- php
- php-fpm
@@ -103,6 +104,27 @@
mode: 0660
register: secconf
- name: Populate GeoIP config
become: yes
template:
src: conf/geoip.conf.j2
dest: /etc/nginx/conf/geoip.conf
owner: http
group: http
mode: 0660
register: geoipconf
- name: Ensure MaxMindDB is present
become: yes
file:
path: /etc/nginx/conf/maxmind-geoip2.mmdb
state: file
owner: http
group: http
mode: 0440
# This requires a https://maxmind.com/ account, so the source will have to come from that site.
# This file should be the current country database.
- name: Clone OWASP-CRS
ignore_errors: true
become: yes
@@ -148,7 +170,7 @@
- name: Ensure service is started
become: yes
when: conf.changed or confd.changed or secconf.changed or baseconf.changed or modsecconf.changed
when: conf.changed or confd.changed or geoipconf.changed or secconf.changed or baseconf.changed or modsecconf.changed
service:
name: "{{ item }}"
enabled: yes

View File

@@ -0,0 +1,28 @@
# Load database and set variables from the database.
geoip2 /etc/nginx/conf/maxmind-geoip2.mmdb {
auto_reload 60m;
$geoip2_metadata_country_build metadata build_epoch;
$geoip2_data_country_code country iso_code;
$geoip2_data_country_name country names en;
}
fastcgi_param COUNTRY_CODE $geoip2_data_country_code;
fastcgi_param COUNTRY_NAME $geoip2_data_country_name;
# Allow LAN and operational countries.
geo $lan {
default 0;
{{ main_subnet }}/{{ netmask }} 1;
}
map $geoip2_data_country_code $allowed_country {
default 0;
{% for country in operational_countries %}
{{ country }} 1;
{% endfor %}
}
# Define the deny variable such that LAN & country requests are allowed.
# Thanks to https://stackoverflow.com/a/64071860 for the example
map $lan$allowed_country $deny {
default 0;
00 1;
}

View File

@@ -1,4 +1,4 @@
WolfPack is a webcrawler for the AniNIX. Public results from Core's instance will be available from [https://wolfpack.aninix.net/wolfpack the WebServer] -- this may be locked to admins, for reproducibility reasons.
WolfPack is a webcrawler for the AniNIX. Public results from Core's instance will be available from AniNIX/Cyberbrain & SFTP services. Internal instances will transfer files via SSHFS.
Note: Code for this service is encoded in [the WolfPack repo](/AniNIX/WolfPack) rather than here -- we just include the package.

View File

@@ -1,3 +1,3 @@
search
/srv/wolfpack/
/home/wolfpack/
aninix.net

View File

@@ -1,4 +1,4 @@
download
/srv/wolfpack
/home/wolfpack
curl -s 'https://mirror.rackspace.com/archlinux/iso/latest/' | grep -m 1 x86_64.iso | cut -f 2 -d \"
echo https://mirror.rackspace.com/archlinux/iso/latest/PREVRESULT

View File

@@ -1,4 +1,4 @@
search
/srv/wolfpack
/home/wolfpack
Eminem Shows
Eminem Concerts

View File

@@ -1,4 +1,4 @@
download
/srv/wolfpack
/home/wolfpack
curl -s http://cdimage.kali.org/current/ | grep -m 1 live-amd64.iso | cut -f 4 -d '"'
echo http://cdimage.kali.org/current/PREVRESULT

View File

@@ -1,3 +1,3 @@
download
/srv/wolfpack
/home/wolfpack
echo https://downloads.raspberrypi.org/imager/imager_latest.exe

View File

@@ -1,14 +1,14 @@
---
- name: Packages
become: yes
package:
become: true
ansible.builtin.package:
state: present
name:
- WolfPack
- name: File config
become: yes
become: true
when: "wolfpack_config is not defined"
ansible.posix.synchronize:
src: "{{ inventory_hostname }}/"
@@ -16,31 +16,32 @@
delete: true
- name: Git config
become: yes
become: true
when: "wolfpack_config is defined"
git:
ansible.builtin.git:
# noqa: latest
repo: "{{ wolfpack_config }}"
dest: /usr/local/etc/WolfPack
clone: yes
update: no
clone: true
update: false
- name: Hardening
become: yes
become: true
loop:
- /usr/local/etc/WolfPack
- /srv/wolfpack
file:
- /home/wolfpack
ansible.builtin.file:
path: "{{ item }}"
state: directory
owner: wolfpack
group: wolfpack
mode: 0755
mode: "0755"
recurse: true
- name: Timer
become: yes
systemd:
become: true
ansible.builtin.systemd:
name: "{{ wolfpack_service | default('wolfpack.timer') }}"
state: started
enabled: yes
daemon_reload: yes
enabled: true
daemon_reload: true

View File

@@ -2,8 +2,9 @@ compile:
@echo Nothing to do
install: clean
rm -Rf yggdrasil-scripts-*
mkdir -p ${pkgdir}/usr/local/bin/
for i in yggdrasil-get yggdrasil-lock yggdrasil-set-music-data yggdrasil-sha256 yggdrasil-sort-shows yggdrasil-unlock; do install -m 0750 -o root -g http $$i ${pkgdir}/usr/local/bin/; done
for i in yggdrasil-*; do install -m 0750 -o root -g http $$i ${pkgdir}/usr/local/bin/; done
mkdir -p ${pkgdir}/usr/lib/systemd/system
for i in *.timer *.service; do install -m 0755 -o root -g root $$i ${pkgdir}/usr/lib/systemd/system; done
@@ -11,8 +12,7 @@ test: compile
@echo Nothing to do
clean:
git clean -fX
git clean -fd
git clean -fdX
diff:
@echo Nothing to do.

View File

@@ -1,4 +1,4 @@
depends=('bash>=4.4')
depends=('bash>=4.4' 'python-mutagen' 'perl-image-exiftool' 'yt-dlp')
makedepends=('make>=4.2')
checkdepends=()
optdepends=()

View File

@@ -2,7 +2,7 @@ This is a collection of scripts we use for managing yggdrasil data.
1. yggdrasil-get: API for pulling data into Yggdrasil.
1. yggdrasil-lock: API for setting permissions safely.
1. yggdrasil-set-music-data: API for updating a music file with the new detected metadata from the path. Assumes `/srv/yggdrasil/Music/$genre/$artist/$album`.
1. yggdrasil-set-music-data: API for updating a music file with the new detected metadata from the path. Assumes `/home/yggdrasil/Music/$genre/$artist/$album`.
1. yggdrasil-sha256: Get a SHA-256 hash of the current library. This is good for checking media changes over time in conjunction with [AniNIX/Aether](/AniNIX/Aether).
1. yggdrasil-sort-shows: Look at `/srv/yggdrasil/new_acquisition` and try to find the right folder in `/srv/yggdrasil/Videos/Shows` to stash it in. Will try to put it under the show name and the season.
1. yggdrasil-sort-shows: Look at `/home/yggdrasil/new_acquisition` and try to find the right folder in `/home/yggdrasil/Videos/Shows` to stash it in. Will try to put it under the show name and the season.
1. yggdrasil-unlock: API for allowing writes to media.

View File

@@ -1,23 +1,109 @@
#!/bin/bash
export YGGDRASIL="/srv/yggdrasil"
source /opt/aninix/Uniglot/Bash/header
function ygdl() {
### Download a file
# param path: path to make
# param newname (optional): output location
if [ "$newname" != "" ]; then
wget -O "$newname" "$path";
else
wget "$path";
fi
}
function ygyt() {
### Cache from YouTube
# param path: YouTube URI
# param newname: output location
if [ `echo "$path" | grep -c '/watch?v='` -eq 1 ]; then
path="$(echo "$path" | cut -f 1 -d '&')"
fi
if [ "$newname" != "" ]; then
yt-dlp -o "$newname" "$path";
else
yt-dlp "$path";
fi
}
function ygmp3() {
uri="$path"
if [ "$newname" != "" ]; then
ygmkdir "$newname"
cd "$newname"
fi
if [ `echo "$uri" | grep -c '/watch?v='` -eq 1 ]; then
uri="$(echo "$uri" | cut -f 1 -d '&')"
fi
youtube-mp3 "$uri";
yggdrasil-set-music-data *.mp3
}
function ygcache() {
### Cache files
# param path: path to move
# param newname (option): somewhere other than $PWD to move
# param exec: what to use
if [ -n "$1" ]; then
exec="$1"
fi
if [ "$newname" != "" ]; then
$exec "$path" ./"$newname"
else
$exec "$path" .
fi
}
function ygmkdir() {
### Make a directory
# path: directory to make
if [ -n "$1" ]; then
path="$1"
fi
if [ -d "$path" ]; then
infoheader "Directory '$path' already existed."
else
mkdir -p "$path"
chmod u+w "$path"
fi
}
function usage() {
### Usage
# param retcode: what to return
if [ -z "$1" ]; then
retcode=0;
else
retcode=$1;
fi
cat << EOM
AniNIX/Yggdrasil Bash API
Syntax: yggdrasil-get {dl|yt|mp3|cp|mv|mkdir} PATH [new file name in $PWD]
Option:
-- dl: Use wget
-- yt: Use yt-dlp
-- mp3: Use youtube-mp3
-- cp: Copy the file here.
-- mv: Move the file here.
-- mkdir: Make a folder
EOM
exit $retcode
}
### Main
export YGGDRASIL="/home/yggdrasil"
if [ "$1" == '-v' ]; then
set -x
shift
fi
option="$1"
path="$2"
newname="$3"
#Offer help
if [ "$option" == "" ] || [ "$option" == "-h" ] || [ "$option" == "--help" ] || [ "$path" == "" ] || [ $(echo $newname | grep -c '/') -ne 0 ]; then
echo "AniNIX::Yggdrasil Bash API"
echo 'Syntax: yggdrasil-get {dl|yt|mp3|sol|cp|mv} PATH [new file name in $PWD]'
echo "Option:"
echo "-- dl: Use wget"
echo "-- yt: Use youtube-dl"
echo "-- mp3: Use youtube-mp3"
echo "-- sol: Use solarmovie-vodlocker-dl"
echo "-- cp: Copy the file here."
echo "-- mv: Move the file here."
echo "-- mkdir: Make a folder"
exit;
if [ "$option" == "" ] || [ "$option" == "-h" ] || [ "$option" == "--help" ] || [ "$path" == "" ]; then
usage 0;
fi
#Make sure we're in the Yggdrasil project.
@@ -29,62 +115,21 @@ fi
#unlock this directory
chmod ug+w "$PWD"
#Appropriately source the file
if [ $? -ne 0 ]; then
echo Couldn\'t unlock $PWD
exit
exit 1
fi
if [ "$option" == "dl" ]; then
if [ "$newname" != "" ]; then
wget -O "$newname" "$path";
else
wget "$path";
fi
fi
if [ "$option" == "yt" ]; then
if [ `echo "$path" | grep -c '/watch?v='` -eq 1 ]; then
path="$(echo "$path" | cut -f 1 -d '&')"
fi
if [ "$newname" != "" ]; then
youtube-dl -o "$newname" "$path";
else
youtube-dl "$path";
fi
fi
if [ "$option" == "mp3" ]; then
if [ "$newname" != "" ]; then
echo "Renaming not available."
fi
if [ `echo "$path" | grep -c '/watch?v='` -eq 1 ]; then
path="$(echo "$path" | cut -f 1 -d '&')"
fi
youtube-mp3 "$path";
yggdrasil-set-music-data *.mp3
fi
if [ "$option" == "sol" ]; then
if [ "$newname" != "" ]; then
solarmovie-vodlocker-dl "$path" "$newname"
else
echo "Need a name."
fi
fi
if [ "$option" == "cp" ]; then
if [ "$newname" != "" ]; then
cp "$path" ./"$newname"
else
cp "$path" .
fi
fi
if [ "$option" == "mv" ]; then
if [ "$newname" != "" ]; then
mv "$path" ./"$newname"
else
mv "$path" .
fi
fi
if [[ "$option" == "mkdir" && "$path" != "" ]]; then
mkdir -p "$path"
fi
# Functional loop
case "$option" in
dl) ygdl ;;
yt) ygyt ;;
mp3) ygmp3 ;;
cp) ygcache cp ;;
mv) ygcache mv ;;
mkdir) ygmkdir ;;
*) usage 1 ;;
esac
#Lock
chmod -R ug-w "$PWD"

View File

@@ -1,5 +1,5 @@
#!/bin/bash
chown -P -R DarkFeather:http /srv/yggdrasil
find -P /srv/yggdrasil/ -type f -exec chmod 0440 {} \;
find -P /srv/yggdrasil/ -type d -exec chmod 0550 {} \;
chmod -R u+w /srv/yggdrasil/new_acquisition
chown -P -R emby:yggdrasil /home/yggdrasil
find -P /home/yggdrasil/ -type f -exec chmod 0440 {} \;
find -P /home/yggdrasil/ -type d -exec chmod 0550 {} \;
chmod -R u+w /home/yggdrasil/new_acquisition

View File

@@ -19,30 +19,21 @@ echo Genre: $pgenre
echo
for i in $@; do
echo Checking "$i"
if [ ! -f "$i" ]; then
echo File doesn\'t exist. $i
continue;
fi
ffartist="$(ffprobe -hide_banner -i $i 2>&1 | grep artist | grep -v 'album_artist' | cut -f 2 -d ':' | sed -e 's/^[[:space:]]*//' | sed -e 's/*[[:space:]]$//')"
ffalbum="$(ffprobe -hide_banner -i $i 2>&1 | grep album | grep -v 'album_artist' | cut -f 2 -d ':' | sed -e 's/^[[:space:]]*//' | sed -e 's/*[[:space:]]$//')"
ffgenre="$(ffprobe -hide_banner -i $i 2>&1 | grep genre | head -n 1 | cut -f 2 -d ':' | sed -e 's/^[[:space:]]*//' | sed -e 's/*[[:space:]]$//')"
echo For \[$i\]...
fartist="$(exiftool -Artist "$i" | sed 's/^Artist\s\+:\s\+//')"
falbum="$(exiftool -Album "$i" | sed 's/^Album\s\+:\s\+//')"
fgenre="$(exiftool -Genre "$i" | sed 's/^Genre\s\+:\s\+//')"
unset tags
echo Found artist \[$ffartist\]
if [ "$partist" != "$ffartist" ]; then
export tags=$tags" -metadata artist=\"$partist\""
fi
echo Found album \[$ffalbum\]
if [ "$ffalbum" != "$palbum" ]; then
export tags=$tags" -metadata album=\"$palbum\""
fi
echo Found genre \[$ffgenre\]
if [ "$ffgenre" != "$pgenre" ]; then
export tags=$tags" -metadata genre=\"$pgenre\""
fi
if [ "$tags" != "" ]; then
bash -c "ffmpeg -hide_banner -i \"$i\"$tags \"$i.ffmpeg.mp3\""
mv "$i.ffmpeg.mp3" "$i"
fi
if [ "$partist" != "$fartist" ] || [ "$falbum" != "$palbum" ] || [ "$fgenre" != "$pgenre" ]; then
echo Found artist \[$fartist\]
echo Found album \[$falbum\]
echo Found genre \[$fgenre\]
echo Updating...
mid3v2 -a "$partist" -A "$palbum" -g "$pgenre" "$i" &>/dev/null
echo
fi
done

View File

@@ -1,26 +0,0 @@
#!/bin/bash
set -x
basedir="/srv/yggdrasil"
shafile="$basedir""/library.sha256"
option="$1"
if [ "$option" == "-h" ] || [ "$option" == "--help" ]; then
echo Usage: $0 '[verify]'
exit 1
fi
if [[ "$option" != "verify" ]]; then
chmod u+w "$basedir"
touch "$shafile"
chmod u+w "$shafile"
find "$basedir" -type f -exec sha256sum {} \; > "$shafile"
chmod u-w "$basedir" "$shafile"
exit 0;
else
echo "These files have problems:"
sha256sum -c "$shafile";
exit $?;
fi

View File

@@ -1,10 +1,10 @@
#!/bin/bash
baseDir="/srv/yggdrasil/Videos/Shows"
baseDir="/home/yggdrasil/Videos/Shows"
# Helptext
function usage() {
echo Sort files from /srv/yggdrasil/new_acquisition into appropriate show directories.
echo Sort files from /home/yggdrasil/new_acquisition into appropriate show directories.
echo
echo Usage: $0 '[ -h ] [ -f fileToUse ] [ -c ] [ -n ] [ -q ] [ -v ]'
echo ' -c: Create sample sort file'
@@ -21,7 +21,7 @@ function HandleFile() {
file="$1"
# Sort out file metadata
dirtyshowname="$(echo "$file" | sed 's/.[Ss][0-9].[Ee][0-9].*$//')"
showname="$(ls -1 "$baseDir" | grep -iE "$dirtyshowname")"
showname="$(ls -1 "$baseDir" | grep -E -i "$dirtyshowname")"
epinfo="$(echo "$file" | sed "s/^${dirtyshowname}.//" | head -c 6)"
season="$(echo "$epinfo" | head -c 3 | tail -c 2)"
episode="$(echo -n "$epinfo" | tail -c 2)"
@@ -57,7 +57,7 @@ while getopts 'b:cf:hnqv' OPTION; do
esac
done
cd /srv/yggdrasil/new_acquisition
cd /home/yggdrasil/new_acquisition
echo INFO Unlocking filestore
if [ `whoami` != "root" ]; then yggdrasil-unlock; fi

View File

@@ -1,2 +1,2 @@
#!/bin/bash
find -P /srv/yggdrasil -type d -exec chmod u+w {} \;
find -P /home/yggdrasil -type d -exec chmod g+w {} \;

View File

@@ -1,21 +1,32 @@
---
- name: Yggdrasil packages
become: yes
package:
become: true
ansible.builtin.package:
name:
- emby-server
- perl-image-exiftool
- ffmpeg
- yggdrasil-scripts # Sub dependencies included in the PKGBUILD
- name: Ensure group
ansible.builtin.group:
name: yggdrasil
state: present
- name: Ensure emby user is in group
ansible.builtin.user:
name: emby
append: true
groups: yggdrasil
- name: Yggdrasil directories
become: yes
file:
become: true
ansible.builtin.file:
path: "{{ item }}"
state: directory
owner: http
group: http
mode: 2750
owner: emby
group: yggdrasil
mode: "2550"
loop:
- /home/yggdrasil
- /home/yggdrasil/Digital_Library
@@ -26,14 +37,16 @@
- /home/yggdrasil/Software
- name: LiveTV channels
command: /bin/bash -c "curl -s https://raw.githubusercontent.com/iptv-org/iptv/master/streams/us.m3u | grep -A 1 -E '{{ iptv_location }}' 2>&1 | grep -vE '^--$'"
# noqa: no-changed-when
ansible.builtin.command:
cmd: bash -c "curl -s https://raw.githubusercontent.com/iptv-org/iptv/master/streams/us.m3u | grep -A1 -E '{{ iptv_location }}' 2>&1 | grep -vE '^--$' || true"
register: livetv_channels
- name: Write to file
become: yes
copy:
become: true
ansible.builtin.copy:
content: "{{ livetv_channels.stdout }}"
dest: /var/lib/emby/local-channels.m3u
owner: emby
group: http
mode: 0640
group: yggdrasil
mode: "0640"