authorgravatar for git@paperclover.netclover caruso <git@paperclover.net> 2026-01-09 00:28:36-08:00
committergravatar for git@paperclover.netclover caruso <git@paperclover.net> 2026-01-09 02:52:13-08:00
log839f6e614995faa9c948343f23bb23831af3117c
tree93623916fecc52b8c26002b646dc499f54e72532
parent6818a04ce885276880fac95a779f3a5a6c849727
signaturelock-open Commit is signed but in an unrecognized format.

feat: internal services on SSO


5 files changed, 162 insertions(+), 143 deletions(-)

compose.yaml+57-51
......@@ -17,6 +17,12 @@ services:
1717 watch:
1818 - path: ./config/Caddyfile
1919 action: restart
20 healthcheck:
21 test: ["CMD", "caddy", "healthcheck", "--address", ":2019"]
22 interval: 10s
23 timeout: 5s
24 retries: 3
25 start_period: 5s
2026 # SSO
2127 keycloak: # port 80, 443
2228 container_name: keycloak
......@@ -255,6 +261,7 @@ services:
255261 ND_SCANNER_GROUPALBUMRELEASES: "1"
256262 ND_BASEURL: "https://music.${HOME_DOMAIN}/"
257263 ND_PID_ALBUM: "folder"
264 ND_EXTAUTH_USERHEADER: "Remote-User"
258265 ND_EXTAUTH_TRUSTEDSOURCES: "0.0.0.0/0" # troll
259266 ND_PORT: "80"
260267 labels:
......@@ -306,55 +313,55 @@ services:
306313 net.paperclover.list.domain: qbt
307314 net.paperclover.list.priority: 52
308315 net.paperclover.list.access: media-manage
309 # jackett: # port 9117
310 # container_name: jackett
311 # environment:
312 # - "PUID=$USER_ID"
313 # - "PGID=$GROUP_ID"
314 # - "TZ=America/Los_Angelas"
315 # image: lscr.io/linuxserver/jackett:latest
316 # restart: unless-stopped
317 # volumes:
318 # - "${APP_ROOT}/jackett:/config/Jackett"
319 # labels:
320 # net.paperclover.list.name: Jackett API Adapter
321 # net.paperclover.list.domain: jkt
322 # net.paperclover.list.priority: 40
323 # net.paperclover.list.access: media-manage
324 # sonarr: # port 8989
325 # container_name: sonarr
326 # environment:
327 # - "PUID=$USER_ID"
328 # - "PGID=$GROUP_ID"
329 # - "TZ=America/Los_Angelas"
330 # image: lscr.io/linuxserver/sonarr:latest
331 # volumes:
332 # - "${APP_ROOT}/sonarr:/config"
333 # - "${TORRENT_TEMP:-${APP_ROOT}/qbittorrent/tmp}:/data/tmp"
334 # - "${MEDIA_ROOT}:/data/media"
335 # restart: unless-stopped
336 # labels:
337 # net.paperclover.list.name: Sonarr TV PVR
338 # net.paperclover.list.domain: jkt
339 # net.paperclover.list.priority: 51
340 # net.paperclover.list.access: media-manage
341 # radarr: # port 7878
342 # container_name: radarr
343 # environment:
344 # - "PUID=$USER_ID"
345 # - "PGID=$GROUP_ID"
346 # - "TZ=America/Los_Angelas"
347 # image: lscr.io/linuxserver/radarr:latest
348 # volumes:
349 # - "${APP_ROOT}/radarr:/config"
350 # - "${TORRENT_TEMP:-${APP_ROOT}/qbittorrent/tmp}:/data/tmp"
351 # - "${MEDIA_ROOT}:/data/media"
352 # restart: unless-stopped
353 # labels:
354 # net.paperclover.list.name: Radarr Movie Organizer
355 # net.paperclover.list.domain: jkt
356 # net.paperclover.list.priority: 50
357 # net.paperclover.list.access: media-manage
316 jackett: # port 9117
317 container_name: jackett
318 environment:
319 - "PUID=$USER_ID"
320 - "PGID=$GROUP_ID"
321 - "TZ=America/Los_Angelas"
322 image: lscr.io/linuxserver/jackett:latest
323 restart: unless-stopped
324 volumes:
325 - "${APP_ROOT}/jackett:/config/Jackett"
326 labels:
327 net.paperclover.list.name: Jackett API Adapter
328 net.paperclover.list.domain: jkt
329 net.paperclover.list.priority: 40
330 net.paperclover.list.access: media-manage
331 sonarr: # port 8989
332 container_name: sonarr
333 environment:
334 - "PUID=$USER_ID"
335 - "PGID=$GROUP_ID"
336 - "TZ=America/Los_Angelas"
337 image: lscr.io/linuxserver/sonarr:latest
338 volumes:
339 - "${APP_ROOT}/sonarr:/config"
340 - "${TORRENT_TEMP:-${APP_ROOT}/qbittorrent/tmp}:/data/tmp"
341 - "${MEDIA_ROOT}:/data/media"
342 restart: unless-stopped
343 labels:
344 net.paperclover.list.name: Sonarr TV PVR
345 net.paperclover.list.domain: jkt
346 net.paperclover.list.priority: 51
347 net.paperclover.list.access: media-manage
348 radarr: # port 7878
349 container_name: radarr
350 environment:
351 - "PUID=$USER_ID"
352 - "PGID=$GROUP_ID"
353 - "TZ=America/Los_Angelas"
354 image: lscr.io/linuxserver/radarr:latest
355 volumes:
356 - "${APP_ROOT}/radarr:/config"
357 - "${TORRENT_TEMP:-${APP_ROOT}/qbittorrent/tmp}:/data/tmp"
358 - "${MEDIA_ROOT}:/data/media"
359 restart: unless-stopped
360 labels:
361 net.paperclover.list.name: Radarr Movie Organizer
362 net.paperclover.list.domain: rdr
363 net.paperclover.list.priority: 50
364 net.paperclover.list.access: media-manage
358365 # language models
359366 opencode: # port 4096
360367 container_name: opencode
......@@ -554,7 +561,7 @@ services:
554561 net.paperclover.list.name: Open Speed Test
555562 net.paperclover.list.domain: speedtest
556563 net.paperclover.list.priority: 10
557 technitium-dns:
564 technitium-dns: # port 5380
558565 image: technitium/dns-server
559566 container_name: technitium-dns
560567 user: "$USER_ID:$GROUP_ID"
......@@ -563,7 +570,6 @@ services:
563570 - 53:53/tcp
564571 - 67:67/udp
565572 - 68:68/udp
566 - 5380:5380/tcp # Web console
567573 - 8053:8053/tcp # dns over http
568574 volumes:
569575 - "${APP_ROOT}/technitium/config:/app/config"
config/403.html created+5
......@@ -0,0 +1,5 @@
1no permission &lt;/3 ... <br>
2<a href="/snow.oauth2/sign_out">retry</a>
3<br>
4<br>
5contact clover for assistance...
config/Caddyfile+96-89
......@@ -1,62 +1,45 @@
1# (auth_require) {
2# @not_websocket not header Connection Upgrade
3# handle /snow.oauth2/* {
4# reverse_proxy "http://forward-auth" {
5# header_up X-Real-IP {remote_host}
6# header_up X-Forwarded-Uri {uri}
7# }
8# }
9#
10# handle {
11# forward_auth @not_websocket "http://forward-auth" {
12# uri /snow.oauth2/auth
13# header_up X-Real-IP {remote_host}
14# copy_headers X-Forwarded-User X-Forwarded-Groups X-Forwarded-Email
15# @error status 401
16# handle_response @error {
17# redir * /snow.oauth2/sign_in?rd={scheme}://{host}{uri}
18# }
19# }
20#
21# reverse_proxy {args[:]}
22# }
23# }
24(auth-optional) {
25 handle /snow.oauth2/* {
1{
2 admin
3}
4
5(reverse_proxy_auth) {
6 handle /snow.oauth2/* {
267 reverse_proxy "http://forward-auth" {
278 header_up X-Real-IP {remote_host}
289 header_up X-Forwarded-Uri {uri}
2910 }
3011 }
31
32 @not_websocket not header Connection Upgrade
33 reverse_proxy @not_websocket "http://forward-auth" {
34 method GET
35 rewrite /snow.oauth2/auth
36
37 header_up X-Forwarded-Method {method}
38 header_up X-Forwarded-Uri {uri}
39
40 @good status 2xx
41 handle_response @good {
42 request_header User-Id {rp.header.X-Auth-Request-User}
43 request_header User-Groups {rp.header.X-Auth-Request-Groups}
44 request_header User-Email {rp.header.X-Auth-Request-Email}
45 request_header User-Name {rp.header.X-Auth-Request-Preferred-Username}
46 }
47 @bad status 4xx
48 handle_response @bad {
49 request_header User-Id ""
50 request_header User-Groups ""
51 request_header User-Email ""
52 request_header User-Name ""
12 handle {
13 reverse_proxy "http://forward-auth" {
14 method GET
15 header_up X-Forwarded-Method {method}
16 header_up X-Forwarded-Uri {uri}
17 rewrite /snow.oauth2/auth
18 header_up X-Real-IP {remote_host}
19 @error status 401
20 handle_response @error {
21 redir * /snow.oauth2/sign_in?rd={scheme}://{host}{uri}
22 }
23 @valid_group header X-Auth-Request-Groups *role:{args[1]}*
24 handle_response @valid_group {
25 method {method}
26 rewrite {uri}
27 reverse_proxy {args[0]} {
28 header_up Cookie ([^;]*?)\s*_oauth2_proxy_\d=[^;]*(;?.*) "$1$2"
29 {block}
30 }
31 }
32 handle_response {
33 rewrite /403.html
34 file_server {
35 status 403
36 root /etc/caddy
37 }
38 }
5339 }
5440 }
55
56 reverse_proxy {args[:]}
5741}
5842
59
6043# services are sorted alphabetically
6144auth.{$HOME_DOMAIN} {
6245 handle / {
......@@ -70,6 +53,9 @@ dawarich.{$HOME_DOMAIN} {
7053db.{$HOME_DOMAIN} {
7154 reverse_proxy "http://clover-source-of-truth"
7255}
56dns.{$HOME_DOMAIN} {
57 import reverse_proxy_auth "http://technitium-dns:5380" admin
58}
7359file.{$HOME_DOMAIN} {
7460 handle "/.static/*" {
7561 uri strip_prefix /.static
......@@ -82,7 +68,36 @@ file.{$HOME_DOMAIN} {
8268 root /etc/caddy/static
8369 file_server
8470 }
85 import auth-optional "http://copyparty"
71 handle /snow.oauth2/* {
72 reverse_proxy "http://forward-auth" {
73 header_up X-Real-IP {remote_host}
74 header_up X-Forwarded-Uri {uri}
75 }
76 }
77 @should_auth not path /shr/*
78 reverse_proxy @should_auth "http://forward-auth" {
79 method GET
80 rewrite /snow.oauth2/auth
81
82 header_up X-Forwarded-Method {method}
83 header_up X-Forwarded-Uri {uri}
84
85 @good status 2xx
86 handle_response @good {
87 request_header User-Id {rp.header.X-Auth-Request-User}
88 request_header User-Groups {rp.header.X-Auth-Request-Groups}
89 request_header User-Email {rp.header.X-Auth-Request-Email}
90 request_header User-Name {rp.header.X-Auth-Request-Preferred-Username}
91 }
92 @bad status 4xx
93 handle_response @bad {
94 request_header User-Id ""
95 request_header User-Groups ""
96 request_header User-Email ""
97 request_header User-Name ""
98 }
99 }
100 reverse_proxy "http://copyparty"
86101}
87102git.{$HOME_DOMAIN} {
88103 handle /user/login {
......@@ -94,12 +109,11 @@ git.{$HOME_DOMAIN} {
94109 }
95110}
96111import ./jellyfin/Caddyfile
97# jkt.{$HOME_DOMAIN} {
98# import auth
99# reverse_proxy "http://jackett:9117" {
100# header_up Authorization "Basic dXNlcm5hbWU6cGFzc3dvcmQ="
101# }
102# }
112jkt.{$HOME_DOMAIN} {
113 import reverse_proxy_auth "http://jackett:9117" media-manage {
114 header_up Authorization "Basic dXNlcm5hbWU6cGFzc3dvcmQ="
115 }
116}
103117music.{$HOME_DOMAIN} {
104118 handle_path /app/sw.js {
105119 header Content-Type "application/javascript"
......@@ -147,41 +161,34 @@ music.{$HOME_DOMAIN} {
147161 reverse_proxy "http://navidrome"
148162 }
149163}
150# opencode.{$HOME_DOMAIN} {
151# import auth
152# reverse_proxy "http://opencode"
153# }
154# pg.{$HOME_DOMAIN} {
155# import auth
156# reverse_proxy "http://pgadmin"
157# }
158# qbt.{$HOME_DOMAIN} {
159# import auth
160# reverse_proxy "qbittorrent:23938"
161# }
162# redis.{$HOME_DOMAIN} {
163# import auth
164# reverse_proxy "redis-insight:5540"
165# }
166# rdr.{$HOME_DOMAIN} {
167# import auth
168# reverse_proxy "radarr:7878" {
169# header_up Authorization "Basic dXNlcm5hbWU6cGFzc3dvcmQ="
170# }
171# }
172# snr.{$HOME_DOMAIN} {
173# import auth
174# reverse_proxy "sonarr:8989" {
175# header_up Authorization "Basic dXNlcm5hbWU6cGFzc3dvcmQ="
176# }
177# }
164opencode.{$HOME_DOMAIN} {
165 import reverse_proxy_auth "http://opencode" admin
166}
167pg.{$HOME_DOMAIN} {
168 import reverse_proxy_auth "http://pgadmin" admin
169}
170qbt.{$HOME_DOMAIN} {
171 import reverse_proxy_auth "http://qbittorrent:23938" media-manage
172}
173redis.{$HOME_DOMAIN} {
174 import reverse_proxy_auth "http://redis-insight:5540" admin
175}
176rdr.{$HOME_DOMAIN} {
177 import reverse_proxy_auth "http://radarr:7878" media-manage {
178 header_up Authorization "Basic dXNlcm5hbWU6cGFzc3dvcmQ="
179 }
180}
181snr.{$HOME_DOMAIN} {
182 import reverse_proxy_auth "http://sonarr:8989" media-manage {
183 header_up Authorization "Basic dXNlcm5hbWU6cGFzc3dvcmQ="
184 }
185}
178186speedtest.{$HOME_DOMAIN} {
179187 reverse_proxy "openspeedtest:3000"
180188}
181# sync.{$HOME_DOMAIN} {
182# import auth
183# reverse_proxy "syncthing:8384"
184# }
189sync.{$HOME_DOMAIN} {
190 import reverse_proxy_auth "http://syncthing:8384" admin
191}
185192
186193# redirections
187194paperclover.dev {
config/jellyfin/Caddyfile+3-2
......@@ -49,8 +49,9 @@ jelly.{$HOME_DOMAIN} {
4949 }
5050
5151 /* theme fixes */
52 .playlistSectionButton, .noBackdropTransparency .detailPagePrimaryContainer {
53 background: rgb(from var(--main-background) r g b / 50%;
52 .material-icons.play_arrow { display: flex }
53 .detailPagePrimaryContainer {
54 background: rgb(from var(--main-background) r g b / 75%)!;
5455 }
5556 .selectLabel {
5657 display: flex;
config/keycloak/init.py+1-1
......@@ -19,7 +19,7 @@ def env(key: str):
1919 return val
2020
2121
22groups_to_create = ["snow", "media", "media-manage", "git", "file"]
22groups_to_create = ["snow", "media-manage"]
2323realm_config = {
2424 "realm": "master",
2525 "displayName": "snow sign on",