Compare commits

...

2 Commits

Author SHA1 Message Date
Neale Pickett fe45901803 Move to qBittorrent 2022-10-12 18:37:25 -06:00
Neale Pickett 801fb60e26 transmission getting on my nerves 2022-10-12 17:45:23 -06:00
6 changed files with 169 additions and 463 deletions

View File

@ -35,12 +35,37 @@ ancestry.woozle.org {
reverse_proxy geneweb:2317
}
##
## handle sends original path
## handle_path truncates path
##
deergrove.woozle.org, sweetums.woozle.org {
handle_path /qbittorrent/* {
import restricted-access
reverse_proxy host.docker.internal:6880
}
handle /transmission/* {
import restricted-access
reverse_proxy host.docker.internal:9091
}
handle /nzbget/* {
import restricted-access
reverse_proxy nzbget:6789
}
handle /sonarr/* {
import restricted-access
reverse_proxy sonarr:8989
}
handle /jackett/* {
import restricted-access
reverse_proxy jackett:9117
}
handle_path /sucker/* {
import restricted-access
reverse_proxy host.docker.internal:5880

View File

@ -22,8 +22,6 @@ services:
target: /etc/caddy/Caddyfile
- source: index.html
target: /www/index.html
- source: browse.html
target: /www/browse.html
extra_hosts:
- host.docker.internal:host-gateway
@ -55,13 +53,45 @@ services:
bind:
propagation: rslave
transmission:
image: ghcr.io/linuxserver/transmission
networks:
- hostnet
qbittorrent:
image: lscr.io/linuxserver/qbittorrent
volumes:
- type: bind
source: /srv/ext/sys/transmission
source: /srv/ext/sys/qbittorrent
target: /config
- type: bind
source: /srv/ext/incoming
target: /srv/ext/incoming
environment:
HOST_PORT: 6680
networks:
- hostnet
sonarr:
image: lscr.io/linuxserver/sonarr
volumes:
- type: bind
source: /srv/ext/sys/sonarr
target: /config
- type: bind
source: /srv/ext/media/tv
target: /srv/ext/media/tv
- type: bind
source: /srv/ext/incoming
target: /srv/ext/incoming
jackett:
image: lscr.io/linuxserver/jackett
volumes:
- type: bind
source: /srv/ext/sys/jackett
target: /config
nzbget:
image: lscr.io/linuxserver/nzbget
volumes:
- type: bind
source: /srv/ext/sys/nzbget
target: /config
- type: bind
source: /srv/ext/incoming
@ -86,7 +116,7 @@ services:
read_only: true
wallart:
image: wallart-server
image: git.woozle.org/neale/wallart-server
volumes:
- type: bind
source: /srv/ext/sys/wallart
@ -101,8 +131,6 @@ services:
- type: bind
source: /srv/ext/sys/atlas/status
target: /var/atlas-probe/status
networks:
- hostnet
geneweb:
image: ravermeister/geneweb
@ -132,6 +160,7 @@ services:
GROUPID: 911
# name;path;browse;readonly;guest
SHARE1: drive;/srv/ext;yes;no;no
SHARE2: retropie;/srv/ext/media/games/retropie;yes;yes;yes
env_file:
- secrets/samba-users.env
ports:
@ -157,13 +186,13 @@ configs:
name: dave.yaml-v3
Caddyfile:
file: Caddyfile
name: Caddyfile-v40
name: Caddyfile-v49
index.html:
file: www/index.html
name: index.html-v16
browse.html:
file: www/browse.html
name: browse.html-v5
file: index.html
name: index.html-v25
transmission-rss.yaml:
file: transmission-rss.yaml
name: transmission-rss.yaml-v1
secrets:

87
homelab/index.html Normal file
View File

@ -0,0 +1,87 @@
<!DOCTYPE html>
<html>
<head>
<title>Deer Grove</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
body {
font-family: sans-serif;
background: #efe;
}
section {
margin: 3em auto;
max-width: 30em;
}
menu, ul {
margin-block: auto;
padding-inline: inherit;
list-style: none;
}
li {
margin: 1em;
}
</style>
</head>
<body>
<h1>Deer Grove</h1>
<section>
<menu>
<h2>Major Services</h2>
<ul>
<li><a href="//drive.woozle.org/">📁 Drive</a></li>
<li><a href="//ancestry.woozle.org/">👪 Ancestry</a></li>
<li><a href="//git.woozle.org/">🗄️ Git</a></li>
</ul>
<h2>Smaller stuff</h2>
<ul>
<li><a href="/octoprint/">🖨️ Octoprint: 3d Printer</a></li>
<li><a href="/wallart/">🖼️ Wall Art Uploader</a></li>
</ul>
<h2>Media</h2>
<ul>
<li><a href="/sucker/">💿 Media Sucker: DVD/CD ripper</a></li>
<li><a href="/sonarr/">📺 Sonarr: TV episode manager</a></li>
<li><a href="/jackett/">🧥 Jackett: Tracker RSS proxy</a></li>
<li><a href="/qbittorrent/">📥 qBittorrent</a></li>
<li><a href="/nzbget/">📰 NZBGet: Usenet fetcher</a></li>
</ul>
</menu>
</section>
<section>
<h1>How all the media stuff fits together</h1>
<p>
Plex is the main interface for users.
It indexes media in <tt>/srv/ext/media</tt>
and lets everybody watch it whetever.
</p>
<p>
Sonarr lets you tell it what you'd like to have,
and watches various feeds,
waiting for it to appear.
Then it tells a downloader to download it.
Once a file is downloaded,
it moves it into a directory where Plex can see it,
making sure it's named properly.
</p>
<p>
Jackett is a feed provider,
which searches torrent sites and provides the results as feeds.
<a href="https://nzbgeek.info/">NZBGeek</a> is a paid feed provider that I use:
it monitors usenet for new posts,
and provides them as feeds.
Usenet is a very old distributed bulletin board: it even predates the World Wide Web.
I pay <a href="https://frugalusenet.com/">Frugal Usenet</a> $5 a month to run a Usenet server so I don't have to.
</p>
<p>
Transmission and NZBGet are downloaders.
They pull files down from bit torrent (Transmission)
and Usenet (NZBGet).
</p>
</section>
</body>
</html>
<!--
vi: ts=2 sw=2 et ai
-->

View File

@ -0,0 +1,12 @@
feeds:
- url: https://www.finnix.org/rss/bittorrent/seeder.rss
download_path: /srv/ext/incoming/seeds
seed_ratio_limit: 50
- url: https://archlinux.org/feeds/releases/
download_path: /srv/ext/incoming/seeds
seed_ratio_limit: 50
server:
host: 192.168.86.2
port: 9091
rpc_path: /transmission/rpc

View File

@ -1,415 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<title>{{html .Name}}</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
* { padding: 0; margin: 0; }
body {
font-family: sans-serif;
text-rendering: optimizespeed;
background-color: #ffffff;
}
a {
color: #006ed3;
text-decoration: none;
}
a:hover,
h1 a:hover {
color: #319cff;
}
a:visited {
color: #800080;
}
header,
#summary {
padding-left: 5%;
padding-right: 5%;
}
th:first-child,
td:first-child {
width: 5%;
}
th:last-child,
td:last-child {
width: 5%;
}
header {
padding-top: 25px;
padding-bottom: 15px;
background-color: #f2f2f2;
}
h1 {
font-size: 20px;
font-weight: normal;
white-space: nowrap;
overflow-x: hidden;
text-overflow: ellipsis;
color: #999;
}
h1 a {
color: #000;
margin: 0 4px;
}
h1 a:hover {
text-decoration: underline;
}
h1 a:first-child {
margin: 0;
}
main {
display: block;
}
.meta {
font-size: 12px;
font-family: Verdana, sans-serif;
border-bottom: 1px solid #9C9C9C;
padding-top: 10px;
padding-bottom: 10px;
}
.meta-item {
margin-right: 1em;
}
#filter {
padding: 4px;
border: 1px solid #CCC;
}
table {
width: 100%;
border-collapse: collapse;
}
tr {
border-bottom: 1px dashed #dadada;
}
tbody tr:hover {
background-color: #ffffec;
}
th,
td {
text-align: left;
padding: 10px 0;
}
th {
padding-top: 15px;
padding-bottom: 15px;
font-size: 16px;
white-space: nowrap;
}
th a {
color: black;
}
th svg {
vertical-align: middle;
}
td {
white-space: nowrap;
font-size: 14px;
}
td:nth-child(2) {
width: 80%;
}
td:nth-child(3),
th:nth-child(3) {
padding: 0 20px 0 20px;
}
th:nth-child(4),
td:nth-child(4) {
text-align: right;
}
td:nth-child(2) svg {
position: absolute;
}
td .name,
td .goup {
margin-left: 1.75em;
word-break: break-all;
overflow-wrap: break-word;
white-space: pre-wrap;
}
.icon {
margin-right: 5px;
}
.icon.sort {
display: inline-block;
width: 1em;
height: 1em;
position: relative;
top: .2em;
}
.icon.sort .top {
position: absolute;
left: 0;
top: -1px;
}
.icon.sort .bottom {
position: absolute;
bottom: -1px;
left: 0;
}
footer {
padding: 40px 20px;
font-size: 12px;
text-align: center;
}
@media (max-width: 600px) {
.hideable {
display: none;
}
td:nth-child(2) {
width: auto;
}
th:nth-child(3),
td:nth-child(3) {
padding-right: 5%;
text-align: right;
}
h1 {
color: #000;
}
h1 a {
margin: 0;
}
#filter {
max-width: 100px;
}
}
@media (prefers-color-scheme: dark) {
body {
background-color: #101010;
color: #dddddd;
}
header {
background-color: #151515;
}
tbody tr:hover {
background-color: #252525;
}
header a,
th a {
color: #dddddd;
}
a {
color: #5796d1;
text-decoration: none;
}
a:hover,
h1 a:hover {
color: #62b2fd;
}
a:visited {
color: #a0a0f0;
}
tr {
border-bottom: 1px dashed rgba(255, 255, 255, 0.12);
}
#filter {
background-color: #151515;
color: #ffffff;
border: 1px solid #212121;
}
.meta {
border-bottom: 1px solid #212121
}
}
</style>
</head>
<body onload='initFilter()'>
<header>
<h1>
{{range $i, $crumb := .Breadcrumbs}}<a href="{{html $crumb.Link}}">{{html $crumb.Text}}</a>{{if ne $i 0}}/{{end}}{{end}}
</h1>
</header>
<main>
<div class="meta">
<div id="summary">
<span class="meta-item"><b>{{.NumDirs}}</b> director{{if eq 1 .NumDirs}}y{{else}}ies{{end}}</span>
<span class="meta-item"><b>{{.NumFiles}}</b> file{{if ne 1 .NumFiles}}s{{end}}</span>
{{- if ne 0 .Limit}}
<span class="meta-item">(of which only <b>{{.Limit}}</b> are displayed)</span>
{{- end}}
<span class="meta-item"><input type="text" placeholder="filter" id="filter" onkeyup='filter()'></span>
</div>
</div>
<div class="listing">
<table aria-describedby="summary">
<thead>
<tr>
<th></th>
<th>
{{- if and (eq .Sort "namedirfirst") (ne .Order "desc")}}
<a href="?sort=namedirfirst&order=desc{{if ne 0 .Limit}}&limit={{.Limit}}{{end}}{{if ne 0 .Offset}}&offset={{.Offset}}{{end}}" class="icon">⬆️</a>
{{- else if and (eq .Sort "namedirfirst") (ne .Order "asc")}}
<a href="?sort=namedirfirst&order=asc{{if ne 0 .Limit}}&limit={{.Limit}}{{end}}{{if ne 0 .Offset}}&offset={{.Offset}}{{end}}" class="icon">⬇️</a>
{{- else}}
<a href="?sort=namedirfirst&order=asc{{if ne 0 .Limit}}&limit={{.Limit}}{{end}}{{if ne 0 .Offset}}&offset={{.Offset}}{{end}}" class="icon sort">↕️</a>
{{- end}}
{{- if and (eq .Sort "name") (ne .Order "desc")}}
<a href="?sort=name&order=desc{{if ne 0 .Limit}}&limit={{.Limit}}{{end}}{{if ne 0 .Offset}}&offset={{.Offset}}{{end}}">Name ⬆️</a>
{{- else if and (eq .Sort "name") (ne .Order "asc")}}
<a href="?sort=name&order=asc{{if ne 0 .Limit}}&limit={{.Limit}}{{end}}{{if ne 0 .Offset}}&offset={{.Offset}}{{end}}">Name ⬇️</a>
{{- else}}
<a href="?sort=name&order=asc{{if ne 0 .Limit}}&limit={{.Limit}}{{end}}{{if ne 0 .Offset}}&offset={{.Offset}}{{end}}">Name</a>
{{- end}}
</th>
<th>
{{- if and (eq .Sort "size") (ne .Order "desc")}}
<a href="?sort=size&order=desc{{if ne 0 .Limit}}&limit={{.Limit}}{{end}}{{if ne 0 .Offset}}&offset={{.Offset}}{{end}}">Size ⬆️<svg width="1em" height=".5em" version="1.1" viewBox="0 0 12.922194 6.0358899"><use xlink:href="#up-arrow"></use></svg></a>
{{- else if and (eq .Sort "size") (ne .Order "asc")}}
<a href="?sort=size&order=asc{{if ne 0 .Limit}}&limit={{.Limit}}{{end}}{{if ne 0 .Offset}}&offset={{.Offset}}{{end}}">Size ⬇️<svg width="1em" height=".5em" version="1.1" viewBox="0 0 12.922194 6.0358899"><use xlink:href="#down-arrow"></use></svg></a>
{{- else}}
<a href="?sort=size&order=asc{{if ne 0 .Limit}}&limit={{.Limit}}{{end}}{{if ne 0 .Offset}}&offset={{.Offset}}{{end}}">Size</a>
{{- end}}
</th>
<th class="hideable">
{{- if and (eq .Sort "time") (ne .Order "desc")}}
<a href="?sort=time&order=desc{{if ne 0 .Limit}}&limit={{.Limit}}{{end}}{{if ne 0 .Offset}}&offset={{.Offset}}{{end}}">Modified ⬆️<svg width="1em" height=".5em" version="1.1" viewBox="0 0 12.922194 6.0358899"><use xlink:href="#up-arrow"></use></svg></a>
{{- else if and (eq .Sort "time") (ne .Order "asc")}}
<a href="?sort=time&order=asc{{if ne 0 .Limit}}&limit={{.Limit}}{{end}}{{if ne 0 .Offset}}&offset={{.Offset}}{{end}}">Modified ⬇️</a>
{{- else}}
<a href="?sort=time&order=asc{{if ne 0 .Limit}}&limit={{.Limit}}{{end}}{{if ne 0 .Offset}}&offset={{.Offset}}{{end}}">Modified</a>
{{- end}}
</th>
<th class="hideable"></th>
</tr>
</thead>
<tbody>
{{- if .CanGoUp}}
<tr>
<td></td>
<td>
<a href="..">
<span class="goup">Go up</span>
</a>
</td>
<td>&mdash;</td>
<td class="hideable">&mdash;</td>
<td class="hideable"></td>
</tr>
{{- end}}
{{- range .Items}}
<tr class="file">
<td></td>
<td>
<a href="{{html .URL}}">
{{- if .IsDir}}📁{{else}}📄{{end -}}
<span class="name">{{html .Name}}</span>
</a>
</td>
{{- if .IsDir}}
<td data-order="-1">&mdash;</td>
{{- else}}
<td data-order="{{.Size}}">{{.HumanSize}}</td>
{{- end}}
<td class="hideable"><time datetime="{{.HumanModTime "2006-01-02T15:04:05Z"}}">{{.HumanModTime "01/02/2006 03:04:05 PM -07:00"}}</time></td>
<td class="hideable"></td>
</tr>
{{- end}}
</tbody>
</table>
</div>
</main>
<footer>
Served with <a rel="noopener noreferrer" href="https://caddyserver.com">Caddy</a>
</footer>
<script>
var filterEl = document.getElementById('filter');
filterEl.focus({ preventScroll: true });
function initFilter() {
if (!filterEl.value) {
var filterParam = new URL(window.location.href).searchParams.get('filter');
if (filterParam) {
filterEl.value = filterParam;
}
}
filter();
}
function filter() {
var q = filterEl.value.trim().toLowerCase();
var elems = document.querySelectorAll('tr.file');
elems.forEach(function(el) {
if (!q) {
el.style.display = '';
return;
}
var nameEl = el.querySelector('.name');
var nameVal = nameEl.textContent.trim().toLowerCase();
if (nameVal.indexOf(q) !== -1) {
el.style.display = '';
} else {
el.style.display = 'none';
}
});
}
function localizeDatetime(e, index, ar) {
if (e.textContent === undefined) {
return;
}
var d = new Date(e.getAttribute('datetime'));
if (isNaN(d)) {
d = new Date(e.textContent);
if (isNaN(d)) {
return;
}
}
e.textContent = d.toLocaleString([], {day: "2-digit", month: "2-digit", year: "numeric", hour: "2-digit", minute: "2-digit", second: "2-digit"});
}
var timeList = Array.prototype.slice.call(document.getElementsByTagName("time"));
timeList.forEach(localizeDatetime);
</script>
</body>
</html>

View File

@ -1,32 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<title>Deer Grove</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bulma@0.9.3/css/bulma.min.css">
</head>
<body>
<section class="section">
<div class="container">
<menu class="menu">
<p class="menu-label">Major Services</p>
<ul class="menu-list">
<li><a href="//drive.woozle.org/">📁 Drive</a></li>
<li><a href="//ancestry.woozle.org/">👪 Ancestry</a></li>
<li><a href="//git.woozle.org/">🗄️ Git</a></li>
</ul>
<p class="menu-label">Smaller stuff</p>
<ul class="menu-list">
<li><a href="/sucker/">💿 Media Sucker: DVD/CD ripper</a></li>
<li><a href="/transmission/web/">📥 Transmission: BitTorrent</a></li>
<li><a href="/octoprint/">🖨️ Octoprint: 3d Printer</a></li>
<li><a href="/wallart/">🖼️ Wall Art Uploader</a></li>
</ul>
</menu>
</template>
</body>
</html>
<!--
vi: ts=2 sw=2 et ai
-->