SHA256
1
0

Compare commits

...

4 Commits

Author SHA256 Message Date
d868ab2c3c Refactor dotfiles role 2026-01-27 01:59:47 -05:00
77ad977cd3 filesystems: add new downloads device 2026-01-27 01:59:15 -05:00
23190684ea Add more dotfiles and templates 2026-01-27 01:56:55 -05:00
0cb596f4db Update playbook infra 2026-01-27 01:55:54 -05:00
17 changed files with 944 additions and 121 deletions

1
.gitignore vendored
View File

@@ -1,2 +1,3 @@
.ansible .ansible
testing/ testing/
vault.yml

View File

@@ -1,2 +1,3 @@
[defaults] [defaults]
inventory = inventories/hosts.ini inventory = inventories/hosts.ini
collections_paths = ./collections

View File

@@ -2,6 +2,7 @@
# Bootstrap Ansible environment # Bootstrap Ansible environment
# Usage: ./bootstrap [--force] # Usage: ./bootstrap [--force]
pip install --upgrade pip "$@" python -m ensurepip --upgrade
pip install --upgrade --requirement pip-requirements "$@" pip install --upgrade pip
ansible-galaxy install --role-file galaxy-requirements.yml "$@" pip install --upgrade --requirement requirements "$@"
ansible-galaxy install --role-file collections/requirements.yml "$@"

View File

@@ -2,4 +2,4 @@
# ansible-playbook playbook.yml -l testing-remote --ask-vault-pass --ask-become-pass --check --diff # ansible-playbook playbook.yml -l testing-remote --ask-vault-pass --ask-become-pass --check --diff
ansible-playbook playbook.yml -l testing-remote --ask-vault-pass --ask-become-pass --diff "$@" ansible-playbook playbook.yml -l workstation-remote-testing --ask-vault-pass --ask-become-pass --diff "$@"

View File

@@ -5,7 +5,7 @@
} }
], ],
"settings": { "settings": {
"ansible.python.interpreterPath": "/home/bryan/.virtualenvs/deploy/bin/python", "ansible.python.interpreterPath": "/home/bryan/develop/deploy/.venv/bin/python",
"search.followSymlinks": false, "search.followSymlinks": false,
}, },

View File

@@ -18,8 +18,8 @@ Host home-router
Hostname home-router Hostname home-router
User root User root
Host ax6000 Host w1700k
Hostname ax6000.lan Hostname w1700k.lan
User root User root
Host bryanroessler.com Host bryanroessler.com
@@ -35,8 +35,8 @@ Host workstation
Host laptop Host laptop
Hostname laptop Hostname laptop
Host vm-fedora42 Host vm-fedora43
Hostname vm-fedora42 Hostname 192.168.122.169
Host vm-alma9 Host vm-alma9
Hostname 192.168.122.235 Hostname 192.168.122.235

View File

@@ -0,0 +1,129 @@
[GENERAL]
homepage = eBooks
auth_type = FORM
displaylength = -1
series_tab = False
config_tab_num = 2
toggles = False
launch_browser = False
imp_preflang = en, en-GB, en-US, eng, English, Unknown
date_lang = en_GB.UTF-8
destination_copy = True
ebook_dir = {{ lazylibrarian_ebook_dir | default('/ebooks') }}
download_dir = {{ lazylibrarian_download_dir | default('/downloads/complete/lazylibrarian') }}
ebook_type = epub, mobi, pdf, azw3
audiobook_type = mp3, m4b, opus, ogg
[API]
api_enabled = True
api_key = {{ lazylibrarian_api_key }}
api_ro_key = {{ lazylibrarian_api_ro_key }}
book_api = GoodReads
ol_api = True
gb_api = {{ lazylibrarian_gb_api | default('') }}
gb_country = US
[WEBSERVER]
http_user = {{ lazylibrarian_http_user | default('lazylibrarianuser') }}
http_pass = {{ lazylibrarian_http_pass }}
[LOGGING]
logdir = {{ lazylibrarian_logdir | default('/config/Logs') }}
detaileduilog = True
[IMPORTER]
multi_source = True
[TELEMETRY]
server_id = {{ lazylibrarian_server_id | default('') }}
[SABNZBD]
sab_host = {{ lazylibrarian_sab_host | default('localhost') }}
sab_port = {{ lazylibrarian_sab_port | default(8082) }}
sab_user = {{ sabnzbd_username | default('sabnzbduser') }}
sab_pass = {{ sabnzbd_password }}
sab_api = {{ sabnzbd_api_key }}
sab_cat = {{ lazylibrarian_sab_cat | default('lazylibrarian') }}
[USENET]
nzb_downloader_sabnzbd = True
[TORRENT]
tor_downloader_qbittorrent = True
seed_wait = False
[QBITTORRENT]
qbittorrent_host = {{ lazylibrarian_qbit_host | default('localhost') }}
qbittorrent_port = {{ lazylibrarian_qbit_port | default(8082) }}
qbittorrent_user = {{ qbittorrent_username | default('qbittorrentuser') }}
qbittorrent_pass = {{ qbittorrent_password }}
qbittorrent_label = {{ lazylibrarian_qbit_label | default('lazylibrarian') }}
[ANNA]
anna_key = {{ lazylibrarian_anna_key }}
anna = True
[POSTPROCESS]
ebook_dest_folder = $Author/$Title $$
audiobook_dest_folder = $Author/$Title
del_downloadfailed = True
[MAGAZINES]
mag_tab = False
[PROWL]
prowl_priority = -2
[PREPROCESS]
ebook_wanted_formats = azw3, mobi, epub
{% for indexer in lazylibrarian_newznab_indexers | default([]) %}
[Newznab_{{ loop.index0 }}]
dispname = {{ indexer.name }}
enabled = {{ indexer.enabled | default(True) | string }}
host = {{ indexer.host }}
api = {{ indexer.api }}
generalsearch = search
bookcat = {{ indexer.bookcat | default('7020') }}
{% if indexer.magcat is defined %}
magcat = {{ indexer.magcat }}
{% endif %}
{% if indexer.comiccat is defined %}
comiccat = {{ indexer.comiccat }}
{% endif %}
updated = {{ indexer.updated | default('2026-01-27') }}
dlpriority = {{ indexer.dlpriority | default(26) }}
{% endfor %}
{% for indexer in lazylibrarian_torznab_indexers | default([]) %}
[Torznab_{{ loop.index0 }}]
dispname = {{ indexer.name }}
enabled = {{ indexer.enabled | default(True) | string }}
host = {{ indexer.host }}
api = {{ indexer.api }}
generalsearch = search
{% if indexer.bookcat is defined %}
bookcat = {{ indexer.bookcat }}
{% endif %}
{% if indexer.magcat is defined %}
magcat = {{ indexer.magcat }}
{% endif %}
{% if indexer.comiccat is defined %}
comiccat = {{ indexer.comiccat }}
{% endif %}
updated = {{ indexer.updated | default('2026-01-27') }}
dlpriority = {{ indexer.dlpriority | default(26) }}
seeders = {{ indexer.seeders | default(1) }}
{% if indexer.seed_ratio is defined %}
seed_ratio = {{ indexer.seed_ratio }}
{% endif %}
{% endfor %}
{% for indexer in lazylibrarian_generic_indexers | default([]) %}
[GEN_{{ loop.index0 }}]
dispname = {{ indexer.name }}
enabled = {{ indexer.enabled | default(True) | string }}
host = {{ indexer.host }}
search = {{ indexer.search }}
{% endfor %}

