Compare commits

...

4 Commits

Author SHA1 Message Date
263dc9e9e8 Updates to add sage recipe host 2026-07-07 20:54:16 -05:00
74f2d1efb9 Add authentik stuff 2026-06-30 21:56:04 -05:00
81dbcd0953 Move more of servarr onto the proxy 2026-06-30 21:55:55 -05:00
0121845d01 Cleanup a few unused containers 2026-06-30 21:54:48 -05:00
10 changed files with 697 additions and 93 deletions

78
authentik.yaml Normal file
View File

@@ -0,0 +1,78 @@
services:
auth-postgresql:
# env_file:
# - .env
environment:
POSTGRES_DB: authentik
POSTGRES_USER: authentik
POSTGRES_PASSWORD: password
healthcheck:
interval: 30s
retries: 5
start_period: 20s
test:
- CMD-SHELL
- pg_isready -d authentik -U authentik
timeout: 5s
image: docker.io/library/postgres:16-alpine
restart: unless-stopped
volumes:
- database:/var/lib/postgresql/data
networks:
- auth
- mail
authentik:
command: server
depends_on:
auth-postgresql:
condition: service_healthy
env_file:
- /data/authentik/env
- ./authentik.env
environment:
AUTHENTIK_POSTGRESQL__HOST: auth-postgresql
AUTHENTIK_POSTGRESQL__NAME: authentik
AUTHENTIK_POSTGRESQL__USER: authentik
AUTHENTIK_POSTGRESQL__PASSWORD: password
# AUTHENTIK_SECRET_KEY: ${AUTHENTIK_SECRET_KEY:?secret key required}
image: ghcr.io/goauthentik/server:2026.2.2
ports:
- 9000:9000
- 9443:9443
restart: unless-stopped
shm_size: 512mb
volumes:
- /data/authentik/data:/data
- /data/authentik/custom-templates:/templates
networks:
- auth
- mail
auth-worker:
command: worker
depends_on:
auth-postgresql:
condition: service_healthy
env_file:
- /data/authentik/env
- ./authentik.env
environment:
AUTHENTIK_POSTGRESQL__HOST: auth-postgresql
AUTHENTIK_POSTGRESQL__NAME: authentik
AUTHENTIK_POSTGRESQL__USER: authentik
AUTHENTIK_POSTGRESQL__PASSWORD: password
# AUTHENTIK_SECRET_KEY: ${AUTHENTIK_SECRET_KEY:?secret key required}
image: ghcr.io/goauthentik/server:2026.2.2
restart: unless-stopped
shm_size: 512mb
user: root
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- /data/authentik/data:/data
- /data/authentik/certs:/certs
- /data/authentik/custom-templates:/templates
networks:
- auth
- mail
volumes:
database:
driver: local

View File

