Compare commits

...

16 Commits

Author SHA1 Message Date
Alex Tavarez
a1bc0ae727 Created systemd user unit service file for Aria2 2025-11-18 21:47:11 -05:00
Alex Tavarez
4dd524a5f2 Added RSyncD configuration file 2025-11-18 21:45:43 -05:00
Alex Tavarez
5901f69c29 Added handler for installing containers after podman installation 2025-11-18 21:45:14 -05:00
Alex Tavarez
73ef748c95 Added Jinja variables 2025-11-18 21:44:28 -05:00
Alex Tavarez
065e93d7c7 Added configuration fields for Aria2 2025-11-18 21:43:48 -05:00
Alex Tavarez
3f11b7c78d Added handler for RSyncD configuration 2025-11-18 21:38:39 -05:00
Alex Tavarez
64873bb846 Added a handler for Aria2 setting up daemon and configuration 2025-11-18 21:37:40 -05:00
Alex Tavarez
bdc6905491 Added Fail2Ban jails for ProFTPd and SSHD 2025-11-18 21:36:59 -05:00
Alex Tavarez
272c1342c1 Excluded Ansible Galaxy cache data and token file from version control tracking 2025-11-18 21:36:09 -05:00
Alex Tavarez
db18e6ddf6 Commented LDAP and NodeJS packages, uncommented aria and rsync packages, from software list--added container, misc and snap software 2025-11-18 21:34:30 -05:00
Alex Tavarez
ee3cf37d2f Imported new additional tasks 2025-11-18 21:31:56 -05:00
Alex Tavarez
7d2d9081e2 Created set of additional tasks for custom filters for new Fail2Ban ProFTPd jail 2025-11-18 21:30:47 -05:00
Alex Tavarez
870b16582c Added set of tasks configuring Nextcloud after installation 2025-11-18 21:29:25 -05:00
Alex Tavarez
de70d3bdd3 Added task to modify default branch name 2025-11-18 21:28:33 -05:00
Alex Tavarez
72395382d3 Changed order of preferred paths for Ansible 2025-11-18 21:27:01 -05:00
Alex Tavarez
fd5cdca0e9 Excluded collections from version control tracking 2025-11-18 21:25:57 -05:00
16 changed files with 460 additions and 87 deletions

3
.gitignore vendored
View File

@@ -12,5 +12,8 @@ hosts.yml
log.txt
**/update-motd.d/*.sh
**/vhost@vps1-sukaato.moe.conf.j2
collections/
motd
banner
.galaxy_cache/
galaxy_token

View File

@@ -16,7 +16,7 @@
;force_color=False
# (path) The default root path for Ansible config files on the controller.
home=.ansible
home=.
# (boolean) This setting allows suppressing colorizing output, which is used to give a better indication of failure and status information.
;nocolor=False
@@ -38,7 +38,7 @@ become_plugins=plugins/become:.ansible/plugins/become:/usr/share/ansible/plugins
fact_caching=jsonfile
# (string) Defines connection or path information for the cache plugin
fact_caching_connection=.ansible/facts
fact_caching_connection=.facts
# (string) Prefix to use for cache plugin files/tables
;fact_caching_prefix=ansible_facts
@@ -54,7 +54,7 @@ fact_caching_connection=.ansible/facts
# (pathspec) Colon separated paths in which Ansible will search for collections content. Collections must be in nested *subdirectories*, not directly in these directories. For example, if ``COLLECTIONS_PATHS`` includes ``'{{ ANSIBLE_HOME ~ "/collections" }}'``, and you want to add ``my.collection`` to that directory, it must be saved as ``'{{ ANSIBLE_HOME} ~ "/collections/ansible_collections/my/collection" }}'``.
collections_path=.ansible/collections:collections:/usr/share/collections:/etc/ansible/collections
collections_path=collections:.ansible/collections:/usr/share/collections:/etc/ansible/collections
# (boolean) A boolean to enable or disable scanning the sys.path for installed collections
;collections_scan_sys_path=True
@@ -169,7 +169,7 @@ local_tmp=.tmp
;log_filter=
# (path) File to which Ansible will log on the controller. When empty logging is disabled.
log_path=.ansible/log.txt
log_path=log.txt
# (pathspec) Colon separated paths in which Ansible will search for Lookup Plugins.
lookup_plugins=plugins/lookup:.ansible/lookup:/usr/share/ansible/plugins/lookup
@@ -223,7 +223,7 @@ netconf_plugins=plugins/netconf:.ansible/netconf:/usr/share/ansible/plugins/netc
;remote_user=
# (pathspec) Colon separated paths in which Ansible will search for Roles.
roles_path=.ansible/roles:roles:/usr/share/ansible/roles:/etc/ansible/roles
roles_path=roles:.ansible/roles:/usr/share/ansible/roles:/etc/ansible/roles
# (string) Set the main callback used to display Ansible output. You can only have one at a time.
# You can have many other callbacks, but just one can be in charge of stdout.