View File

@@ -0,0 +1,127 @@
[Application]
FileLogger\Age=1
FileLogger\AgeType=1
FileLogger\Backup=true
FileLogger\DeleteOld=true
FileLogger\Enabled=false
FileLogger\MaxSizeBytes=66560
FileLogger\Path=/config/qBittorrent/data/logs
MemoryWorkingSetLimit=2048
[AutoRun]
OnTorrentAdded\Enabled=false
OnTorrentAdded\Program=
enabled=false
program=
[BitTorrent]
MergeTrackersEnabled={{ qbittorrent_merge_trackers | default(false) | lower }}
Session\AddExtensionToIncompleteFiles=true
Session\AddTorrentStopped=false
Session\AddTrackersEnabled={{ qbittorrent_add_trackers | default(false) | lower }}
Session\AdditionalTrackers={{ qbittorrent_additional_trackers | default('') }}
Session\AlternativeGlobalDLSpeedLimit={{ qbittorrent_alt_dl_limit | default(0) }}
Session\AlternativeGlobalUPSpeedLimit={{ qbittorrent_alt_up_limit | default(0) }}
Session\AnonymousModeEnabled={{ qbittorrent_anonymous_mode | default(true) | lower }}
Session\DefaultSavePath={{ qbittorrent_complete_dir | default('/downloads/complete') }}
Session\DisableAutoTMMByDefault=false
Session\DisableAutoTMMTriggers\CategorySavePathChanged=false
Session\DisableAutoTMMTriggers\DefaultSavePathChanged=false
Session\ExcludedFileNames=
Session\GlobalDLSpeedLimit={{ qbittorrent_dl_limit | default(0) }}
Session\GlobalMaxRatio={{ qbittorrent_max_ratio | default(1) }}
Session\GlobalMaxSeedingMinutes={{ qbittorrent_max_seed_minutes | default(0) }}
Session\GlobalUPSpeedLimit={{ qbittorrent_ul_limit | default(300) }}
Session\IgnoreLimitsOnLAN=true
Session\IgnoreSlowTorrentsForQueueing=true
Session\MaxActiveDownloads={{ qbittorrent_max_active_downloads | default(0) }}
Session\MaxActiveTorrents={{ qbittorrent_max_active_torrents | default(0) }}
Session\Port={{ qbittorrent_session_port | default(48442) }}
Session\QueueingSystemEnabled={{ qbittorrent_queueing_enabled | default(false) | lower }}
Session\SSL\Port={{ qbittorrent_ssl_port | default('11192') }}
Session\ShareLimitAction={{ qbittorrent_share_limit_action | default('Stop') }}
Session\TempPath={{ qbittorrent_temp_dir | default('/downloads/incomplete/qbittorrent') }}
Session\TempPathEnabled=true
Session\UseAlternativeGlobalSpeedLimit=true
[Core]
AutoDeleteAddedTorrentFile=IfAdded
[LegalNotice]
Accepted=true
[Meta]
MigrationVersion=8
[Network]
Cookies=@Invalid()
Proxy\HostnameLookupEnabled=false
Proxy\Profiles\BitTorrent=true
Proxy\Profiles\Misc=true
Proxy\Profiles\RSS=true
[Preferences]
Advanced\AnonymousMode={{ qbittorrent_anonymous_mode | default(true) | lower }}
Advanced\RecheckOnCompletion={{ qbittorrent_recheck_on_completion | default(false) | lower }}
Advanced\trackerPort={{ qbittorrent_tracker_port | default(9000) }}
Advanced\trackerPortForwarding=false
Bittorrent\MaxRatio={{ qbittorrent_max_ratio | default(1) }}
Connection\GlobalDLLimitAlt={{ qbittorrent_global_dl_limit_alt | default(0) }}
Connection\GlobalUPLimitAlt={{ qbittorrent_global_up_limit_alt | default(0) }}
Connection\PortRangeMin={{ qbittorrent_port_range_min | default(48442) }}
Connection\ResolvePeerCountries=true
Downloads\SavePath={{ qbittorrent_complete_dir | default('/downloads/complete') }}
Downloads\ScanDirsLastPath={{ qbittorrent_scan_dir | default('/torrents') }}
Downloads\ScanDirsV2=@Variant(\0\0\0\x1c\0\0\0\0)
Downloads\TempPath={{ qbittorrent_temp_dir | default('/downloads/incomplete/qbittorrent') }}
Downloads\TempPathEnabled=true
Downloads\UseIncompleteExtension=true
DynDNS\DomainName=changeme.dyndns.org
DynDNS\Enabled=false
DynDNS\Password=
DynDNS\Service=DynDNS
DynDNS\Username=
General\Locale={{ qbittorrent_locale | default('en') }}
MailNotification\email=
MailNotification\enabled=false
MailNotification\password=
MailNotification\req_auth=true
MailNotification\req_ssl=false
MailNotification\sender=qBittorrent_notification@example.com
MailNotification\smtp_server=smtp.changeme.com
MailNotification\username=
Queueing\IgnoreSlowTorrents=true
Queueing\MaxActiveDownloads={{ qbittorrent_max_active_downloads | default(20) }}
Queueing\MaxActiveTorrents={{ qbittorrent_max_active_torrents | default(20) }}
Queueing\QueueingEnabled=true
WebUI\Address={{ qbittorrent_host | default('') }}
WebUI\AlternativeUIEnabled=false
WebUI\AuthSubnetWhitelist={{ qbittorrent_subnet_whitelist | default('') }}
WebUI\AuthSubnetWhitelistEnabled=true
WebUI\BanDuration=3600
WebUI\CSRFProtection=true
WebUI\ClickjackingProtection=true
WebUI\CustomHTTPHeaders=
WebUI\CustomHTTPHeadersEnabled=false
WebUI\Enabled=true
WebUI\HTTPS\CertificatePath={{ qbittorrent_https_cert | default('/config/qBittorrent/config/ssl/server.crt') }}
WebUI\HTTPS\Enabled={{ qbittorrent_enable_https | default(false) | lower }}
WebUI\HTTPS\KeyPath={{ qbittorrent_https_key | default('/config/qBittorrent/config/ssl/server.key') }}
WebUI\HostHeaderValidation=false
WebUI\LocalHostAuth=false
WebUI\MaxAuthenticationFailCount=5
WebUI\Password_PBKDF2="{{ qbittorrent_password_pbkdf2 | default('') }}"
WebUI\Password_ha1={{ qbittorrent_password_ha1 | default('') }}
WebUI\Port={{ qbittorrent_ui_port | default(8082) }}
WebUI\ReverseProxySupportEnabled=false
WebUI\RootFolder=
WebUI\SecureCookie=true
WebUI\ServerDomains={{ qbittorrent_server_domains | default('*') }}
WebUI\SessionTimeout=3600
WebUI\TrustedReverseProxiesList=
WebUI\UseUPnP=true
WebUI\Username={{ qbittorrent_username | default('qbittorrentuser') }}
[RSS]
AutoDownloader\DownloadRepacks={{ qbittorrent_download_repacks | default(true) | lower }}
AutoDownloader\SmartEpisodeFilter=s(\\d+)e(\\d+), (\\d+)x(\\d+), "(\\d{4}[.\\-]\\d{1,2}[.\\-]\\d{1,2})", "(\\d{1,2}[.\\-]\\d{1,2}[.\\-]\\d{4})"