@@ -3,6 +3,8 @@ include:
- ./jellyfin-compose.yaml
- ./immich-compose.yaml
- ./matrix-compose.yaml
- ./authentik.yaml
- ./recipe-sage.yaml
secrets:
JWT_SECRET:
file: '/data/authelia/secrets/JWT_SECRET'
@@ -61,6 +63,9 @@ networks:
matrix:
external: false
enable_ipv6: true
sage:
external: false
enable_ipv6: true
services:
web:
build:
@@ -85,6 +90,7 @@ services:
- bitwarden
- matrix
- immich
- sage
depends_on:
- jellyfin
- ollama-webui
@@ -94,7 +100,12 @@ services:
- gitea
- gpodder
- memos
- authentik
- matrix-server
- jackett
- sage-static
- sage-api
- sage-pushpin
logging: &logging
options:
max-size: "50m"
@@ -122,44 +133,52 @@ services:
- './authelia/:/config:ro'
- '/data/authelia/:/data'
logging: *logging
minecraft:
image: itzg/minecraft-server:latest
tty: true
stdin_open: true
restart: unless-stopped
ports:
- "25565:25565"
- "24454:24454/udp"
environment:
EULA: "TRUE"
TYPE: "FABRIC"
MEMORY: "4G"
MOTD: "Loading server..."
# VERSION: "1.21.11"
VERSION: "26.1.1"
# LEVEL: "world"
LEVEL: "house"
SEED: "881949285698121329"
# minecraft:
# image: itzg/minecraft-server:latest
# tty: true
# stdin_open: true
# restart: unless-stopped
# ports:
# - "25565:25565"
# - "24454:24454/udp"
# environment:
# EULA: "TRUE"
# TYPE: "FABRIC"
# MEMORY: "16G"
# PAUSE_WHEN_EMPTY_SECONDS: "20"
# USE_MEOWICE_FLAGS: "true"
DIFFICULTY: "normal"
MODE: "survival"
OPS: |-
187eca31-2e33-4199-97e0-2286bf35f7f8
ENABLE_WHITELIST: "true"
WHITELIST: |-
187eca31-2e33-4199-97e0-2286bf35f7f8,
5d341a01-506c-4473-a530-1ae9188c03c7,
34586a37-772e-4da4-86a1-6704f286d4c6,
1ff2724b-168f-4b17-8cf2-850894b34ead
PAUSE_WHEN_EMPTY_SECONDS: "20"
ENABLE_ROLLING_LOGS: "true"
REMOVE_OLD_MODS: "TRUE"
logging: *logging
volumes:
- "/data/minecraft/data:/data"
- "/data/minecraft/mods:/mods"
- "/data/minecraft/plugins:/plugins"
- "/data/minecraft/config:/config"
# USE_MEOWICE_GRAALVM_FLAGS: "true"
# # JVM_OPS: "--add-modules=jdk.incubator.vector -XX:+UseG1GC -XX:+ParallelRefProcEnabled -XX:MaxGCPauseMillis=200 -XX:+UnlockExperimentalVMOptions -XX:+DisableExplicitGC -XX:+AlwaysPreTouch -XX:G1HeapWastePercent=5 -XX:G1MixedGCCountTarget=4 -XX:InitiatingHeapOccupancyPercent=15 -XX:G1MixedGCLiveThresholdPercent=90 -XX:G1RSetUpdatingPauseTimePercent=5 -XX:SurvivorRatio=32 -XX:+PerfDisableSharedMem -XX:MaxTenuringThreshold=1 -Dusing.aikars.flags=https://mcflags.emc.gs -Daikars.new.flags=true -XX:G1NewSizePercent=40 -XX:G1MaxNewSizePercent=50 -XX:G1HeapRegionSize=16M -XX:G1ReservePercent=15"
# SYNC_CHUNK_WRITES: "false"
# SPAWN_PROTECTION: "false"
# ENABLE_ROLLING_LOGS: "true"
# MOTD: "Loading server..."
# # VERSION: "1.21.11"
# VERSION: "26.1.1"
# # LEVEL: "world"
# LEVEL: "house"
# SEED: "881949285698121329"
# DIFFICULTY: "normal"
# MODE: "survival"
# OPS: |-
# 187eca31-2e33-4199-97e0-2286bf35f7f8
# ENABLE_WHITELIST: "true"
# WHITELIST: |-
# 187eca31-2e33-4199-97e0-2286bf35f7f8,
# 5d341a01-506c-4473-a530-1ae9188c03c7,
# 34586a37-772e-4da4-86a1-6704f286d4c6,
# 1ff2724b-168f-4b17-8cf2-850894b34ead
# REMOVE_OLD_MODS: "TRUE"
# logging: *logging
# volumes:
# # - "/data/minecraft/data:/data"
# # - "/data/minecraft/mods:/mods"
# # - "/data/minecraft/plugins:/plugins"
# # - "/data/minecraft/config:/config"
# - "/srv/minecraft/data:/data"
# - "/srv/minecraft/mods:/mods"
# - "/srv/minecraft/plugins:/plugins"
# - "/srv/minecraft/config:/config"
gitea:
image: docker.gitea.com/gitea:1.24
environment:
@@ -239,41 +258,13 @@ services:
- POSTFIX_mydestination=loadingm.xyz,loading-hpdl380g10.loadingm.xyz
- MASQUERADED_DOMAINS=loadingm.xyz,loading-hpdl380g10.loadingm.xyz
- SMTPD_SASL_USERS="a:123,b:123"
- "POSTFIX_mynetworks=0.0.0.0/0,[::0]/0"
volumes:
- /data/mail:/etc/opendkim/keys
networks:
- mail
ports:
- 127.0.0.1:25:25
# mail:
# image: ghcr.io/docker-mailserver/docker-mailserver:latest
# container_name: mailserver
# # Provide the FQDN of your mail server here (Your DNS MX record should point to this value)
# hostname: mail.loadingm.xyz
# env_file: mailserver.env
# # More information about the mail-server ports:
# # https://docker-mailserver.github.io/docker-mailserver/latest/config/security/understanding-the-ports/
# ports:
# - "25:25" # SMTP (explicit TLS => STARTTLS, Authentication is DISABLED => use port 465/587 instead)
# - "143:143" # IMAP4 (explicit TLS => STARTTLS)
# - "465:465" # ESMTP (implicit TLS)
# - "587:587" # ESMTP (explicit TLS => STARTTLS)
# - "993:993" # IMAP4 (implicit TLS)
# volumes:
# - /data/dms/mail-data/:/var/mail/
# - /data/dms/mail-state/:/var/mail-state/
# - /data/dms/mail-logs/:/var/log/mail/
# - /data/dms/config/:/tmp/docker-mailserver/
# - /etc/localtime:/etc/localtime:ro
# restart: always
# stop_grace_period: 1m
# # Uncomment if using `ENABLE_FAIL2BAN=1`:
# # cap_add:
# # - NET_ADMIN
# healthcheck:
# test: "ss --listening --ipv4 --tcp | grep --silent ':smtp' || exit 1"
# timeout: 3s
# retries: 0
bitwarden:
# env_file:
# - bitwarden.env

View File