View File

@@ -0,0 +1,16 @@
# fail2ban filter for the ProFTPD FTP daemon
[INCLUDES]
before = common.conf
[Definition]
_daemon = proftpd
failregex = \(\S+\[<HOST>\]\)[: -]+ USER \S+: no such user found from \S+ \[[0-9.]+\] to \S+:\S+\s*$
\(\S+\[<HOST>\]\)[: -]+ USER \S+ \(Login failed\):.*\s+$
\(\S+\[<HOST>\]\)[: -]+ Maximum login attempts \([0-9]+\) exceeded, connection refused.*\s+$
\(\S+\[<HOST>\]\)[: -]+ SECURITY VIOLATION: \S+ login attempted\.\s+$
\(\S+\[<HOST>\]\)[: -]+ Maximum login attempts \(\d+\) exceeded\s+$
ignoreregex =

View File

@@ -0,0 +1,7 @@
[proftpd]
enabled = true
port = 990
filter = custom_proftpd
logpath = /var/log/proftpd.log
maxretry = 6

View File

@@ -0,0 +1,35 @@
[sshd]
# ==========================
# SSH Jail Configuration
# ==========================
# Enable the SSH jail to monitor and protect against brute-force attacks.
enabled = true
# Port Fail2Ban should monitor for SSH connections.
# If you run SSH on a custom port, replace 'ssh' with the actual port number (e.g., 2222).
port = ssh
# Filter definition to use.
# 'sshd' refers to the default filter that matches common SSH authentication failures.
filter = sshd
# Log file location.
# '%(sshd_log)s' uses the default value set by the system, typically /var/log/auth.log or journalctl.
logpath = %(sshd_log)s
# Backend for reading logs.
# 'systemd' is recommended if your system uses journalctl for logging.
backend = systemd
# ==========================
# SSH-Specific Overrides
# ==========================
# Time window to evaluate failed login attempts.
# If 'maxretry' failures occur within this time, the IP will be banned.
findtime = 5m
# Number of failed attempts allowed before triggering a ban.
maxretry = 4

View File

@@ -0,0 +1,49 @@
# SPDX-License-Identifier: MIT-0
---
# handlers file for bootstrap
- name: Configure Aria2
listen: aria
when: ansible_facts['user_id'] in hostvars[inventory_hostname].users.keys()
block:
- name: Create Aria2 user configuration directory
block:
- name: Create configuration directory
ansible.builtin.file:
force: false
group: "{{ hostvars[inventory_hostname].users[ansible_facts['user_id']].group | default(ansible_facts['user_id']) }}"
owner: "{{ ansible_facts['user_id'] }}"
path: "{{ ansible_facts['user_dir'] }}/.config"
state: directory
- name: Create configuration directory
when: ansible_facts['user_id'] in hostvars[inventory_hostname].users.keys()
ansible.builtin.file:
force: false
group: "{{ hostvars[inventory_hostname].users[ansible_facts['user_id']].group | default(ansible_facts['user_id']) }}"
owner: "{{ ansible_facts['user_id'] }}"
path: "{{ ansible_facts['user_dir'] }}/.config/aria2"
state: directory
- name: Create Aria2 configuration
ansible.builtin.template:
backup: true
dest: "{{ ansible_facts['user_dir'] }}/.config/aria2/aria2.conf"
force: true
group: "{{ hostvars[inventory_hostname].users[ansible_facts['user_id']].group | default(ansible_facts['user_id']) }}"
owner: "{{ ansible_facts['user_id'] }}"
src: aria2/aria2.conf.j2
# validate: string
- name: Create Aria2 SystemD user unit service
ansible.builtin.copy:
backup: true
dest: "{{ ansible_facts['user_dir'] }}/.config/systemd/user/aria2cd.service"
force: true
group: "{{ hostvars[inventory_hostname].users[ansible_facts['user_id']].group | default(ansible_facts['user_id']) }}"
owner: "{{ ansible_facts['user_id'] }}"
src: systemd/user/aria2cd.service.j2
# validate: string
- name: Start Aria2 SystemD user unit service
ansible.builtin.systemd_service:
daemon_reload: true
enabled: true
name: aria2cd
scope: user
state: started