View File

@@ -0,0 +1,477 @@
__version__ = 19
__encoding__ = utf-8
[misc]
username = {{ sabnzbd_username | default("admin") }}
password = {{ sabnzbd_password | default("admin") }}
host = {{ sabnzbd_host | default("::") }}
port = {{ sabnzbd_http_port | default("8081") }}
api_key = {{ sabnzbd_api_key }}
nzb_key = {{ sabnzbd_nzb_key }}
download_dir = {{ sabnzbd_download_dir | default("/downloads/incomplete/sabnzbd") }}
complete_dir = {{ sabnzbd_complete_dir | default("/downloads/complete") }}
dirscan_dir = {{ sabnzbd_dirscan_dir | default("/nzbs") }}
web_dir = Glitter
web_color = Night
inet_exposure = 4
cleanup_list = sfv, m3u, nfo
unwanted_extensions = exe, com
ignore_samples = 1
enable_all_par = 1
new_nzb_on_failure = 1
replace_dots = 1
prospective_par_download = 1
deobfuscate_final_filenames = 1
direct_unpack = 1
pause_on_pwrar = 2
propagation_delay = 0
top_only = 1
pre_script = None
queue_complete = ""
queue_complete_pers = 0
bandwidth_perc = 100
refresh_rate = 1
interface_settings = '{"dateFormat":"fromNow","extraQueueColumns":["category","age"],"extraHistoryColumns":["size"],"displayCompact":false,"displayFullWidth":false,"confirmDeleteQueue":true,"confirmDeleteHistory":true,"keyboardShortcuts":true}'
queue_limit = 30
config_lock = 0
sched_converted = 0
notified_new_skin = 2
direct_unpack_tested = 1
check_new_rel = 1
auto_browser = 0
language = en
enable_https_verification = 1
https_port = {{ sabnzbd_https_port | default("9090") }}
bandwidth_max = 60M
cache_limit = 1G
https_cert = {{ sabnzbd_https_cert | default("/config/admin/server.cert") }}
https_key = {{ sabnzbd_https_key | default("/config/admin/server.key") }}
https_chain = ""
enable_https = {{ sabnzbd_enable_https | default(false) | int }}
permissions = ""
download_free = ""
complete_free = ""
fulldisk_autoresume = 0
script_dir = ""
nzb_backup_dir = ""
admin_dir = admin
dirscan_speed = 5
password_file = ""
log_dir = logs
max_art_tries = 3
load_balancing = 2
sfv_check = 1
quick_check_ext_ignore = nfo, sfv, srr
script_can_fail = 0
enable_recursive = 1
flat_unpack = 0
par_option = ""
pre_check = 0
nice = ""
win_process_prio = 3
ionice = ""
fail_hopeless_jobs = 1
fast_fail = 1
auto_disconnect = 1
no_dupes = 0
no_series_dupes = 0
series_propercheck = 1
auto_sort = ""
direct_unpack_threads = 3
folder_rename = 1
replace_spaces = 0
safe_postproc = 1
pause_on_post_processing = 0
sanitize_safe = 0
action_on_unwanted_extensions = 0
unwanted_extensions_mode = 0
history_retention = ""
enable_meta = 1
quota_size = ""
quota_day = ""
quota_resume = 0
quota_period = m
rating_enable = 0
rating_host = ""
rating_api_key = ""
rating_filter_enable = 0
rating_filter_abort_audio = 0
rating_filter_abort_video = 0
rating_filter_abort_encrypted = 0
rating_filter_abort_encrypted_confirm = 0
rating_filter_abort_spam = 0
rating_filter_abort_spam_confirm = 0
rating_filter_abort_downvoted = 0
rating_filter_abort_keywords = ""
rating_filter_pause_audio = 0
rating_filter_pause_video = 0
rating_filter_pause_encrypted = 0
rating_filter_pause_encrypted_confirm = 0
rating_filter_pause_spam = 0
rating_filter_pause_spam_confirm = 0
rating_filter_pause_downvoted = 0
rating_filter_pause_keywords = ""
enable_tv_sorting = 0
tv_sort_string = ""
tv_categories = tv,
enable_movie_sorting = 0
movie_sort_string = ""
movie_sort_extra = -cd%1
movie_extra_folder = 0
movie_categories = movies,
enable_date_sorting = 0
date_sort_string = ""
date_categories = tv,
schedlines = ,
rss_rate = 60
ampm = 0
replace_illegal = 1
start_paused = 0
preserve_paused_state = 0
enable_par_cleanup = 1
process_unpacked_par2 = 1
enable_unrar = 1
enable_unzip = 1
enable_7zip = 1
enable_filejoin = 1
enable_tsjoin = 1
overwrite_files = 0
ignore_unrar_dates = 0
backup_for_duplicates = 1
empty_postproc = 0
wait_for_dfolder = 0
rss_filenames = 0
api_logging = 1
html_login = 1
osx_menu = 1
osx_speed = 1
warn_dupl_jobs = 1
helpful_warnings = 1
keep_awake = 1
win_menu = 1
allow_incomplete_nzb = 0
enable_broadcast = 1
ipv6_hosting = 0
fixed_ports = 1
api_warnings = 1
disable_api_key = 0
no_penalties = 0
x_frame_options = 1
allow_old_ssl_tls = 0
num_decoders = 3
rss_odd_titles = nzbindex.nl/, nzbindex.com/, nzbclub.com/
req_completion_rate = 100.2
selftest_host = self-test.sabnzbd.org
movie_rename_limit = 100M
episode_rename_limit = 20M
size_limit = 0
show_sysload = 2
history_limit = 20
wait_ext_drive = 5
max_foldername_length = 246
nomedia_marker = ""
ipv6_servers = 1
url_base = /sabnzbd
host_whitelist = htpc,
local_ranges = ,
max_url_retries = 10
downloader_sleep_time = 10
ssdp_broadcast_interval = 15
socks5_proxy_url = ""
email_server = ""
email_to = ,
email_from = ""
email_account = ""
email_pwd = ""
email_endjob = 0
email_full = 0
email_dir = ""
email_rss = 0
email_cats = *,
num_simd_decoders = 2
ext_rename_ignore = ,
sorters_converted = 1
backup_dir = ""
replace_underscores = 0
tray_icon = 1
enable_season_sorting = 1
receive_threads = 2
switchinterval = 0.005
end_queue_script = None
no_smart_dupes = 0
dupes_propercheck = 1
history_retention_option = all
history_retention_number = 1
enable_multipar = 1
disable_archive = 0
ipv6_staging = 0
verify_xff_header = 0
config_conversion_version = 4
disable_par2cmdline = 0
unrar_parameters = ""
outgoing_nntp_ip = ""
[categories]
[[*]]
name = *
order = 0
pp = 3
script = None
dir = ""
newzbin = ""
priority = 0
[[music]]
name = music
order = 0
pp = ""
script = Default
dir = music
newzbin = music
priority = -100
[[tv]]
name = tv
order = 0
pp = ""
script = Default
dir = tv
newzbin = tv
priority = -100
[[movies]]
name = movies
order = 0
pp = ""
script = Default
dir = movies
newzbin = "movies, movie"
priority = -100
[[radarr]]
name = radarr
order = 0
pp = ""
script = Default
dir = radarr
newzbin = "movies, movie"
priority = -100
[[sonarr]]
name = sonarr
order = 0
pp = ""
script = Default
dir = sonarr
newzbin = tv
priority = -100
[[other]]
name = other
order = 1
pp = ""
script = Default
dir = other
newzbin = "games, game, other"
priority = -100
[[lidarr]]
name = lidarr
order = 2
pp = ""
script = Default
dir = lidarr
newzbin = music
priority = -100
[[readarr]]
name = readarr
order = 3
pp = ""
script = Default
dir = readarr
newzbin = ebooks
priority = -100
[[lazylibrarian]]
name = lazylibrarian
order = 4
pp = ""
script = Default
dir = lazylibrarian
newzbin = "ebooks, audiobooks"
priority = -100
[servers]
{% for s in sabnzbd_servers | default([]) %}
[[{{ s.name }}]]
name = {{ s.name }}
displayname = {{ s.displayname | default(s.name) }}
host = {{ s.host | default(s.name) }}
port = {{ s.port | default(563) }}
timeout = {{ s.timeout | default(60) }}
username = {{ s.username| default('') }}
password = {{ s.password| default('') }}
connections = {{ s.connections | default(50) }}
ssl = {{ s.ssl | default(1) }}
ssl_verify = {{ s.ssl_verify | default(1) }}
ssl_ciphers = {{ s.ssl_ciphers | default('""') }}
enable = {{ s.enable| default(1) }}
required = {{ s.required| default(0) }}
optional = {{ s.optional| default(0) }}
retention = {{ s.retention | default(0) }}
expire_date = {{ s.expire_date | default('""') }}
quota = {{ s.quota | default('""') }}
usage_at_start = {{ s.usage_at_start | default(0) }}
priority = {{ s.priority| default(0) }}
notes = {{ s.notes | default('""') }}
{% endfor %}
[logging]
log_level = 1
max_log_size = 5242880
log_backups = 5
[ncenter]
ncenter_enable = 0
ncenter_cats = *,
ncenter_prio_startup = 1
ncenter_prio_download = 0
ncenter_prio_pause_resume = 0
ncenter_prio_pp = 0
ncenter_prio_complete = 1
ncenter_prio_failed = 1
ncenter_prio_disk_full = 1
ncenter_prio_new_login = 0
ncenter_prio_warning = 0
ncenter_prio_error = 0
ncenter_prio_queue_done = 1
ncenter_prio_other = 1
ncenter_prio_quota = 1
[acenter]
acenter_enable = 0
acenter_cats = *,
acenter_prio_startup = 0
acenter_prio_download = 0
acenter_prio_pause_resume = 0
acenter_prio_pp = 0
acenter_prio_complete = 1
acenter_prio_failed = 1
acenter_prio_disk_full = 1
acenter_prio_new_login = 0
acenter_prio_warning = 0
acenter_prio_error = 0
acenter_prio_queue_done = 1
acenter_prio_other = 1
acenter_prio_quota = 1
[ntfosd]
ntfosd_enable = 1
ntfosd_cats = *,
ntfosd_prio_startup = 1
ntfosd_prio_download = 0
ntfosd_prio_pause_resume = 0
ntfosd_prio_pp = 0
ntfosd_prio_complete = 1
ntfosd_prio_failed = 1
ntfosd_prio_disk_full = 1
ntfosd_prio_new_login = 0
ntfosd_prio_warning = 0
ntfosd_prio_error = 0
ntfosd_prio_queue_done = 1
ntfosd_prio_other = 1
ntfosd_prio_quota = 1
[prowl]
prowl_enable = 0
prowl_cats = *,
prowl_apikey = ""
prowl_prio_startup = -3
prowl_prio_download = -3
prowl_prio_pause_resume = -3
prowl_prio_pp = -3
prowl_prio_complete = 0
prowl_prio_failed = 1
prowl_prio_disk_full = 1
prowl_prio_new_login = -3
prowl_prio_warning = -3
prowl_prio_error = -3
prowl_prio_queue_done = 0
prowl_prio_other = 0
prowl_prio_quota = 0
[pushover]
pushover_token = ""
pushover_userkey = ""
pushover_device = ""
pushover_emergency_expire = 3600
pushover_emergency_retry = 60
pushover_enable = 0
pushover_cats = *,
pushover_prio_startup = -3
pushover_prio_download = -2
pushover_prio_pause_resume = -2
pushover_prio_pp = -3
pushover_prio_complete = -1
pushover_prio_failed = -1
pushover_prio_disk_full = 1
pushover_prio_new_login = -3
pushover_prio_warning = 1
pushover_prio_error = 1
pushover_prio_queue_done = -1
pushover_prio_other = -1
pushover_prio_quota = -1
[pushbullet]
pushbullet_enable = 0
pushbullet_cats = *,
pushbullet_apikey = ""
pushbullet_device = ""
pushbullet_prio_startup = 0
pushbullet_prio_download = 0
pushbullet_prio_pause_resume = 0
pushbullet_prio_pp = 0
pushbullet_prio_complete = 1
pushbullet_prio_failed = 1
pushbullet_prio_disk_full = 1
pushbullet_prio_new_login = 0
pushbullet_prio_warning = 0
pushbullet_prio_error = 0
pushbullet_prio_queue_done = 0
pushbullet_prio_other = 1
pushbullet_prio_quota = 1
[nscript]
nscript_enable = 0
nscript_cats = *,
nscript_script = ""
nscript_parameters = ""
nscript_prio_startup = 1
nscript_prio_download = 0
nscript_prio_pause_resume = 0
nscript_prio_pp = 0
nscript_prio_complete = 1
nscript_prio_failed = 1
nscript_prio_disk_full = 1
nscript_prio_new_login = 0
nscript_prio_warning = 0
nscript_prio_error = 0
nscript_prio_queue_done = 1
nscript_prio_other = 1
nscript_prio_quota = 1
[apprise]
apprise_enable = 0
apprise_cats = *,
apprise_urls = ""
apprise_target_startup = ""
apprise_target_startup_enable = 0
apprise_target_download = ""
apprise_target_download_enable = 0
apprise_target_pause_resume = ""
apprise_target_pause_resume_enable = 0
apprise_target_pp = ""
apprise_target_pp_enable = 0
apprise_target_complete = ""
apprise_target_complete_enable = 1
apprise_target_failed = ""
apprise_target_failed_enable = 1
apprise_target_disk_full = ""
apprise_target_disk_full_enable = 0
apprise_target_new_login = ""
apprise_target_new_login_enable = 1
apprise_target_warning = ""
apprise_target_warning_enable = 0
apprise_target_error = ""
apprise_target_error_enable = 0
apprise_target_queue_done = ""
apprise_target_queue_done_enable = 0
apprise_target_other = ""
apprise_target_other_enable = 1
apprise_target_quota = ""
apprise_target_quota_enable = 1