@@ -77,7 +77,7 @@ container:
# Whether to use privileged mode or not when launching task containers (privileged mode is required for Docker-in-Docker).
privileged: false
# And other options to be used when the container is started (eg, --add-host=my.gitea.url:host-gateway).
options: '-v /data/site:/data/site'
options: '-v /data/site:/data/site -v /var/run/docker.sock:/var/run/docker.sock'
# The parent directory of a job's working directory.
# NOTE: There is no need to add the first '/' of the path as act_runner will add it automatically.
# If the path starts with '/', the '/' will be trimmed.
@@ -100,7 +100,7 @@ container:
# If it's not empty or "-", the specified docker host will be used. An error will be returned if it doesn't work.
docker_host: "-"
# Pull docker image(s) even if already present
force_pull: false
force_pull: true
# Rebuild docker image(s) even if already present
force_rebuild: false
# Always require a reachable docker daemon, even if not required by act_runner

View File

@@ -0,0 +1,295 @@
---
id: 1337x
name: 1337x
description: "1337x is a Public torrent site that offers verified torrent downloads"
language: en-US
type: public
encoding: UTF-8
requestDelay: 3
# get status and news on domains at the official site https://1337x-status.org/
links:
- https://1337x.to/
- https://1337x.st/
- https://x1337x.ws/
- https://x1337x.eu/
- https://x1337x.cc/
legacylinks:
- https://1337x.is/
- https://1337x.gd/
- https://1337x.mrunblock.bond/
- https://1337x.abcproxy.org/
- https://1337x.so/
- https://1337x.unblockit.download/
- https://1337x.unblockninja.com/ # keyword search not working
- https://1337x.ninjaproxy1.com/ # keyword search not working
- https://1337x.proxyninja.org/ # keyword search not working
- https://1337x.proxyninja.net/ # keyword search not working
- https://1337x.torrentbay.st/ # keyword search not working
- https://1337x.torrentsbay.org/ # keyword search not working
- https://x1337x.se/
caps:
categorymappings:
# Anime
- {id: 28, cat: TV/Anime, desc: "Anime/Anime"}
- {id: 78, cat: TV/Anime, desc: "Anime/Dual Audio"}
- {id: 79, cat: TV/Anime, desc: "Anime/Dubbed"}
- {id: 80, cat: TV/Anime, desc: "Anime/Subbed"}
- {id: 81, cat: TV/Anime, desc: "Anime/Raw"}
# Audio
- {id: 22, cat: Audio/MP3, desc: "Music/MP3"}
- {id: 23, cat: Audio/Lossless, desc: "Music/Lossless"}
- {id: 24, cat: Audio, desc: "Music/DVD"}
- {id: 25, cat: Audio/Video, desc: "Music/Video"}
- {id: 26, cat: Audio, desc: "Music/Radio"}
- {id: 27, cat: Audio/Other, desc: "Music/Other"}
- {id: 53, cat: Audio, desc: "Music/Album"}
- {id: 58, cat: Audio, desc: "Music/Box set"}
- {id: 59, cat: Audio, desc: "Music/Discography"}
- {id: 60, cat: Audio, desc: "Music/Single"}
- {id: 68, cat: Audio, desc: "Music/Concerts"}
- {id: 69, cat: Audio, desc: "Music/AAC"}
# Movies
- {id: 1, cat: Movies/DVD, desc: "Movies/DVD"}
- {id: 2, cat: Movies/SD, desc: "Movies/Divx/Xvid"}
- {id: 3, cat: Movies, desc: "Movies/SVCD/VCD"}
- {id: 4, cat: Movies/Foreign, desc: "Movies/Dubs/Dual Audio"}
- {id: 42, cat: Movies/HD, desc: "Movies/HD"}
- {id: 54, cat: Movies/HD, desc: "Movies/h.264/x264"}
- {id: 55, cat: Movies, desc: "Movies/Mp4"}
- {id: 66, cat: Movies/3D, desc: "Movies/3D"}
- {id: 70, cat: Movies/HD, desc: "Movies/HEVC/x265"}
- {id: 73, cat: Movies, desc: "Movies/Bollywood"}
- {id: 76, cat: Movies/UHD, desc: "Movies/UHD"}
# TV
- {id: 5, cat: TV, desc: "TV/DVD"}
- {id: 6, cat: TV, desc: "TV/Divx/Xvid"}
- {id: 7, cat: TV, desc: "TV/SVCD/VCD"}
- {id: 41, cat: TV/HD, desc: "TV/HD"}
- {id: 71, cat: TV, desc: "TV/HEVC/x265"}
- {id: 74, cat: TV, desc: "TV/Cartoons"}
- {id: 75, cat: TV/SD, desc: "TV/SD"}
- {id: 9, cat: TV/Documentary, desc: "TV/Documentary"}
# Apps
- {id: 18, cat: PC, desc: "Apps/PC Software"}
- {id: 19, cat: PC/Mac, desc: "Apps/Mac"}
- {id: 20, cat: PC, desc: "Apps/Linux"}
- {id: 21, cat: PC, desc: "Apps/Other"}
- {id: 56, cat: PC/Mobile-Android, desc: "Apps/Android"}
- {id: 57, cat: PC/Mobile-iOS, desc: "Apps/iOS"}
# Games
- {id: 10, cat: PC/Games, desc: "Games/PC Game"}
- {id: 11, cat: Console/PS3, desc: "Games/PS2"}
- {id: 12, cat: Console/PSP, desc: "Games/PSP"}
- {id: 13, cat: Console/XBox, desc: "Games/Xbox"}
- {id: 14, cat: Console/XBox 360, desc: "Games/Xbox360"}
- {id: 15, cat: Console/PS3, desc: "Games/PS1"}
- {id: 16, cat: Console/Other, desc: "Games/Dreamcast"}
- {id: 17, cat: PC/Mobile-Other, desc: "Games/Other"}
- {id: 43, cat: Console/PS3, desc: "Games/PS3"}
- {id: 44, cat: Console/Wii, desc: "Games/Wii"}
- {id: 45, cat: Console/NDS, desc: "Games/DS"}
- {id: 46, cat: Console/Other, desc: "Games/GameCube"}
- {id: 72, cat: Console/3DS, desc: "Games/3DS"}
- {id: 77, cat: Console/PS4, desc: "Games/PS4"}
- {id: 82, cat: Console/Other, desc: "Games/Switch"}
# XXX
- {id: 48, cat: XXX/DVD, desc: "XXX/Video"}
- {id: 49, cat: XXX/ImageSet, desc: "XXX/Picture"}
- {id: 50, cat: XXX, desc: "XXX/Magazine"}
- {id: 51, cat: XXX, desc: "XXX/Hentai"}
- {id: 67, cat: XXX, desc: "XXX/Games"}
# Other
- {id: 33, cat: Other, desc: "Other/Emulation"}
- {id: 34, cat: Books, desc: "Other/Tutorial"}
- {id: 35, cat: Other, desc: "Other/Sounds"}
- {id: 36, cat: Books/EBook, desc: "Other/E-books"}
- {id: 37, cat: Other, desc: "Other/Images"}
- {id: 38, cat: Other, desc: "Other/Mobile Phone"}
- {id: 39, cat: Books/Comics, desc: "Other/Comics"}
- {id: 40, cat: Other/Misc, desc: "Other/Other"}
- {id: 47, cat: Other, desc: "Other/Nulled Script"}
- {id: 52, cat: Audio/Audiobook, desc: "Other/Audiobook"}
modes:
search: [q]
tv-search: [q, season, ep]
movie-search: [q]
music-search: [q]
book-search: [q]
allowrawsearch: true
settings:
- name: uploader
type: text
label: Filter by Uploader
- name: info_uploader
type: info
label: About filtering by Uploader
default: "You can filter by Uploader by entering a Case Sensitive username, or leave empty to get all results.<br>Note: this is the username of the Uploader and not the Groupname that often show up at the end of 1337x titles, eg -GalaxyRG."
- name: info_flaresolverr
type: info_flaresolverr
- name: downloadlink
type: select
label: Download link
default: "http://itorrents.org/"
options:
"http://itorrents.org/": iTorrents.org
"magnet:": magnet
- name: downloadlink2
type: select
label: Download link (fallback)
default: "magnet:"
options:
"http://itorrents.org/": iTorrents.org
"magnet:": magnet
- name: info_download
type: info
label: About the Download links
default: As the iTorrents .torrent download link on this site is known to fail from time to time, we suggest using the magnet link as a fallback. The BTCache and Torrage services are not supported because they require additional user interaction (a captcha for BTCache and a download button on Torrage.)
- name: disablesort
type: checkbox
label: Disable sorting - 1337x prevents sorting searches during high server load, which breaks the indexer when performing a keyword search - disable if you get zero results
default: false
- name: sort
type: select
label: Sort requested from site
default: time
options:
time: created
seeders: seeders
size: size
- name: type
type: select
label: Order requested from site
default: desc
options:
desc: desc
asc: asc
download:
# the .torrent URL and magnet URI are on the details page
selectors:
- selector: ul li a[href^="{{ .Config.downloadlink }}"]
attribute: href
- selector: ul li a[href^="{{ .Config.downloadlink2 }}"]
attribute: href
search:
paths:
# present first page of movies tv and music results if there are no search parms supplied (20 hits per page)
- path: "{{ if and (.Keywords) (eq .Config.disablesort .False) }}sort-{{ else }}{{ end }}{{ if .Keywords }}search/{{ .Keywords }}{{ else }}cat/Movies{{ end }}{{ if and (.Keywords) (eq .Config.disablesort .False) }}/{{ .Config.sort }}/{{ .Config.type }}{{ else }}{{ end }}/1/"
- path: "{{ if and (.Keywords) (eq .Config.disablesort .False) }}sort-{{ else }}{{ end }}{{ if .Keywords }}search/{{ .Keywords }}{{ else }}cat/TV{{ end }}{{ if and (.Keywords) (eq .Config.disablesort .False)) }}/{{ .Config.sort }}/{{ .Config.type }}{{ else }}{{ end }}/{{ if .Keywords }}2{{ else }}1{{ end }}/"
- path: "{{ if and (.Keywords) (eq .Config.disablesort .False) }}sort-{{ else }}{{ end }}{{ if .Keywords }}search/{{ .Keywords }}{{ else }}cat/Music{{ end }}{{ if and (.Keywords) (eq .Config.disablesort .False) }}/{{ .Config.sort }}/{{ .Config.type }}{{ else }}{{ end }}/{{ if .Keywords }}3{{ else }}1{{ end }}/"
- path: "{{ if and (.Keywords) (eq .Config.disablesort .False) }}sort-{{ else }}{{ end }}{{ if .Keywords }}search/{{ .Keywords }}{{ else }}cat/Other{{ end }}{{ if and (.Keywords) (eq .Config.disablesort .False) }}/{{ .Config.sort }}/{{ .Config.type }}{{ else }}{{ end }}/{{ if .Keywords }}4{{ else }}1{{ end }}/"
keywordsfilters:
- name: re_replace # daily standard S2023 > 2023
args: ["\\bS(20\\d{2})\\b", "$1"]
rows:
selector: "tr:has(a[href^=\"/torrent/\"]){{ if .Config.uploader }}:has(td[class^=\"coll-5\"]:contains({{ .Config.uploader }})){{ else }}{{ end }}"
fields:
title_default:
# the movies, tv and music pages abbreviate the title
selector: td[class^="coll-1"] a[href^="/torrent/"]
title_optional:
# the movies, tv and music pages abbreviate the title so we process the href instead. #8137
optional: true
selector: td[class^="coll-1"] a[href^="/torrent/"]:contains("...")
attribute: href
filters:
- name: urldecode
- name: split
args: ["/", 3]
title:
# title_optional can be empty so use the title_default instead #8586
text: "{{ if .Result.title_optional }}{{ .Result.title_optional }}{{ else }}{{ .Result.title_default }}{{ end }}"
filters:
- name: re_replace
args: ["-([\\w]+(?:[\\[\\]\\(\\)\\w]+)?)$", "~$1"]
- name: replace
args: ["-", " "]
- name: re_replace
args: ["~([\\w]+(?:[\\[\\]\\(\\)\\w]+)?)$", "-$1"]
- name: replace
args: ["\u000f", ""] # get rid of unwanted character #6582
# cleanup for Sonarr
- name: re_replace # EP 3 4 to E3-4
args: ["(?i)\\sEP\\s(\\d{1,2})\\s(E?\\s?\\d{1,2})\\s", " E$1-$2 "]
- name: re_replace # S02E04 05 to S02E04-05
args: ["(?i)([-_. ])S(\\d{1,2})\\s?E\\s?(\\d{1,2})\\s(E?\\s?\\d{1,2})([-_. ])", "$1S$2E$3-$4$5"]
- name: re_replace
args: ["(?i)AC3\\s?(\\d)\\s(\\d)", "AC3 $1.$2"]
- name: re_replace
args: ["(?i) DD\\s?(\\d)\\s(\\d)", " DD $1.$2"]
- name: re_replace
args: ["(?i) DDP\\s?(\\d)\\s(\\d)", " DDP $1.$2"]
- name: re_replace
args: ["(?i)\\sE\\s?AC3", " EAC3"]
- name: re_replace
args: ["(?i)WEB\\sDL", "WEB-DL"]
- name: re_replace
args: ["(?i)HDTVRIP", "HDTV"]
category_optional:
optional: true
selector: td[class^="coll-1"] a[href^="/sub/"]
attribute: href
filters:
# extract the third part
- name: split
args: ["/", 2]
category:
text: "{{ if .Result.category_optional }}{{ .Result.category_optional }}{{ else }}40{{ end }}"
details:
selector: td[class^="coll-1"] a[href^="/torrent/"]
attribute: href
download:
# .torrent link is on the details page
selector: td[class^="coll-1"] a[href^="/torrent/"]
attribute: href
# dates come in three flavours:
date_year:
# (within this year) 7am Sep. 14th
optional: true
selector: td[class^="coll-date"]:not(:contains(":")):not(:contains("'"))
filters:
- name: re_replace
args: ["st|nd|rd|th", ""]
- name: dateparse
args: "htt MMM. d"
date_years:
# (more than a year ago) Apr. 18th '11
optional: true
selector: td[class^="coll-date"]:contains("'")
filters:
- name: replace
args: ["'", ""]
- name: re_replace
args: ["st|nd|rd|th", ""]
- name: dateparse
args: "MMM. d yy"
date_today:
# (today) 12:25am
optional: true
selector: td[class^="coll-date"]:contains(":")
filters:
- name: fuzzytime
date:
text: "{{ if or .Result.date_year .Result.date_years .Result.date_today }}{{ or .Result.date_year .Result.date_years .Result.date_today }}{{ else }}now{{ end }}"
size:
selector: td[class^="coll-4"]
seeders:
selector: td[class^="coll-2"]
leechers:
selector: td[class^="coll-3"]
_username:
selector: td[class^="coll-5"]
description:
text: "Uploader: {{ .Result._username }}"
downloadvolumefactor:
text: 0
uploadvolumefactor:
text: 1
# engine n/a