View File

@@ -304,3 +304,11 @@
scope: global
state: present
value: "{{ hostvars[inventory_hostname].users[ansible_facts['user_id']].git_profile.email }}"
- name: Set default initial branch name
become: true
community.general.git_config:
add_mode: replace-all
name: init.defaultBranch
scope: system
state: present
value: main

View File

@@ -1,9 +1,20 @@
# SPDX-License-Identifier: MIT-0
---
# handlers file for bootstrap
# @NOTE below for packages
- name: Postinstall set-up of git
ansible.builtin.import_tasks:
file: git.yml
- name: Postinstall set-up of ProFTPd
ansible.builtin.import_tasks:
file: proftpd.yml
- name: Postinstall set-up of ProFTPd
ansible.builtin.import_tasks:
file: proftpd.yml
# @NOTE below for snaps
- name: Postinstall set-up of snapd
ansible.builtin.import_tasks:
file: snapd.yml
- name: Postinstall set-up of Nextcloud snap
ansible.builtin.import_tasks:
file: nextcloud.yml

View File

@@ -8,19 +8,30 @@
- name: Enable monitoring of network hardware
ansible.builtin.command:
cmd: "snap connect nextcloud:network-observe"
- name: Enable access to removable media
- name: Begin manual installation
ansible.builtin.command:
cmd: "snap connect nextcloud:removable-media"
argv:
- /snap/bin/nextcloud.manual-install
- "{{ config.nextcloud.users.admin.username }}"
- "{{ config.nextcloud.users.admin.password }}"
# @TODO see if setting below is necessary given use of reverse proxy
# - name: Set trusted domains
# ansible.builtin.command:
# cmd: "nextcloud.occ config:system:set trusted_domains 0 --value='cloud.{{ hostvars[inventory_hostname].fqdn }}'"
- name: Set trusted domains
block:
- name: Set localhost as trusted domain
ansible.builtin.command:
cmd: "/snap/bin//snap/bin/nextcloud.occ config:system:set trusted_domains 0 --value='localhost'"
# @TODO see if setting below is necessary given use of reverse proxy
- name: Set FQDN as trusted domain
ansible.builtin.command:
cmd: "/snap/bin//snap/bin/nextcloud.occ config:system:set trusted_domains 1 --value='cloud.{{ hostvars[inventory_hostname].fqdn }}'"
# @TODO configure perhaps for trusted (reverse) proxy instead of above
- name: Set trusted reverse proxy IPv4 address
- name: Set trusted reverse proxy addresses
block:
- name: Set trusted reverse proxy IPv4 address based on hostname
when: config.trusted_revproxy_ips.ipv4 is None or len(config.trusted_revproxy_ips.ipv4) < 1
ansible.builtin.command:
argv:
- nextcloud.occ
- /snap/bin/nextcloud.occ
- "config:system:set"
- trusted_proxies 0
- "--value=$(hostname -I | awk -F ' ' '{ print $1 }')"
@@ -28,37 +39,30 @@
when: config.trusted_revproxy_ips.ipv4 is not None and len(config.trusted_revproxy_ips.ipv4) > 0
ansible.builtin.command:
argv:
- nextcloud.occ
- /snap/bin/nextcloud.occ
- "config:system:set"
- "trusted_proxies {{ idx }}"
- "--value={{ item }}"
loop: "{{ config.trusted_revproxy_ips.ipv4 }}"
loop_control:
index_var: idx
- name: Set trusted reverse proxy IPv6 address
- name: Set trusted reverse proxy IPv6 address based on hostname
when: config.trusted_revproxy_ips.ipv6 is None or len(config.trusted_revproxy_ips.ipv6) < 1
ansible.builtin.command:
argv:
- nextcloud.occ
- /snap/bin/nextcloud.occ
- "config:system:set"
- trusted_proxies 0
- "--value=$(hostname -I | awk -F ' ' '{ print $2 }')"
- trusted_proxies 1
- --value=$(hostname -I | awk -F ' ' '{ print $2 }')
- name: Set trusted reverse proxy IPv6 address
when: config.trusted_revproxy_ips.ipv6 is not None and len(config.trusted_revproxy_ips.ipv6) > 0
ansible.builtin.command:
argv:
- nextcloud.occ
- /snap/bin/nextcloud.occ
- "config:system:set"
- "trusted_proxies {{ idx }}"
- "--value={{ item }}"
loop: "{{ config.trusted_revproxy_ips.ipv6 }}"
loop_control:
index_var: idx
- name: Enable LDAP integration app
ansible.builtin.command:
cmd: "nextcloud.occ app:enable user_ldap"
# @TODO see if can further configure LDAP in particular: https://docs.nextcloud.com/server/stable/admin_manual/occ_command.html#ldap-commands
- name: Enable contacts' birthday calendar app
ansible.builtin.command:
cmd: "nextcloud.occ dav:sync-birthday-calendar"
# @TODO create system-level bash alias for `nextcloud.occ` command
# @TODO create system-level bash alias for `/snap/bin/nextcloud.occ` command