View File

@@ -0,0 +1,116 @@
---
# Traefik dynamic configuration for HTPC services
# Auto-generated by Ansible - deployed as dotfile
http:
middlewares:
redirect-https:
redirectScheme:
scheme: https
permanent: true
routers:
redirect-to-https:
rule: "HostRegexp(`{any:.*}`)"
entryPoints:
- web
middlewares:
- redirect-https
service: noop
sabnzbd:
rule: "PathPrefix(`/sabnzbd`)"
service: sabnzbd
entryPoints:
- websecure
tls: {}
qbittorrent:
rule: "PathPrefix(`/qbittorrent`)"
service: qbittorrent
entryPoints:
- websecure
tls: {}
sonarr:
rule: "PathPrefix(`/sonarr`)"
service: sonarr
entryPoints:
- websecure
tls: {}
radarr:
rule: "PathPrefix(`/radarr`)"
service: radarr
entryPoints:
- websecure
tls: {}
lidarr:
rule: "PathPrefix(`/lidarr`)"
service: lidarr
entryPoints:
- websecure
tls: {}
lazylibrarian:
rule: "PathPrefix(`/lazylibrarian`)"
service: lazylibrarian
entryPoints:
- websecure
tls: {}
prowlarr:
rule: "PathPrefix(`/prowlarr`)"
service: prowlarr
entryPoints:
- websecure
tls: {}
dashboard:
rule: "PathPrefix(`/dashboard`)"
service: api@internal
entryPoints:
- websecure
tls: {}
services:
noop:
loadBalancer:
servers:
- url: "http://localhost"
sabnzbd:
loadBalancer:
servers:
- url: "http://localhost:8081"
qbittorrent:
loadBalancer:
servers:
- url: "http://localhost:8082"
sonarr:
loadBalancer:
servers:
- url: "http://localhost:{{ SONARR__SERVER__PORT | default('8989') }}"
radarr:
loadBalancer:
servers:
- url: "http://localhost:{{ RADARR__SERVER__PORT | default('7878') }}"
lidarr:
loadBalancer:
servers:
- url: "http://localhost:{{ LIDARR__SERVER__PORT | default('8686') }}"
lazylibrarian:
loadBalancer:
servers:
- url: "http://localhost:{{ lazylibrarian_port | default('5299') }}"
prowlarr:
loadBalancer:
servers:
- url: "http://localhost:{{ PROWLARR__SERVER__PORT | default('9696') }}"