View File

@@ -4,11 +4,14 @@ services:
cap_add:
- NET_ADMIN
ports:
# - 8000:8000
- 8080:8080
- 51820:51820
- 51820:51820/udp
- 46931:46931
- 46931:46931/udp
# - 8191:8191 # Flaresolverr
# - 9117:9117 # Jackett
networks:
- jellyfin-int
env_file: .vpnenv
@@ -32,9 +35,24 @@ services:
volumes:
- /data/jellyfin:/data/jellyfin
- /data/jellyfin/gluetun:/tmp/gluetun
qbittorrent:
image: lscr.io/linuxserver/qbittorrent:latest
socks5:
image: serjs/go-socks5-proxy
restart: unless-stopped
network_mode: service:gluetun
environment:
- REQUIRE_AUTH=false
depends_on:
- gluetun
qbittorrent:
# Previously was latest, trying older version since newest isn't working?
image: lscr.io/linuxserver/qbittorrent:5.1.4
network_mode: service:gluetun
# ports:
# - 8080:8080
# - 6881:6881
# - 6881:6881/udp
# networks:
# - jellyfin-int
environment:
- WEBUI_PORT=8080
- PUID=0
@@ -45,17 +63,18 @@ services:
- /data/jellyfin:/data/jellyfin
- /data/jellyfin/configs/qbittorrent:/config
# - /data/jellyfin/qbittorrent/downloads:/data/jellyfin/qbittorrent/downloads
# ports:
# - 8080:8080
# - 6881:6881
# - 6881:6881/udp
# networks:
# - jellyfin-int
depends_on:
- gluetun
restart: unless-stopped
flaresolverr:
image: ghcr.io/flaresolverr/flaresolverr:latest
network_mode: service:gluetun
depends_on:
- gluetun
# networks:
# - jellyfin-int
# ports:
# - 8191:8191
environment:
- LOG_LEVEL=${LOG_LEVEL:-info}
- LOG_HTML=${LOG_HTML:-false}
@@ -65,10 +84,6 @@ services:
#- LANG=en_US
# volumes:
# - /tmp/flaresolver:/tmp
ports:
- 8191:8191
networks:
- jellyfin-int
restart: unless-stopped
prowlarr:
image: lscr.io/linuxserver/prowlarr:latest
@@ -85,6 +100,14 @@ services:
restart: unless-stopped
jackett:
image: lscr.io/linuxserver/jackett:latest
network_mode: service:gluetun
depends_on:
- socks5
- flaresolverr
# networks:
# - jellyfin-int
# ports:
# - 9117:9117
environment:
- PUID=0
- PGID=0
@@ -92,10 +115,6 @@ services:
# - RUN_OPTS=-l -t
volumes:
- /data/jellyfin/configs/jackett:/config
ports:
- 9117:9117
networks:
- jellyfin-int
restart: unless-stopped
sonarr:
image: lscr.io/linuxserver/sonarr:latest
@@ -130,7 +149,8 @@ services:
- jellyfin-int
restart: unless-stopped
jellyfin:
image: lscr.io/linuxserver/jellyfin:latest
image: ghcr.io/jellyfin/jellyfin:latest
# image: lscr.io/linuxserver/jellyfin:latest
environment:
- PUID=0
- PGID=0