View File

@@ -0,0 +1,13 @@
# SPDX-License-Identifier: MIT-0
---
# handlers file for bootstrap
- name: Pull podman images
listen: rsync
block:
- name: Pull container images via podman
containers.podman.podman_image:
name: "{{ item.value['name'] }}"
tag: "{{ item.value['tag'] | default('latest') }}"
state: present
notify: "{{ item.key }}"
loop: "{{ lookup('ansible.builtin.dict', software.containers) }}"

View File

@@ -111,3 +111,47 @@
allowed_users: "{{ ','.join(list(map(lambda u: u['username'], filter(lambda u: not 'http' in u['services'] and not 'https' in u['services'] and not 'httpd' in u['services'] and not 'caddy' in u['services'] and not 'www-data' in u['services'], config['proftpd']['vusers'].values())))) }}"
anon_root: "{{ map(lambda u: u['home'], filter(lambda u: 'ftps' in u['services'] or 'proftpd' in u['services'], hostvars[inventory_hostname]['users'].values())) | list | random }}/public"
anon_user: "{{ config['proftpd']['vusers']['smuggler']['username'] }}"
- name: Set ProFTPd jail in fail2ban
block:
- name: Create fail2ban system configuration directory
ansible.builtin.file:
force: false
group: root
mode: "0755"
owner: root
path: /etc/fail2ban
state: directory
- name: Create fail2ban filters system configuration directory
ansible.builtin.file:
force: false
group: root
mode: "0755"
owner: root
path: /etc/fail2ban/filter.d
state: directory
- name: Create fail2ban filter system configuration
ansible.builtin.copy:
backup: true
dest: /etc/fail2ban/filter.d/custom_proftpd.conf
force: true
group: root
owner: root
src: fail2ban/filter.d/custom_proftpd.conf
# validate: string
- name: Create fail2ban jails system configuration directory
ansible.builtin.file:
force: false
group: root
mode: "0755"
owner: root
path: /etc/fail2ban/jail.d
state: directory
- name: Create fail2ban jail system configuration
ansible.builtin.copy:
backup: true
dest: /etc/fail2ban/jail.d/proftpd.local
force: true
group: root
owner: root
src: fail2ban/jail.d/proftpd.local
# validate: string

View File

@@ -0,0 +1,24 @@
# SPDX-License-Identifier: MIT-0
---
# handlers file for bootstrap
- name: Configure RSyncD
listen: rsync
become: true
block:
# @TODO further construct the following commented task
# - name: Add directories to be published by RSyncD
- name: Create RSyncD configuration
ansible.builtin.template:
backup: true
dest: /etc/rsyncd.conf
force: true
group: root
owner: root
src: rsyncd.conf.j2
# validate: string
- name: Start and enable RSyncD SystemD system unit service
ansible.builtin.systemd_service:
enabled: true
name: rsync
scope: system
state: started