View File

@@ -0,0 +1 @@
{{ traefik_server_cert }}

View File

@@ -0,0 +1 @@
{{ traefik_server_key }}

View File

@@ -31,7 +31,7 @@ mounts:
create_dir: false create_dir: false
- path: /mnt/downloads - path: /mnt/downloads
src: /dev/disk/by-uuid/ee6247ed-5bcf-481e-802e-74efbc02eb45 src: /dev/disk/by-uuid/56a4fe2f-ce26-48cc-b602-548db7357549
fstype: btrfs fstype: btrfs
opts: defaults,compress=zstd:1 opts: defaults,compress=zstd:1
state: mounted state: mounted
@@ -41,7 +41,7 @@ mounts:
create_dir: false create_dir: false
- path: /home/bryan/downloads - path: /home/bryan/downloads
src: /dev/disk/by-uuid/ee6247ed-5bcf-481e-802e-74efbc02eb45 src: /dev/disk/by-uuid/56a4fe2f-ce26-48cc-b602-548db7357549
fstype: btrfs fstype: btrfs
opts: subvol=downloads,defaults,compress=zstd:1,x-systemd.requires=home.mount,x-gvfs-hide opts: subvol=downloads,defaults,compress=zstd:1,x-systemd.requires=home.mount,x-gvfs-hide
state: mounted state: mounted