View File

@@ -0,0 +1,49 @@
# Upgrade WebSocket if requested, otherwise use keepalive
map $http_upgrade $connection_upgrade_keepalive {
default upgrade;
'' '';
}
server {
# Nginx versions 1.25+
listen 443 ssl;
listen [::]:443 ssl;
http2 on;
server_name authentik.loadingm.xyz;
acme_certificate letsencrypt;
ssl_certificate $acme_certificate;
ssl_certificate_key $acme_certificate_key;
ssl_certificate_cache max=2;
## The default `client_max_body_size` is 1M, this might not be enough for some posters, etc.
client_max_body_size 20M;
# Security / XSS Mitigation Headers
add_header X-Content-Type-Options "nosniff";
# Permissions policy. May cause issues with some clients
add_header Permissions-Policy "accelerometer=(), ambient-light-sensor=(), battery=(), bluetooth=(), camera=(), clipboard-read=(), display-capture=(), document-domain=(), encrypted-media=(), gamepad=(), geolocation=(), gyroscope=(), hid=(), idle-detection=(), interest-cohort=(), keyboard-map=(), local-fonts=(), magnetometer=(), microphone=(), payment=(), publickey-credentials-get=(), serial=(), sync-xhr=(), usb=(), xr-spatial-tracking=()" always;
# Content Security Policy
# See: https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP
# Enforces https content and restricts JS/CSS to origin
# External Javascript (such as cast_sender.js for Chromecast) must be whitelisted.
add_header Content-Security-Policy "default-src https: data: blob: ; img-src 'self' https://* ; style-src 'self' 'unsafe-inline'; script-src 'self' 'unsafe-inline' https://www.gstatic.com https://www.youtube.com blob:; worker-src 'self' blob:; connect-src 'self'; object-src 'none'; frame-ancestors 'self'; font-src 'self'";
location / {
# Proxy main karakeep traffic
proxy_pass http://authentik:9000;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Protocol $scheme;
proxy_set_header X-Forwarded-Host $http_host;
proxy_set_header Host $http_host;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade_keepalive;
# Disable buffering when the nginx proxy gets very resource heavy upon streaming
proxy_buffering off;
}
}