View File

@@ -0,0 +1,83 @@
# Global settings
continue=true
# check-integrity=true
daemon=true
human-readable=true
dir=~/downloads
file-allocation=falloc
log-level=warn
max-concurrent-downloads=3
max-overall-download-limit=0
# RPC settings
enable-rpc=true
rpc-allow-origin-all=true
rpc-max-request-size=10M
rpc-listen-all=true
rpc-listen-port=6800
rpc-secret={{ config.aria.secret }}
# rpc-certificate=
# rpc-private-key=
# rpc-secure=true
# HTTP/FTP/SFTP settings
connect-timeout=120
timeout=90
server-stat-of=~/.config/aria2/dl.log
server-stat-if=~/.config/aria2/dl.log
server-stat-timeout=86400
# checksum=sha-256={{ config.aria.checksum }}
max-connection-per-server=5
max-tries=10
max-file-not-found=7
min-split-size=100M
split=7
retry-wait=10
netrc-path=~/.netrc
reuse-uri=true
uri-selector=feedback
seed-ratio=1.5
seed-time=75
# HTTP settings
http-accept-gzip=true
http-auth-challenge=true
http-no-cache=true
enable-http-pipelining=true
enable-http-keep-alive=true
save-cookies=~/.config/aria2/cookie.txt
load-cookies=~/.config/aria2/cookie.txt
# user-agent=Mozilla/5.0
# FTP/SFTP settings
ftp-pasv=true
ftp-type=binary
ftp-reuse-connection=true
# ssh-host-key-md=sha-256=
# Bittorrent settings
listen-port=6881-6999
# bt-hash-check-seed=true
# bt-force-encryption=true
bt-save-metadata=true
bt-load-saved-metadata=true
bt-max-open-files=50
bt-max-peers=150
bt-stop-timeout=7200
bt-tracker=udp://93.158.213.92:1337/announce,udp://23.134.88.9:6969/announce,udp://23.134.88.9:1337/announce,udp://185.243.218.213:80/announce,udp://89.234.156.205:451/announce,udp://44.30.4.4:6969/announce,udp://23.175.184.30:23333/announce,udp://51.222.82.36:6969/announce,udp://211.75.205.189:80/announce,udp://77.91.85.95:6969/announce,udp://45.13.119.213:6969/announce,udp://43.154.112.29:17272/announce,udp://209.141.59.25:6969/announce,udp://5.255.124.190:6969/announce,udp://152.53.152.105:1984/announce,udp://109.201.134.183:80/announce,udp://111.90.151.241:6969/announce,udp://152.53.152.105:54123/announce,udp://189.69.171.209:6969/announce,udp://151.243.109.110:6969/announce
bt-tracker-connect-timeout=120
bt-tracker-timeout=333
bt-tracker-interval=0
enable-dht=true
dht-listen-port=6881-6999
dht-message-timeout=15
enable-peer-exchange=true
follow-torrent=mem
# Metalink settings
follow-metalink=mem
metalink-language=en,es,ja
metalink-location=jp,us,ch
# metalink-os=linux

View File

@@ -0,0 +1,41 @@
port = 873
use chroot = true
max connections = 17
ignore nonreadable = true
pid file = /var/run/rsyncd.pid
[{{ ansible_facts['user_id'] }}-dl]
path = {{ ansible_facts['user_dir'] }}/downloads/public
uid = rika
gid = rika
timeout = 90
comment = Personal download inventory
read only = true
exclude = .nextcloudsync.log .calnotes .caltrash .stfolder .stignore .directory .ssh *.pub
[{{ ansible_facts['user_id'] }}-public]
path = {{ ansible_facts['user_dir'] }}/public/rsync
uid = rika
gid = rika
timeout = 90
comment = Public share point
read only = true
exclude = .nextcloudsync.log .calnotes .caltrash .stfolder .stignore .directory .ssh *.pub
[{{ ansible_facts['user_id'] }}-soulseek]
path = {{ ansible_facts['user_dir'] }}/public/soulseek
uid = rika
gid = rika
timeout = 90
comment = Personal SoulSeek inventory
read only = true
exclude = .nextcloudsync.log .calnotes .caltrash .stfolder .stignore .directory .ssh *.pub
[{{ ansible_facts['user_id'] }}-portfolio]
path = {{ ansible_facts['user_dir'] }}/portfolio
uid = rika
gid = rika
timeout = 90
comment = Personal portfolio
read only = true
exclude = .nextcloudsync.log .calnotes .caltrash .stfolder .stignore .directory .ssh *.pub