View File

@@ -5,16 +5,18 @@ htpc-remote ansible_host=htpc ansible_user=bryan
[workstation] [workstation]
workstation-local ansible_connection=local ansible_user=bryan workstation-local ansible_connection=local ansible_user=bryan
workstation-remote ansible_host=workstation ansible_user=bryan workstation-remote ansible_host=workstation ansible_user=bryan
workstation-remote-testing ansible_host=vm-fedora43 ansible_user=bryan
[laptop] [laptop]
laptop-local ansible_connection=local ansible_user=bryan laptop-local ansible_connection=local ansible_user=bryan
laptop-remote ansible_host=laptop ansible_user=bryan laptop-remote ansible_host=laptop ansible_user=bryan
laptop-remote-testing ansible_host=192.168.122.95 ansible_user=bryan
[server] [server]
bryanroessler.com ansible_host=bryanroessler.com ansible_user=bryan bryanroessler.com ansible_host=bryanroessler.com ansible_user=bryan
[testing] # [testing]
testing-remote ansible_host=192.168.122.205 ansible_user=bryan # testing-remote ansible_host=192.168.122.205 ansible_user=bryan
# [desktops:children] # [desktops:children]
# workstation # workstation

View File

@@ -1,115 +1,82 @@
--- ---
- name: Find home dotfiles (excluding templates) - name: Build file lists
ansible.builtin.find: ansible.builtin.set_fact:
paths: dotfiles_files_home: "{{ lookup('community.general.filetree',
- "{{ playbook_dir }}/dotfiles/common/home" playbook_dir ~ '/dotfiles/common/home',
- "{{ playbook_dir }}/dotfiles/{{ group_names[0] }}/home" playbook_dir ~ '/dotfiles/' ~ group_names[0] ~ '/home') | selectattr('state', 'equalto', 'file') | rejectattr('path', 'match', '.*\\.j2$') | list }}"
recurse: true dotfiles_templates_home: "{{ lookup('community.general.filetree',
file_type: file playbook_dir ~ '/dotfiles/common/home',
hidden: true playbook_dir ~ '/dotfiles/' ~ group_names[0] ~ '/home') | selectattr('state', 'equalto', 'file') | selectattr('path', 'match', '.*\\.j2$') | list }}"
excludes: "*.j2" dotfiles_files_root: "{{ lookup('community.general.filetree',
delegate_to: localhost playbook_dir ~ '/dotfiles/common/root',
register: dotfiles_home_files playbook_dir ~ '/dotfiles/' ~ group_names[0] ~ '/root') | selectattr('state', 'equalto', 'file') | rejectattr('path', 'match', '.*\\.j2$') | list }}"
run_once: true dotfiles_templates_root: "{{ lookup('community.general.filetree',
ignore_errors: true playbook_dir ~ '/dotfiles/common/root',
playbook_dir ~ '/dotfiles/' ~ group_names[0] ~ '/root') | selectattr('state', 'equalto', 'file') | selectattr('path', 'match', '.*\\.j2$') | list }}"
- name: Find root dotfiles (excluding templates) - name: Ensure home directories
ansible.builtin.find:
paths:
- "{{ playbook_dir }}/dotfiles/common/root"
- "{{ playbook_dir }}/dotfiles/{{ group_names[0] }}/root"
recurse: true
file_type: file
hidden: true
excludes: "*.j2"
delegate_to: localhost
register: dotfiles_root_files
run_once: true
ignore_errors: true
- name: Find home template files
ansible.builtin.find:
paths:
- "{{ playbook_dir }}/dotfiles/common/home"
- "{{ playbook_dir }}/dotfiles/{{ group_names[0] }}/home"
recurse: true
file_type: file
hidden: true
patterns: "*.j2"
delegate_to: localhost
register: dotfiles_home_templates
run_once: true
ignore_errors: true
- name: Find root template files
ansible.builtin.find:
paths:
- "{{ playbook_dir }}/dotfiles/common/root"
- "{{ playbook_dir }}/dotfiles/{{ group_names[0] }}/root"
recurse: true
file_type: file
hidden: true
patterns: "*.j2"
delegate_to: localhost
register: dotfiles_root_templates
run_once: true
ignore_errors: true
- name: Symlink home dotfiles (local)
ansible.builtin.file: ansible.builtin.file:
src: "{{ item.path }}" path: "{{ ansible_facts.env.HOME }}/{{ item.path | dirname }}"
dest: "{{ ansible_facts['env']['HOME'] }}/{{ item.path | regex_replace('^.+/dotfiles/(?:common|' + group_names[0] + ')/home/', '') }}" state: directory
state: link mode: "{{ '0700' if (item.path | dirname).startswith('.ssh') else '0755' }}"
force: true loop: "{{ dotfiles_files_home + dotfiles_templates_home }}"
loop: "{{ dotfiles_home_files.files }}" when: item.path | dirname != ''
when: ansible_connection in ['local', 'localhost']
- name: Symlink root dotfiles (local) - name: Deploy home files (local)
ansible.builtin.file:
src: "{{ item.path }}"
dest: "/{{ item.path | regex_replace('^.+/dotfiles/(?:common|' + group_names[0] + ')/root/', '') }}"
state: link
force: true
loop: "{{ dotfiles_root_files.files }}"
when: ansible_connection in ['local', 'localhost']
become: true
- name: Deploy home dotfiles (remote)
ansible.builtin.copy:
src: "{{ item.path }}"
dest: "{{ ansible_facts['env']['HOME'] }}/{{ item.path | regex_replace('^.+/dotfiles/(?:common|' + group_names[0] + ')/home/', '') }}"
mode: preserve
loop: "{{ dotfiles_home_files.files }}"
when: ansible_connection not in ['local', 'localhost']
- name: Deploy root dotfiles (remote)
ansible.builtin.copy:
src: "{{ item.path }}"
dest: "/{{ item.path | regex_replace('^.+/dotfiles/(?:common|' + group_names[0] + ')/root/', '') }}"
mode: preserve
loop: "{{ dotfiles_root_files.files }}"
when: ansible_connection not in ['local', 'localhost']
become: true
- name: Template home dotfiles
ansible.builtin.template:
src: "{{ item.path }}"
dest: "{{ ansible_facts['env']['HOME'] }}/{{ item.path | regex_replace('^.+/dotfiles/(?:common|' + group_names[0] + ')/home/', '') | replace('.j2', '') }}"
mode: '0600'
loop: "{{ dotfiles_home_templates.files }}"
- name: Template root dotfiles
ansible.builtin.template:
src: "{{ item.path }}"
dest: "/{{ item.path | regex_replace('^.+/dotfiles/(?:common|' + group_names[0] + ')/root/', '') | replace('.j2', '') }}"
mode: '0600'
loop: "{{ dotfiles_root_templates.files }}"
become: true
- name: Deploy symlinks
ansible.builtin.file: ansible.builtin.file:
src: "{{ item.src }}" src: "{{ item.src }}"
dest: "{{ item.dest }}" dest: "{{ ansible_facts.env.HOME }}/{{ item.path }}"
state: link state: link
force: true force: true
loop: "{{ symlinks | default([]) }}" loop: "{{ dotfiles_files_home }}"
when: ansible_connection in ['local', 'localhost']
- name: Deploy home files (remote)
ansible.builtin.copy:
src: "{{ item.src }}"
dest: "{{ ansible_facts.env.HOME }}/{{ item.path }}"
mode: preserve
loop: "{{ dotfiles_files_home }}"
when: ansible_connection not in ['local', 'localhost']
- name: Render home templates
ansible.builtin.template:
src: "{{ item.src }}"
dest: "{{ ansible_facts.env.HOME }}/{{ item.path | replace('.j2', '') }}"
mode: preserve
loop: "{{ dotfiles_templates_home }}"
- name: Ensure root directories
ansible.builtin.file:
path: "/{{ item.path | dirname }}"
state: directory
mode: '0755'
loop: "{{ dotfiles_files_root + dotfiles_templates_root }}"
become: true
- name: Deploy root files (local)
ansible.builtin.file:
src: "{{ item.src }}"
dest: "/{{ item.path }}"
state: link
force: true
loop: "{{ dotfiles_files_root }}"
when: ansible_connection in ['local', 'localhost']
become: true
- name: Deploy root files (remote)
ansible.builtin.copy:
src: "{{ item.src }}"
dest: "/{{ item.path }}"
mode: preserve
loop: "{{ dotfiles_files_root }}"
when: ansible_connection not in ['local', 'localhost']
become: true
- name: Render root templates
ansible.builtin.template:
src: "{{ item.src }}"
dest: "/{{ item.path | replace('.j2', '') }}"
mode: preserve
loop: "{{ dotfiles_templates_root }}"
become: true