View File

@@ -16,12 +16,6 @@ server {
# Permissions policy. May cause issues with some clients
add_header Permissions-Policy "accelerometer=(), ambient-light-sensor=(), battery=(), bluetooth=(), camera=(), clipboard-read=(), display-capture=(), document-domain=(), encrypted-media=(), gamepad=(), geolocation=(), gyroscope=(), hid=(), idle-detection=(), interest-cohort=(), keyboard-map=(), local-fonts=(), magnetometer=(), microphone=(), payment=(), publickey-credentials-get=(), serial=(), sync-xhr=(), usb=(), xr-spatial-tracking=()" always;
# Content Security Policy
# See: https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP
# Enforces https content and restricts JS/CSS to origin
# External Javascript (such as cast_sender.js for Chromecast) must be whitelisted.
add_header Content-Security-Policy "default-src https: data: blob: ; img-src 'self' https://* ; style-src 'self' 'unsafe-inline'; script-src 'self' 'unsafe-inline' https://www.gstatic.com https://www.youtube.com blob:; worker-src 'self' blob:; connect-src 'self'; object-src 'none'; frame-ancestors 'self'; font-src 'self'";
location / {
# Proxy main karakeep traffic
proxy_pass http://gpodder:8000;

46
nginx/sites-enabled/sage Normal file
View File

@@ -0,0 +1,46 @@
server {
# Nginx versions 1.25+
listen 443 ssl;
listen [::]:443 ssl;
http2 on;
server_name sage.loadingm.xyz;
acme_certificate letsencrypt;
ssl_certificate $acme_certificate;
ssl_certificate_key $acme_certificate_key;
ssl_certificate_cache max=2;
## The default `client_max_body_size` is 1M, this might not be enough for some posters, etc.
client_max_body_size 200G;
# Security / XSS Mitigation Headers
add_header X-Content-Type-Options "nosniff";
# Permissions policy. May cause issues with some clients
add_header Permissions-Policy "accelerometer=(), ambient-light-sensor=(), battery=(), bluetooth=(), camera=(), clipboard-read=(), display-capture=(), document-domain=(), encrypted-media=(), gamepad=(), geolocation=(), gyroscope=(), hid=(), idle-detection=(), interest-cohort=(), keyboard-map=(), local-fonts=(), magnetometer=(), microphone=(), payment=(), publickey-credentials-get=(), serial=(), sync-xhr=(), usb=(), xr-spatial-tracking=()" always;
location /grip/ws {
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_connect_timeout 1h;
proxy_send_timeout 1h;
proxy_read_timeout 1h;
proxy_pass http://sage-pushpin:7999/ws;
}
# Alias minio in case minio container is not present
set $minio http://sage-minio:9000;
location /minio/ {
rewrite ^/minio/(.*)$ /$1 break;
proxy_pass $minio;
}
location /api/ {
proxy_pass http://sage-api:3000/;
}
location / {
proxy_pass http://sage-static:80/;
}
}

View File

@@ -65,7 +65,8 @@ server {
location ^~ /jackett/ {
include /etc/nginx/snippets/authelia-authrequest.conf;
add_header Content-Security-Policy "default-src https: data: blob: ; img-src 'self' https://* ; style-src 'self' 'unsafe-inline'; script-src 'self' 'unsafe-inline' 'unsafe-eval' https://www.gstatic.com https://www.youtube.com blob:; worker-src 'self' blob:; connect-src 'self'; object-src 'none'; frame-ancestors 'self'; font-src 'self'";
proxy_pass http://jackett:9117;
# proxy_pass http://jackett:9117;
proxy_pass http://gluetun:9117;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $host;

130
recipe-sage.yaml Normal file
View File

@@ -0,0 +1,130 @@
# This config file is for RecipeSage-selfhost config version 4.3.1, and RecipeSage version 3.0.10.
services:
# sage-proxy: # The proxy must not be removed. If needed, point your own proxy to this container, rather than removing this
# # container_name: recipesage_proxy
# image: julianpoy/recipesage-selfhost-proxy:v4.0.0
# ports:
# - 7270:80
# depends_on:
# - sage-static
# - sage-api
# - sage-pushpin
# restart: unless-stopped
sage-static: # Hosts frontend assets
# container_name: recipesage_static
image: julianpoy/recipesage-selfhost:static-v3.0.10
restart: unless-stopped
networks:
- sage
sage-api: # Hosts backend API
# container_name: recipesage_api
image: julianpoy/recipesage-selfhost:api-v3.0.10
depends_on:
sage-postgres:
condition: service_healthy
sage-typesense:
condition: service_started
sage-pushpin:
condition: service_started
sage-browserless:
condition: service_started
networks:
- sage
- ollama-int
command: sh -c "npx prisma migrate deploy; npx nx seed prisma; npx ts-node --swc --project packages/backend/tsconfig.json packages/backend/src/bin/www"
environment:
- STORAGE_TYPE=filesystem
- FILESYSTEM_STORAGE_PATH=/rs-media
- NODE_ENV=selfhost
- VERBOSE=false
- VERSION=selfhost
- POSTGRES_DB=recipesage_selfhost # If changing this, make sure to update the postgres container and the DATABASE_URL below accordingly
- POSTGRES_USER=recipesage_selfhost # If changing this, make sure to update the postgres container and the DATABASE_URL below accordingly
- POSTGRES_PASSWORD=recipesage_selfhost # If changing this, make sure to update the postgres container and the DATABASE_URL below accordingly
- POSTGRES_PORT=5432 # If changing this, make sure to update the postgres container and the DATABASE_URL below accordingly
- POSTGRES_HOST=sage-postgres # If changing this, make sure to update the postgres container and the DATABASE_URL below accordingly
- POSTGRES_SSL=false
- POSTGRES_LOGGING=false
- DATABASE_URL=postgresql://recipesage_selfhost:recipesage_selfhost@sage-postgres:5432/recipesage_selfhost # Format is: postgresql://USERNAME:PASSWORD@HOST:PORT/DBNAME and must match the variables from the postgres container if you decide to change them
- GCM_KEYPAIR
- SENTRY_DSN
- GRIP_URL=http://sage-pushpin:5561/
- GRIP_KEY=changeme
- SEARCH_PROVIDER=typesense
- 'TYPESENSE_NODES=[{"host": "sage-typesense", "port": 8108, "protocol": "http"}]'
- TYPESENSE_API_KEY=recipesage_selfhost
- STRIPE_SK # Value should not be set.
- STRIPE_WEBHOOK_SECRET # Value should not be set
- BROWSERLESS_HOST=sage-browserless
- BROWSERLESS_PORT=3000
- BROWSERLESS_TOKEN=
- INGREDIENT_INSTRUCTION_CLASSIFIER_URL=http://sage-ingredient-instruction-classifier:3000/
- OPENAI_API_KEY=ollama # Please follow the instructions in the README if you decide to supply a value here
- OPENAI_API_BASE_URL=http://ollama:11434/v1/
volumes:
- /srv/sage/apimedia:/rs-media
restart: unless-stopped
sage-typesense: # Provides the fuzzy search engine
# container_name: recipesage_typesense
image: typesense/typesense:0.24.1
networks:
- sage
volumes:
- /srv/sage/typesensedata:/data
command: "--data-dir /data --api-key=recipesage_selfhost --enable-cors"
restart: unless-stopped
sage-pushpin: # Provides websocket support
# container_name: recipesage_pushpin
image: julianpoy/pushpin:2023-09-17
networks:
- sage
entrypoint: /bin/sh -c
command:
[
'sed -i "s/sig_key=changeme/sig_key=$$GRIP_KEY/" /etc/pushpin/pushpin.conf && echo "* $${TARGET},over_http" > /etc/pushpin/routes && pushpin --merge-output',
]
environment:
- GRIP_KEY=changeme
- TARGET=api:3000
restart: unless-stopped
sage-postgres: # Database
# container_name: recipesage_postgres
image: postgres:16
networks:
- sage
environment:
- POSTGRES_DB=recipesage_selfhost # If you change this, make sure to change both POSTGRES_DB and DATABASE_URL on the API container
- POSTGRES_USER=recipesage_selfhost # If you change this, make sure to change both POSTGRES_USER and DATABASE_URL on the API container
- POSTGRES_PASSWORD=recipesage_selfhost # If you change this, make sure to change both POSTGRES_PASSWORD and DATABASE_URL on the API container
- PGUSER=recipesage_selfhost # Change to db user
volumes:
- /srv/sage/postgresdata:/var/lib/postgresql/data
restart: unless-stopped
healthcheck:
test: ["CMD-SHELL", "pg_isready", "-d", "db_prod", "-U", "recipesage_selfhost"] # Change to db user
interval: 5s
timeout: 5s
retries: 5
start_period: 10s
sage-browserless: # A headless browser for scraping websites with the auto import tool
# container_name: recipesage_browserless
image: ghcr.io/browserless/chromium:v2.24.3
networks:
- sage
environment:
- MAX_CONCURRENT_SESSIONS=3
- MAX_QUEUE_LENGTH=10
restart: unless-stopped
# Uncomment the lines below to enable the ingredient instruction classifier. It's somewhat resource intensive (and large) and requires AVX instruction support on your CPU, but does improve site compatibility for the automatic import tool.
sage-ingredient-instruction-classifier: # An _optional_ server that runs a machine learning model able to classify text for improved automatic import site support. Not required for application to run, and will crash if your CPU does not support AVX instructions
# container_name: recipesage_classifier
image: julianpoy/ingredient-instruction-classifier:1.4.11
networks:
- sage
environment:
- SENTENCE_EMBEDDING_BATCH_SIZE=200
- PREDICTION_CONCURRENCY=2
restart: unless-stopped