View File

@@ -0,0 +1,13 @@
[Unit]
Description=aria2 Daemon
After=network.target
[Service]
Type=forking
ExecStart=/usr/bin/aria2c --conf-path={{ ansible_facts['user_dir'] }}/.config/aria2/aria2.conf
ExecReload=/usr/bin/kill -HUP $MAINPID
RestartSec=1min
Restart=on-failure
[Install]
WantedBy=default.target

View File

@@ -5,6 +5,9 @@
software:
pkgs:
# @NOTE keep fields or keys constant; otherwise will have to edit handler notifiers and listeners elsewhere
failtwoban:
name:
apt: fail2ban
gocryptfs:
name:
apt: gocryptfs
@@ -80,18 +83,19 @@ software:
crystal-docs:
name:
apt: crystal-doc
javascript-lang:
name:
apt: nodejs
# @TODO replace below commented with an NVM-style installation (v22): https://nodejs.org/en/download
# javascript-lang:
# name:
# apt: nodejs
# javascript-pkg:
# name:
# apt: npm
# javascript-linter:
# name:
# apt: eslint
javascript-docs:
name:
apt: nodejs-doc
javascript-pkg:
name:
apt: npm
javascript-linter:
name:
apt: eslint
php-lang:
name:
apt: php
@@ -104,9 +108,9 @@ software:
php-pkg:
name:
apt: composer
php-ldap:
name:
apt: php-ldap
# php-ldap:
# name:
# apt: php-ldap
html-linter:
name:
apt: tidy
@@ -180,18 +184,18 @@ software:
# dpkg-dev:
# name:
# apt: dpkg-dev
ldap-utils:
name:
apt: ldap-utils
slapd:
name:
apt: slapd
# ldap-utils:
# name:
# apt: ldap-utils
# slapd:
# name:
# apt: slapd
proftpd-mod-crypto:
name:
apt: proftpd-mod-crypto
proftpd-mod-ldap:
name:
apt: proftpd-mod-ldap
# proftpd-mod-ldap:
# name:
# apt: proftpd-mod-ldap
# @TODO manually install the commented below on current active new VPS, then uncomment
# proftpd-mod-clamav:
# name:
@@ -202,15 +206,15 @@ software:
proftpd-docs:
name:
apt: proftpd-doc
# rsync:
# name:
# apt: rsync
rsync:
name:
apt: rsync
# rclone:
# name:
# apt: rsync
# aria:
# name:
# apt: aria2
aria:
name:
apt: aria2
# mopidy:
# name:
# apt: mopidy
@@ -228,11 +232,20 @@ software:
- "nextcloud:php.memory-limit=512M"
- "nextcloud:nextcloud.cron-interval=10m"
- "nextcloud:http.compression=true"
# @TODO commented opts use 'connect' snapd subcommand--look into how to use in Ansible
# - "nextcloud:removable-media"
# - "nextcloud:network-observe"
- "nextcloud:ports.http=81"
# @TODO see how to set these options: https://help.nextcloud.com/t/how-to-configure-nextcloud-snap/216036#p-649442-trusted-domains-configuration-8
# @TODO see how to set these options: https://help.nextcloud.com/t/how-to-configure-nextcloud-snap/216036#p-649442-trusted-proxy-configuration-9
containers:
ariang:
name: https://docker.io/p3terx/ariang
tag: latest
links:
quartz:
name: quartz
src: https://github.com/jackyzha0/quartz.git
branch: v4
version: ~
output: ~
config:
git:
sys:
@@ -274,4 +287,13 @@ config:
tls_paths:
cert: "/usr/local/share/ca-certificates/{{ hostvars[inventory_hostname].fqdn }}.crt"
privkey: "/usr/local/share/ca-certificates/{{ hostvars[inventory_hostname].fqdn }}.key"
nextcloud:
users:
admin:
username: admin
# @TODO change this password to ansible-vaulted actual choice password later
password: password123 # @NOTE placeholder
aria:
checksum: ~
secret: ~