Compare commits

..

1 Commits

Author SHA1 Message Date
62b2c11d58 Pull latest changes from main before redeploying
Some checks failed
Deploy homelab / Deploy (push) Has been cancelled
2025-09-02 23:33:39 -05:00
38 changed files with 336 additions and 1684 deletions

View File

@@ -1,28 +0,0 @@
name: "Build certificates"
on:
workflow_dispatch:
inputs:
# Note: this doesn't work on current gitea for some reason?
build_certs:
description: "Build certificates from scratch"
type: "boolean"
required: true
default: false
schedule: "@weekly"
env:
TZ: "America/Chicago"
jobs:
deploy:
name: "Setup/Renew certificates"
runs-on: "homelab"
steps:
- name: "Build certificates"
if: inputs.build_certs
run: |
cd /home/matthew/homelab
bash ./build-certs.sh
- name: "Renew certificates"
run: |
cd /home/matthew/homelab
docker compose run --rm certbot renew
docker restart homelab-web-1

View File

@@ -10,12 +10,8 @@ jobs:
name: Deploy
runs-on: homelab
steps:
- name: "Pull latest code"
run: |
- run: |
cd /home/matthew/homelab
git checkout main
git pull
- name: "Deploy containers"
run: |
cd /home/matthew/homelab
docker compose up -d --remove-orphans

1
.gitignore vendored
View File

@@ -1,5 +1,4 @@
.env
*.env
authelia/secrets/
authelia/notification.txt
authelia/db.sqlite3

25
.vpnenv
View File

@@ -1,25 +0,0 @@
TZ=America/Menominee
# # Probably US-IL#152
# VPN_ENDPOINT_IP=87.249.134.138
# VPN_ENDPOINT_PORT=51820
# WIREGUARD_ADDRESSES=10.2.0.2/32
# VPN_DNS_ADDRESS=10.2.0.1
# WIREGUARD_PUBLIC_KEY=WNLAmQkeAvdg9QRFMXq7EuwpEWWkltWwiS/DGIcjHjs=
# WIREGUARD_PRIVATE_KEY=MEvccGuRDyqlbpMdqUlCdGwlAD/LD4iTvx+6LG/0/0k=
# US-IL#156
VPN_ENDPOINT_IP=87.249.134.139
VPN_ENDPOINT_PORT=51820
WIREGUARD_ADDRESSES=10.2.0.2/32
VPN_DNS_ADDRESS=10.2.0.1
WIREGUARD_PUBLIC_KEY=xuqP9uEGryELhamLSK9IDRNhljo3lA1zL9/gS7yj2WQ=
WIREGUARD_PRIVATE_KEY=wHp5gAjV9qznCbk702bq/Az/qXrnb8PKMiNhWQ5mw2I=
# # US-IL#156
# VPN_ENDPOINT_IP=87.249.134.139
# VPN_ENDPOINT_PORT=51820
# WIREGUARD_ADDRESSES=10.2.0.2/32
# VPN_DNS_ADDRESS=10.2.0.1
# WIREGUARD_PUBLIC_KEY=xuqP9uEGryELhamLSK9IDRNhljo3lA1zL9/gS7yj2WQ=
# WIREGUARD_PRIVATE_KEY=wHp5gAjV9qznCbk702bq/Az/qXrnb8PKMiNhWQ5mw2I=

View File

@@ -1,45 +0,0 @@
# My personal homelab setup
Currently running on a Debian host
## Raw data
Raw data is stored in `/data`, a ZFS data set
```bash
# Install ZFS
apt update
apt install linux-headers-amd64
apt install zfsutils-linux zfs-dkms
zpool create hdd raidz2 <disks...>
mkdir -p /data
zfs create -o mountpoint=/data hdd/data
zfs set compression=on hdd/data
```
## act_runner
```bash
pushd /tmp
wget https://gitea.com/gitea/act_runner/releases/download/v0.2.13/act_runner-0.2.13-linux-amd64.xz
xz -d act_runner-0.2.13-linux-amd64.xz
mv act_runner-0.2.13-linux-amd64 /usr/bin/act_runner
chmod +x /usr/bin/act_runner
mkdir /home/matthew/act_runner
```
## Systemd
```bash
# Add services
ln -s $PWD/*.service /etc/systemd/system/
systemctl enable homelab
systemctl start homelab
cd ~/act_runner
/usr/bin/act_runner register --config /home/matthew/homelab/host-runner.yaml
systemctl enable act_runner
systemctl start act_runner
```

View File

@@ -1,16 +0,0 @@
[Unit]
Description=Gitea Actions runner
Documentation=https://gitea.com/gitea/act_runner
After=docker.service
[Service]
ExecStart=/usr/bin/act_runner daemon --config /home/matthew/homelab/host-runner.yaml
ExecReload=/bin/kill -s HUP $MAINPID
WorkingDirectory=/home/matthew/act_runner
TimeoutSec=0
RestartSec=10
Restart=always
User=matthew
[Install]
WantedBy=multi-user.target

View File

@@ -6,7 +6,7 @@ authentication_backend:
password_change:
disable: false
file:
path: '/data/users.yml'
path: '/config/users.yml'
watch: false
search:
email: false
@@ -37,72 +37,18 @@ session:
remember_me: '1d'
notifier:
disable_startup_check: false
# filesystem:
# filename: '/data/notification.txt'
smtp:
address: 'smtp://mail:25'
sender: 'Authelia <auth@loadingm.xyz>'
disable_require_tls: true # Determine if this is needed
disable_starttls: true
filesystem:
filename: '/config/notification.txt'
storage:
local:
path: '/data/db.sqlite3'
path: '/config/db.sqlite3'
access_control:
default_policy: deny
rules:
- domain: 'servarr.loadingm.xyz'
subject:
- 'group:admin'
- domain: '*.loadingm.xyz'
policy: one_factor
# - domain: '*.loadingm.xyz'
# policy: one_factor
server:
endpoints:
authz:
auth-request:
implementation: 'AuthRequest'
identity_providers:
oidc:
# enable_client_debug_messages: false
# minimum_parameter_entropy: 8
# enforce_pkce: 'public_clients_only'
# enable_pkce_plain_challenge: false
# enable_jwt_access_token_stateless_introspection: false
# discovery_signed_response_alg: 'none'
# discovery_signed_response_key_id: ''
# require_pushed_authorization_requests: false
# authorization_policies:
# policy_name:
# default_policy: 'two_factor'
# rules:
# - policy: 'deny'
# subject: 'group:services'
# networks:
# - '192.168.1.0/24'
# - '192.168.2.51'
lifespans:
access_token: '1h'
authorize_code: '1m'
id_token: '1h'
refresh_token: '90m'
# claims_policies:
# policy_name:
# id_token: []
# access_token: []
# id_token_audience_mode: 'specification'
# custom_claims:
# claim_name:
# name: 'claim_name'
# attribute: 'attribute_name'
# scopes:
# scope_name:
# claims: []
# cors:
# endpoints:
# - 'authorization'
# - 'token'
# - 'revocation'
# - 'introspection'
# allowed_origins:
# - 'https://example.com'
# allowed_origins_from_client_redirect_uris: false

View File

@@ -1,139 +0,0 @@
# au rand() {
# docker run --rm authelia/authelia:latest authelia crypto rand --length $1 --charset rfc3986
# }
# au hash() {
# docker run --rm authelia/authelia:latest authelia crypto hash generate pbkdf2 --variant sha512 --random --random.length $1 --random.charset rfc3986
# }
identity_providers:
oidc:
hmac_secret: '$(au rand 72)'
jwks:
- key: $(openssl genrsa -out - 2048)
claims_policies:
karakeep:
id_token: ['email']
## The other portions of the mandatory OpenID Connect 1.0 configuration go here.
## See: https://www.authelia.com/c/oidc
clients:
- client_name: 'Gitea'
client_id: '$(au rand 72)'
client_secret: '$(au hash 72)'
public: false
authorization_policy: 'two_factor'
require_pkce: false
pkce_challenge_method: ''
redirect_uris:
- 'https://gitea.loadingm.xyz/user/oauth2/authelia/callback'
scopes:
- 'openid'
- 'email'
- 'profile'
response_types:
- 'code'
grant_types:
- 'authorization_code'
access_token_signed_response_alg: 'none'
userinfo_signed_response_alg: 'none'
token_endpoint_auth_method: 'client_secret_basic'
- client_name: 'Memos'
client_id: '$(au rand 72)'
client_secret: '$(au hash 72)'
public: false
authorization_policy: 'two_factor'
require_pkce: false
pkce_challenge_method: ''
redirect_uris:
- 'https://memos.loadingm.xyz/auth/callback'
scopes:
- 'openid'
- 'email'
- 'profile'
response_types:
- 'code'
grant_types:
- 'authorization_code'
access_token_signed_response_alg: 'none'
userinfo_signed_response_alg: 'none'
token_endpoint_auth_method: 'client_secret_basic'
- client_name: 'Open WebUI'
client_id: '$(au rand 72)'
client_secret: '$(au hash 72)'
public: false
authorization_policy: 'two_factor'
require_pkce: false
pkce_challenge_method: ''
redirect_uris:
- 'https://ollama.loadingm.xyz/oauth/oidc/callback'
scopes:
- 'openid'
- 'email'
- 'groups'
- 'profile'
response_types:
- 'code'
grant_types:
- 'authorization_code'
access_token_signed_response_alg: 'none'
userinfo_signed_response_alg: 'none'
token_endpoint_auth_method: 'client_secret_basic'
- client_name: 'Karakeep'
client_id: '$(au rand 72)'
client_secret: '$(au hash 72)'
public: false
authorization_policy: 'two_factor'
require_pkce: false
pkce_challenge_method: ''
redirect_uris:
- 'https://karakeep.loadingm.xyz/api/auth/callback/custom'
scopes:
- 'openid'
- 'email'
- 'profile'
claims_policy: 'karakeep'
response_types:
- 'code'
grant_types:
- 'authorization_code'
access_token_signed_response_alg: 'none'
userinfo_signed_response_alg: 'none'
token_endpoint_auth_method: 'client_secret_basic'
# - client_name: 'Jellyseerr'
# client_id: '$(au rand 72)'
# client_secret: '$(au hash 72)'
# public: false
# authorization_policy: 'two_factor'
# require_pkce: false
# pkce_challenge_method: ''
# redirect_uris:
# - 'https://memos.loadingm.xyz/auth/callback'
# scopes:
# - 'openid'
# - 'email'
# - 'profile'
# response_types:
# - 'code'
# grant_types:
# - 'authorization_code'
# access_token_signed_response_alg: 'none'
# userinfo_signed_response_alg: 'none'
# token_endpoint_auth_method: 'client_secret_basic'
# - client_name: 'Jellyfin'
# client_id: '$(au rand 72)'
# client_secret: '$(au hash 72)'
# public: false
# authorization_policy: 'two_factor'
# require_pkce: false
# pkce_challenge_method: ''
# redirect_uris:
# - 'https://memos.loadingm.xyz/auth/callback'
# scopes:
# - 'openid'
# - 'email'
# - 'profile'
# response_types:
# - 'code'
# grant_types:
# - 'authorization_code'
# access_token_signed_response_alg: 'none'
# userinfo_signed_response_alg: 'none'
# token_endpoint_auth_method: 'client_secret_basic'

View File

@@ -1,78 +0,0 @@
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

10
build-certs.sh Normal file
View File

@@ -0,0 +1,10 @@
docker compose run --rm certbot certonly --webroot --webroot-path /var/www/certbot/ \
-d loadingm.xyz \
-d gitea.loadingm.xyz \
-d auth.loadingm.xyz \
-d jellyfin.loadingm.xyz \
-d jellyseerr.loadingm.xyz \
-d servarr.loadingm.xyz \
-d karakeep.loadingm.xyz \
-d ollama.loadingm.xyz

View File

@@ -1,75 +1,38 @@
include:
- ./karakeep-compose.yaml
- ./jellyfin-compose.yaml
- ./immich-compose.yaml
- ./matrix-compose.yaml
- ./authentik.yaml
- ./recipe-sage.yaml
secrets:
JWT_SECRET:
file: '/data/authelia/secrets/JWT_SECRET'
file: './authelia/secrets/JWT_SECRET'
SESSION_SECRET:
file: '/data/authelia/secrets/SESSION_SECRET'
file: './authelia/secrets/SESSION_SECRET'
STORAGE_PASSWORD:
file: '/data/authelia/secrets/STORAGE_PASSWORD'
file: './authelia/secrets/STORAGE_PASSWORD'
STORAGE_ENCRYPTION_KEY:
file: '/data/authelia/secrets/STORAGE_ENCRYPTION_KEY'
file: './authelia/secrets/STORAGE_ENCRYPTION_KEY'
volumes:
meilisearch:
karakeep:
bitwarden:
immich-model-cache:
nginx:
networks:
karakeep:
external: false
enable_ipv6: true
karakeep-int:
external: false
enable_ipv6: true
ollama:
external: false
enable_ipv6: true
ollama-int:
external: false
enable_ipv6: true
jellyfin:
external: false
enable_ipv6: true
jellyfin-int:
external: false
enable_ipv6: true
auth:
external: false
enable_ipv6: true
gitea:
external: false
enable_ipv6: true
gpodder:
external: false
enable_ipv6: true
memos:
external: false
enable_ipv6: true
mail:
external: false
enable_ipv6: true
bitwarden:
external: false
enable_ipv6: true
immich:
external: false
enable_ipv6: true
matrix:
external: false
enable_ipv6: true
sage:
external: false
enable_ipv6: true
services:
web:
build:
dockerfile: ./nginx-dockerfile
image: "nginx"
restart: unless-stopped
ports:
- 80:80
@@ -77,7 +40,9 @@ services:
volumes:
- ./nginx:/etc/nginx:ro
- /data/site:/data/site:ro
- nginx:/var/cache/nginx/
- /data/certbot/www/:/var/www/certbot/:ro
# - /etc/letsencrypt:/etc/letsencrypt:ro
- /data/certbot/conf:/etc/letsencrypt:ro
networks:
- karakeep
- ollama
@@ -85,12 +50,6 @@ services:
- jellyfin-int
- auth
- gitea
- gpodder
- memos
- bitwarden
- matrix
- immich
- sage
depends_on:
- jellyfin
- ollama-webui
@@ -98,110 +57,71 @@ services:
- authelia
- qbittorrent
- gitea
- gpodder
- memos
- authentik
- matrix-server
- jackett
- sage-static
- sage-api
- sage-pushpin
logging: &logging
options:
max-size: "50m"
# Optional - extra fonts to be used during transcoding with subtitle burn-in
# - type: bind
# source: /usr/local/share/fonts/cu
# target: /usr/local/share/fonts/custom
# read_only: true
certbot:
image: certbot/certbot:latest
volumes:
- /data/certbot/www/:/var/www/certbot/:rw
- /data/certbot/conf/:/etc/letsencrypt/:rw
authelia:
container_name: 'authelia'
image: 'docker.io/authelia/authelia:latest'
command:
- 'authelia'
- '--config=/config/configuration.yml'
- '--config=/data/configuration.yml'
restart: 'unless-stopped'
secrets: ['JWT_SECRET', 'SESSION_SECRET', 'STORAGE_PASSWORD', 'STORAGE_ENCRYPTION_KEY']
networks:
- auth
- mail
environment:
AUTHELIA_IDENTITY_VALIDATION_RESET_PASSWORD_JWT_SECRET_FILE: '/run/secrets/JWT_SECRET'
AUTHELIA_SESSION_SECRET_FILE: '/run/secrets/SESSION_SECRET'
AUTHELIA_STORAGE_ENCRYPTION_KEY_FILE: '/run/secrets/STORAGE_ENCRYPTION_KEY'
volumes:
- './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: "16G"
# PAUSE_WHEN_EMPTY_SECONDS: "20"
# USE_MEOWICE_FLAGS: "true"
# 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
- './authelia/:/config'
# webdav:
# image: ""
minecraft:
image: itzg/minecraft-server:latest
tty: true
stdin_open: true
restart: unless-stopped
ports:
- "25565:25565"
environment:
- USER_UID=106
- USER_GID=110
- ENABLE_NOTIFY_MAIL=true
# -
EULA: "TRUE"
TYPE: "FABRIC"
MEMORY: "2048M"
MOTD: "Loading server..."
LEVEL: "world"
USE_MEOWICE_FLAGS: "true"
DIFFICULTY: "3"
OPS: |-
187eca31-2e33-4199-97e0-2286bf35f7f8
ENABLE_WHITELIST: "true"
WHITELIST: |-
187eca31-2e33-4199-97e0-2286bf35f7f8
PAUSE_WHEN_EMPTY_SECONDS: "20"
ENABLE_ROLLING_LOGS: "true"
volumes:
- "/opt/minecraft:/data"
gitea:
image: gitea/gitea:latest
environment:
- USER_UID=1000
- USER_GID=1000
restart: unless-stopped
networks:
- gitea
- mail
volumes:
- /data/gitea/data:/data
- /home/git/.ssh/:/data/git/.ssh
- /etc/timezone:/etc/timezone:ro
- /etc/localtime:/etc/localtime:ro
ports:
- "222:22"
logging: *logging
depends_on:
- authelia
gitea-runner:
image: docker.gitea.com/act_runner:latest
image: docker.io/gitea/act_runner:nightly
restart: unless-stopped
networks:
- gitea
@@ -213,75 +133,6 @@ services:
- /var/run/docker.sock:/var/run/docker.sock
- /data/gitea/runner/:/data
- ./gitea-runner.yaml:/config.yaml
logging: *logging
depends_on:
- gitea
gpodder:
image: gitea.loadingm.xyz/the10thwiz/gpodder-rs:latest
restart: unless-stopped
environment:
- ROCKET_SECRET_KEY=${GPODDER_SECRET_KEY}
networks:
- gpodder
volumes:
- /data/gpodder:/data
logging: *logging
tftp:
image: kaczmar2/tftp-server
restart: unless-stopped
environment:
- ENABLE_WEB_SERVER=false
network_mode: host
volumes:
- /data/tftp:/srv/tftp:ro
- /etc/localtime:/etc/localtime:ro
logging: *logging
memos:
image: neosmemo/memos:stable
networks:
- memos
volumes:
- /data/memos:/var/opt/memos
environment:
- MEMOS_MODE=prod
- MEMOS_PORT=5230
restart: unless-stopped
logging: *logging
mail:
image: boky/postfix
restart: unless-stopped
logging: *logging
environment:
- ALLOWED_SENDER_DOMAINS=loadingm.xyz
# - POSTFIX_myhostname=mail
- POSTFIX_myhostname=loadingm.xyz
- 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
bitwarden:
# env_file:
# - bitwarden.env
environment:
DOMAIN: "https://bitwarden.loadingm.xyz"
SMTP_HOST: mail
SMTP_FROM: bitwarden@loadingm.xyz
SMTP_SECURITY: off
SIGNUPS_ALLOWED: false
# ADMIN_TOKEN: "google straining barracuda prescribe augmented bucket"
networks:
- bitwarden
- mail
image: vaultwarden/server:latest
restart: always
volumes:
- /data/bitwarden:/data
# calibre:
# image: "linuxserver/calibre-web"
# 5d-diplomacy-frontend:

View File

@@ -45,8 +45,6 @@ runner:
- "ubuntu-22.04:docker://docker.gitea.com/runner-images:ubuntu-22.04"
- "ubuntu-20.04:docker://docker.gitea.com/runner-images:ubuntu-20.04"
- "rustup-all:docker://gitea.loadingm.xyz/the10thwiz/rustup:latest"
- "rustup-wasm:docker://gitea.loadingm.xyz/the10thwiz/rustup:wasm-stable"
- "rustup-all-musl:docker://gitea.loadingm.xyz/the10thwiz/rustup:musl-latest"
- "rustup-stable:docker://gitea.loadingm.xyz/the10thwiz/rustup:stable"
- "rustup-beta:docker://gitea.loadingm.xyz/the10thwiz/rustup:beta"
- "rustup-nightly:docker://gitea.loadingm.xyz/the10thwiz/rustup:nightly"
@@ -77,7 +75,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 -v /var/run/docker.sock:/var/run/docker.sock'
options:
# 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.
@@ -93,14 +91,14 @@ container:
# If you want to allow any volume, please use the following configuration:
# valid_volumes:
# - '**'
valid_volumes: ['**']
valid_volumes: []
# overrides the docker client host with the specified one.
# If it's empty, act_runner will find an available docker host automatically.
# If it's "-", act_runner will find an available docker host automatically, but the docker host won't be mounted to the job containers and service containers.
# 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: "-"
docker_host: ""
# Pull docker image(s) even if already present
force_pull: true
force_pull: false
# 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

@@ -1,20 +0,0 @@
[Unit]
Description=Homelab services
Requires=docker.service
After=docker.service
[Service]
Restart=always
User=root
Group=docker
TimeoutStopSec=15
WorkingDirectory=/home/matthew/homelab
# Shutdown container (if running) when unit is started
ExecStartPre=/usr/bin/docker compose -f docker-compose.yaml down
# Start container when unit is started
ExecStart=/usr/bin/docker compose -f docker-compose.yaml up
# Stop container when unit is stopped
ExecStop=/usr/bin/docker compose -f docker-compose.yaml down
[Install]
WantedBy=multi-user.target

View File

@@ -1,66 +0,0 @@
services:
immich-server:
image: ghcr.io/immich-app/immich-server:v2
# extends:
# file: hwaccel.transcoding.yml
# service: cpu # set to one of [nvenc, quicksync, rkmpp, vaapi, vaapi-wsl] for accelerated transcoding
volumes:
- /data/immich/uploads:/data
- /etc/localtime:/etc/localtime:ro
environment:
DB_USERNAME: postgres
DB_PASSWORD: nVmwTyOKlcEa6VUc
DB_DATABASE_NAME: immich
DB_HOSTNAME: immich-db
REDIS_HOSTNAME: immich-redis
networks:
- immich
depends_on:
- immich-redis
- immich-db
restart: always
healthcheck:
disable: false
immich-machine-learning:
# For hardware acceleration, add one of -[armnn, cuda, rocm, openvino, rknn] to the image tag.
# Example tag: ${IMMICH_VERSION:-v2}-cuda
image: ghcr.io/immich-app/immich-machine-learning:v2
# extends: # uncomment this section for hardware acceleration - see https://docs.immich.app/features/ml-hardware-acceleration
# file: hwaccel.ml.yml
# service: cpu # set to one of [armnn, cuda, rocm, openvino, openvino-wsl, rknn] for accelerated inference - use the `-wsl` version for WSL2 where applicable
volumes:
- immich-model-cache:/cache
environment:
DB_USERNAME: postgres
DB_PASSWORD: nVmwTyOKlcEa6VUc
DB_DATABASE_NAME: immich
networks:
- immich
restart: always
healthcheck:
disable: false
immich-redis:
image: docker.io/valkey/valkey:9@sha256:fb8d272e529ea567b9bf1302245796f21a2672b8368ca3fcb938ac334e613c8f
healthcheck:
test: redis-cli ping || exit 1
networks:
- immich
restart: always
immich-db:
image: ghcr.io/immich-app/postgres:14-vectorchord0.4.3-pgvectors0.2.0@sha256:bcf63357191b76a916ae5eb93464d65c07511da41e3bf7a8416db519b40b1c23
environment:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: nVmwTyOKlcEa6VUc
POSTGRES_DB: immich
POSTGRES_INITDB_ARGS: '--data-checksums'
# Uncomment the DB_STORAGE_TYPE: 'HDD' var if your database isn't stored on SSDs
# DB_STORAGE_TYPE: 'HDD'
volumes:
- /data/immich/postgres:/var/lib/postgresql/data
networks:
- immich
shm_size: 128mb
restart: always

View File

@@ -1,295 +0,0 @@
---
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

@@ -1,58 +1,7 @@
services:
gluetun:
image: qmcgaw/gluetun
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
environment:
- VPN_SERVICE_PROVIDER=custom
- VPN_TYPE=wireguard
# - VPN_ENDPOINT_IP=${ENDPOINT_IP}
# - VPN_ENDPOINT_PORT=${ENDPOINT_PORT}
# - WIREGUARD_ADDRESSES=${WIREGUARD_ADDR}
# - VPN_DNS_ADDRESS=${DNS_ADDRESS}
# - WIREGUARD_PUBLIC_KEY=${PUBLIC_KEY}
# - WIREGUARD_PRIVATE_KEY=${PRIVATE_KEY}
- VPN_PORT_FORWARDING=on
- VPN_PORT_FORWARDING_PROVIDER=protonvpn
- VPN_PORT_FORWARDING_STATUS_FILE=/tmp/gluetun/forwarded_port
- VPN_PORT_FORWARDING_UP_COMMAND=/bin/sh -c 'wget -O- --retry-connrefused --post-data "json={\"listen_port\":{{PORT}},\"current_network_interface\":\"{{VPN_INTERFACE}}\",\"random_port\":false,\"upnp\":false}" http://127.0.0.1:8080/api/v2/app/setPreferences 2>&1'
- VPN_PORT_FORWARDING_DOWN_COMMAND=/bin/sh -c 'wget -O- --retry-connrefused --post-data "json={\"listen_port\":0,\"current_network_interface\":\"lo"}" http://127.0.0.1:8080/api/v2/app/setPreferences 2>&1'
- TZ=${TZ}
- UPDATER_PERIOD=24h
restart: always
volumes:
- /data/jellyfin:/data/jellyfin
- /data/jellyfin/gluetun:/tmp/gluetun
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
image: lscr.io/linuxserver/qbittorrent:latest
container_name: qbittorrent
environment:
- WEBUI_PORT=8080
- PUID=0
@@ -62,19 +11,17 @@ services:
volumes:
- /data/jellyfin:/data/jellyfin
- /data/jellyfin/configs/qbittorrent:/config
# - /data/jellyfin/qbittorrent/downloads:/data/jellyfin/qbittorrent/downloads
depends_on:
- gluetun
- /data/jellyfin/qbittorrent/downloads:/downloads
ports:
- 8080:8080
- 6881:6881
- 6881:6881/udp
networks:
- jellyfin-int
restart: unless-stopped
flaresolverr:
image: ghcr.io/flaresolverr/flaresolverr:latest
network_mode: service:gluetun
depends_on:
- gluetun
# networks:
# - jellyfin-int
# ports:
# - 8191:8191
container_name: flaresolverr
environment:
- LOG_LEVEL=${LOG_LEVEL:-info}
- LOG_HTML=${LOG_HTML:-false}
@@ -82,11 +29,14 @@ services:
- TZ=${TZ}
#- LANG=fr_FR
#- LANG=en_US
# volumes:
# - /tmp/flaresolver:/tmp
ports:
- 8191:8191
networks:
- jellyfin-int
restart: unless-stopped
prowlarr:
image: lscr.io/linuxserver/prowlarr:latest
container_name: prowlarr
environment:
- PUID=0
- PGID=0
@@ -100,24 +50,21 @@ 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
container_name: jackett
environment:
- PUID=0
- PGID=0
- TZ=${TZ}
# - 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
container_name: sonarr
environment:
- PUID=0
- PGID=0
@@ -127,13 +74,14 @@ services:
- /data/jellyfin/configs/sonarr:/config
- /data/jellyfin/sonarr/tv:/tv
- /data/jellyfin/qbittorrent/downloads:/downloads
# ports:
# - 8989:8989
ports:
- 8989:8989
networks:
- jellyfin-int
restart: unless-stopped
radarr:
image: lscr.io/linuxserver/radarr:latest
container_name: radarr
environment:
- PUID=0
- PGID=0
@@ -143,60 +91,44 @@ services:
- /data/jellyfin/configs/radarr:/config
- /data/jellyfin/radarr/movies:/movies
- /data/jellyfin/qbittorrent/downloads:/downloads
# ports:
# - 7878:7878
ports:
- 7878:7878
networks:
- jellyfin-int
restart: unless-stopped
jellyfin:
image: ghcr.io/jellyfin/jellyfin:latest
# image: lscr.io/linuxserver/jellyfin:latest
image: lscr.io/linuxserver/jellyfin:latest
container_name: jellyfin
environment:
- PUID=0
- PGID=0
- TZ=${TZ}
- JELLYFIN_DATA_DIR=/config/data
- JELLYFIN_CONFIG_DIR=/config
- JELLYFIN_LOG_DIR=/config/log
- JELLYFIN_CACHE_DIR=/config/cache
# - NVIDIA_VISIBLE_DEVICES=all
- NVIDIA_VISIBLE_DEVICES=all
ports:
# - 8096:8096
# - 8920:8920
- 8096:8096
- 8920:8920
- 7359:7359/udp
- 1900:1900/udp
networks:
- jellyfin
- jellyfin-int
volumes:
- /data/library:/data/library:ro
- /data/jellyfin:/data/jellyfin
- /backup:/data/jellyfin/backups
# - /data/jellyfin/configs/jellyfin:/config
- /srv/jellyfin:/config
- /data/jellyfin/configs/jellyfin:/config
- /data/jellyfin/jellyfin/cache:/cache
- /data/jellyfin/sonarr/tv:/data/tvshows
- /data/jellyfin/radarr/movies:/data/movies
- /data/jellyfin/qbittorrent/downloads:/data/media_downloads
restart: unless-stopped
group_add:
- '993'
devices:
- /dev/dri/renderD128:/dev/dri/renderD128
# runtime: nvidia
# deploy:
# resources:
# reservations:
# devices:
# - driver: intel
# count: all
# capabilities: [gpu]
jellyseerr:
image: fallenbagel/jellyseerr:latest
container_name: jellyseerr
environment:
- LOG_LEVEL=debug
- TZ=${TZ}
# ports:
# - 5055:5055
ports:
- 5055:5055
volumes:
- /data/jellyfin/configs/jellyseerr:/app/config
restart: unless-stopped

View File

@@ -10,8 +10,7 @@ services:
# ports:
# - 3000:3000
env_file:
# - .env
- /data/secrets/karakeep
- .env
environment:
MEILI_ADDR: http://meilisearch:7700
BROWSER_WEB_URL: http://karakeep-chrome:9222
@@ -21,9 +20,7 @@ services:
INFERENCE_OUTPUT_SCHEMA: json
INFERENCE_CONTEXT_LENGTH: 1024
INFERENCE_JOB_TIMEOUT_SEC: 120
CRAWLER_FULL_PAGE_ARCHIVE: true
BROWSER_COOKIE_PATH: /data/cookies.json
LOG_LEVEL: info
# You almost never want to change the value of the DATA_DIR variable.
# If you want to mount a custom directory, change the volume mapping above instead.
DATA_DIR: /data # DON'T CHANGE THIS
@@ -55,14 +52,12 @@ services:
networks:
- karakeep-int
ollama:
image: docker.io/ollama/ollama:rocm
image: docker.io/ollama/ollama:latest
volumes:
- .:/code
- /data/library/ollama/ollama:/root/.ollama
devices:
- /dev/dri:/dev/dri
- /dev/kfd:/dev/kfd
# pull_policy: always
container_name: ollama
pull_policy: always
tty: true
restart: always
environment:
@@ -71,31 +66,21 @@ services:
- OLLAMA_DEBUG=1
networks:
- ollama-int
ollama-webui:
image: ghcr.io/open-webui/open-webui:main
container_name: ollama-webui
volumes:
- /data/library/ollama/ollama-webui:/app/backend/data
depends_on:
- ollama
environment: # https://docs.openwebui.com/getting-started/env-configuration#default_models
- OLLAMA_BASE_URLS=http://ollama:7869 #comma separated ollama hosts
- ENABLE_OPENAI_API=False
- WEBUI_URL=https://ollama.loadingm.xyz
- OLLAMA_BASE_URLS=http://host.docker.internal:7869 #comma separated ollama hosts
- ENV=dev
- ENABLE_OAUTH_SIGNUP=true
- OAUTH_MERGE_ACCOUNTS_BY_EMAIL=true
- OPENID_PROVIDER_URL=https://auth.loadingm.xyz/.well-known/openid-configuration
- OAUTH_PROVIDER_NAME=Authelia
- OAUTH_SCOPES=openid email profile groups
- ENABLE_OAUTH_ROLE_MANAGEMENT=true
- OAUTH_ALLOWED_ROLES=openwebui,openwebui-admin
- OAUTH_ADMIN_ROLES=openwebui-admin
- OAUTH_ROLES_CLAIM=groups
- OAUTH_CODE_CHALLENGE_METHOD=S256
env_file: /data/secrets/ollama-webui
# - WEBUI_AUTH=True
# - WEBUI_NAME=valiantlynx AI
# - WEBUI_SECRET_KEY=t0p-s3cr3t
- WEBUI_AUTH=True
- WEBUI_NAME=valiantlynx AI
- WEBUI_URL=http://localhost:8080
- WEBUI_SECRET_KEY=t0p-s3cr3t
extra_hosts:
- host.docker.internal:host-gateway
restart: unless-stopped

View File

@@ -1,27 +0,0 @@
services:
matrix-server:
image: forgejo.ellis.link/continuwuation/continuwuity
restart: unless-stopped
environment:
CONTINUWUITY_SERVER_NAME: "matrix.loadingm.xyz"
CONTINUWUITY_WELL_KNOWN__SERVER: "matrix.loadingm.xyz:443"
CONTINUWUITY_ALLOW_REGISTRATION: true
CONTINUWUITY_REGISTRATION_TOKEN: "qFz7aekKxgXdd6SpQ09llv52+S4="
CONTINUWUITY_ALLOW_FEDERATION: 'true'
CONTINUWUITY_ALLOW_CHECK_FOR_UPDATES: 'true'
CONTINUWUITY_TRUSTED_SERVERS: '["matrix.org", "mozilla.org"]'
CONTINUWUITY_DATABASE_PATH: /var/lib/continuwuity
CONTINUWUITY_PORT: 6167
CONTINUWUITY_ADDRESS: 0.0.0.0
volumes:
- /data/matrix/db:/var/lib/continuwuity
networks:
- matrix
# ports:
# - 8448:6167
# turn:
# image: docker.io/coturn/coturn
# restart: unless-stopped
# network_mode: "host"
# volumes:
# - ./coturn.conf:/etc/coturn/turnserver.conf:ro

View File

@@ -1,2 +0,0 @@
FROM nginx
RUN apt install nginx-module-acme

View File

@@ -3,7 +3,6 @@ worker_processes auto;
worker_cpu_affinity auto;
pid /run/nginx.pid;
error_log /var/log/nginx/error.log;
load_module /usr/lib/nginx/modules/ngx_http_acme_module.so;
events {
worker_connections 768;
@@ -11,14 +10,6 @@ events {
}
http {
resolver 127.0.0.11:53;
acme_issuer letsencrypt {
uri https://acme-v02.api.letsencrypt.org/directory;
contact matthew.pomes@pm.me;
state_path /var/cache/nginx/acme-letsencrypt;
accept_terms_of_service;
}
##
# Basic Settings
@@ -66,12 +57,6 @@ http {
##
include /etc/nginx/sites-enabled/*;
server {
listen 80;
location / {
return 301 https://$host$request_uri;
}
}
}

View File

@@ -1,8 +1,17 @@
server {
if ($host = 5d-diplomacy.loadingm.xyz) {
return 301 https://$host$request_uri;
} # managed by Certbot
listen 80;
listen [::]:80;
server_name 5d-diplomacy.loadingm.xyz;
location /.well-known/acme-challenge/ {
root /var/www/certbot;
}
# Uncomment to redirect HTTP to HTTPS
location / {
return 301 https://$host$request_uri;
@@ -16,14 +25,16 @@ server {
http2 on;
server_name 5d-diplomacy.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;
ssl_certificate /etc/letsencrypt/live/5d-diplomacy.loadingm.xyz/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/5d-diplomacy.loadingm.xyz/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
ssl_trusted_certificate /etc/letsencrypt/live/5d-diplomacy.loadingm.xyz/chain.pem;
# Security / XSS Mitigation Headers
add_header X-Content-Type-Options "nosniff";

View File

@@ -1,3 +1,18 @@
server {
listen 80;
listen [::]:80;
server_name auth.loadingm.xyz;
location /.well-known/acme-challenge/ {
root /var/www/certbot;
}
# Uncomment to redirect HTTP to HTTPS
location / {
return 301 https://$host$request_uri;
}
}
server {
# Nginx versions 1.25+
listen 443 ssl;
@@ -5,14 +20,16 @@ server {
http2 on;
server_name auth.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;
ssl_certificate /etc/letsencrypt/live/loadingm.xyz/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/loadingm.xyz/privkey.pem;
# include /etc/letsencrypt/options-ssl-nginx.conf;
# ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
ssl_trusted_certificate /etc/letsencrypt/live/loadingm.xyz/chain.pem;
# Security / XSS Mitigation Headers
add_header X-Content-Type-Options "nosniff";
@@ -25,6 +42,10 @@ server {
# 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 /.well-known/acme-challenge/ {
root /var/www/certbot;
}
location / {
# Proxy main karakeep traffic
proxy_pass http://authelia:9091;

View File

@@ -1,49 +0,0 @@
# 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

@@ -1,63 +0,0 @@
server {
# Nginx versions 1.25+
listen 443 ssl;
listen [::]:443 ssl;
http2 on;
server_name bitwarden.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.
# set $CSP "default-src https: data: blob:";
# set $CSP "$CSP; img-src 'self' https://* data:";
# set $CSP "$CSP; style-src 'self' 'unsafe-inline' data:";
# set $CSP "$CSP; style-src-elem 'self' 'unsafe-inline' data:";
# set $CSP "$CSP; script-src 'self' 'unsafe-inline' https://www.gstatic.com https://www.youtubse.com blob: data:";
# set $CSP "$CSP; worker-src 'self' blob: data:";
# set $CSP "$CSP; connect-src 'self' data:";
# set $CSP "$CSP; object-src 'none' data:";
# set $CSP "$CSP; frame-ancestors 'self' data:";
# set $CSP "$CSP; font-src 'self' data:";
# add_header Content-Security-Policy $CSP;
location /notifications/hub {
proxy_pass http://bitwarden:80;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
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;
}
location / {
# Proxy main bitwarden traffic
proxy_pass http://bitwarden:80;
proxy_set_header Host $host;
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;
# Disable buffering when the nginx proxy gets very resource heavy upon streaming
proxy_buffering off;
}
}

View File

@@ -1,3 +1,18 @@
server {
listen 80;
listen [::]:80;
server_name gitea.loadingm.xyz;
location /.well-known/acme-challenge/ {
root /var/www/certbot;
}
# Uncomment to redirect HTTP to HTTPS
location / {
return 301 https://$host$request_uri;
}
}
server {
# Nginx versions 1.25+
listen 443 ssl;
@@ -5,14 +20,16 @@ server {
http2 on;
server_name gitea.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;
ssl_certificate /etc/letsencrypt/live/loadingm.xyz/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/loadingm.xyz/privkey.pem;
# include /etc/letsencrypt/options-ssl-nginx.conf;
# ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
ssl_trusted_certificate /etc/letsencrypt/live/loadingm.xyz/chain.pem;
# Security / XSS Mitigation Headers
add_header X-Content-Type-Options "nosniff";
@@ -25,6 +42,10 @@ server {
# 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' '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'";
location /.well-known/acme-challenge/ {
root /var/www/certbot;
}
location / {
# Proxy main karakeep traffic
proxy_pass http://gitea:3000;

View File

@@ -1,32 +0,0 @@
server {
# SSL configuration
listen 443 ssl;
listen [::]:443 ssl;
http2 on;
server_name gpodder.loadingm.xyz;
acme_certificate letsencrypt;
ssl_certificate $acme_certificate;
ssl_certificate_key $acme_certificate_key;
ssl_certificate_cache max=2;
# 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 / {
# Proxy main karakeep traffic
proxy_pass http://gpodder:8000;
proxy_set_header Host $host;
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;
# Disable buffering when the nginx proxy gets very resource heavy upon streaming
proxy_buffering off;
}
}

View File

@@ -1,53 +0,0 @@
server {
# Nginx versions 1.25+
listen 443 ssl;
listen [::]:443 ssl;
http2 on;
server_name immich.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;
# 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' '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'";
location /api/socket.io {
proxy_pass http://immich-server:2283;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
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;
}
location / {
# Proxy main karakeep traffic
proxy_pass http://immich-server:2283;
proxy_set_header Host $host;
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;
# Disable buffering when the nginx proxy gets very resource heavy upon streaming
proxy_buffering off;
}
}

View File

@@ -1,3 +1,18 @@
server {
listen 80;
listen [::]:80;
server_name jellyfin.loadingm.xyz;
location /.well-known/acme-challenge/ {
root /var/www/certbot;
}
# Uncomment to redirect HTTP to HTTPS
location / {
return 301 https://$host$request_uri;
}
}
server {
# Nginx versions 1.25+
listen 443 ssl;
@@ -5,14 +20,16 @@ server {
http2 on;
server_name jellyfin.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;
ssl_certificate /etc/letsencrypt/live/loadingm.xyz/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/loadingm.xyz/privkey.pem;
# include /etc/letsencrypt/options-ssl-nginx.conf;
# ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
ssl_trusted_certificate /etc/letsencrypt/live/loadingm.xyz/chain.pem;
# Security / XSS Mitigation Headers
add_header X-Content-Type-Options "nosniff";
@@ -25,6 +42,10 @@ server {
# 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 /.well-known/acme-challenge/ {
root /var/www/certbot;
}
location / {
# Proxy main Jellyfin traffic
proxy_pass http://jellyfin:8096;

View File

@@ -1,3 +1,18 @@
server {
listen 80;
listen [::]:80;
server_name jellyseerr.loadingm.xyz;
location /.well-known/acme-challenge/ {
root /var/www/certbot;
}
# Uncomment to redirect HTTP to HTTPS
location / {
return 301 https://$host$request_uri;
}
}
server {
# Nginx versions 1.25+
listen 443 ssl;
@@ -5,20 +20,26 @@ server {
http2 on;
server_name jellyseerr.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;
ssl_certificate /etc/letsencrypt/live/loadingm.xyz/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/loadingm.xyz/privkey.pem;
# include /etc/letsencrypt/options-ssl-nginx.conf;
# ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
ssl_trusted_certificate /etc/letsencrypt/live/loadingm.xyz/chain.pem;
# 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 /.well-known/acme-challenge/ {
root /var/www/certbot;
}
# Content Security Policy
# See: https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP
# Enforces https content and restricts JS/CSS to origin

View File

@@ -1,3 +1,18 @@
server {
listen 80;
listen [::]:80;
server_name karakeep.loadingm.xyz;
location /.well-known/acme-challenge/ {
root /var/www/certbot;
}
# Uncomment to redirect HTTP to HTTPS
location / {
return 301 https://$host$request_uri;
}
}
server {
# Nginx versions 1.25+
listen 443 ssl;
@@ -5,14 +20,16 @@ server {
http2 on;
server_name karakeep.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;
ssl_certificate /etc/letsencrypt/live/loadingm.xyz/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/loadingm.xyz/privkey.pem;
# include /etc/letsencrypt/options-ssl-nginx.conf;
# ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
ssl_trusted_certificate /etc/letsencrypt/live/loadingm.xyz/chain.pem;
# Security / XSS Mitigation Headers
add_header X-Content-Type-Options "nosniff";
@@ -23,17 +40,11 @@ server {
# 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.
set $CSP "default-src https: data: blob:";
set $CSP "$CSP; img-src 'self' https://* data:";
set $CSP "$CSP; style-src 'self' 'unsafe-inline' data:";
set $CSP "$CSP; style-src-elem 'self' 'unsafe-inline' data:";
set $CSP "$CSP; script-src 'self' 'unsafe-inline' https://www.gstatic.com https://www.youtubse.com blob: data:";
set $CSP "$CSP; worker-src 'self' blob: data:";
set $CSP "$CSP; connect-src 'self' data:";
set $CSP "$CSP; object-src 'none' data:";
set $CSP "$CSP; frame-ancestors 'self' data:";
set $CSP "$CSP; font-src 'self' data:";
add_header Content-Security-Policy $CSP;
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 /.well-known/acme-challenge/ {
root /var/www/certbot;
}
location / {
# Proxy main karakeep traffic
@@ -44,7 +55,6 @@ server {
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Protocol $scheme;
proxy_set_header X-Forwarded-Host $http_host;
proxy_hide_header Content-Security-Policy;
# Disable buffering when the nginx proxy gets very resource heavy upon streaming
proxy_buffering off;

View File

@@ -1,53 +0,0 @@
server {
# Nginx versions 1.25+
listen 443 ssl;
listen [::]:443 ssl;
http2 on;
server_name matrix.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;
# 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' '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'";
# location /api/socket.io {
# proxy_pass http://matrix-server:6167;
# proxy_http_version 1.1;
# proxy_set_header Upgrade $http_upgrade;
# proxy_set_header Connection "upgrade";
# proxy_set_header Host $host;
# 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;
# }
location / {
# Proxy main karakeep traffic
proxy_pass http://matrix-server:6167;
proxy_set_header Host $host;
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;
# Disable buffering when the nginx proxy gets very resource heavy upon streaming
proxy_buffering off;
}
}

View File

@@ -1,41 +0,0 @@
server {
# Nginx versions 1.25+
listen 443 ssl;
listen [::]:443 ssl;
http2 on;
server_name memos.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;
# 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' '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'";
location / {
# Proxy main karakeep traffic
proxy_pass http://memos:5230;
proxy_set_header Host $host;
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;
# Disable buffering when the nginx proxy gets very resource heavy upon streaming
proxy_buffering off;
}
}

View File

@@ -5,23 +5,9 @@ server {
http2 on;
server_name ollama.loadingm.xyz;
acme_certificate letsencrypt;
ssl_certificate $acme_certificate;
ssl_certificate_key $acme_certificate_key;
ssl_certificate_cache max=2;
location /ws/ {
proxy_pass http://ollama-webui:8080;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
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;
}
include /etc/nginx/snippets/letsencrypt.conf;
# include /etc/nginx/snippets/authelia-location.conf;
location / {
include /etc/nginx/snippets/proxy.conf;

View File

@@ -1,14 +1,52 @@
##
# You should look at the following URL's in order to grasp a solid understanding
# of Nginx configuration files in order to fully unleash the power of Nginx.
# https://www.nginx.com/resources/wiki/start/
# https://www.nginx.com/resources/wiki/start/topics/tutorials/config_pitfalls/
# https://wiki.debian.org/Nginx/DirectoryStructure
#
# In most cases, administrators will remove this file from sites-enabled/ and
# leave it as reference inside of sites-available where it will continue to be
# updated by the nginx packaging team.
#
# This file will automatically load configuration files provided by other
# applications, such as Drupal or Wordpress. These applications will be made
# available underneath a path with that package name, such as /drupal8.
#
# Please see /usr/share/doc/nginx-doc/examples/ for more detailed examples.
##
server {
listen 80 default_server;
listen [::]:80;
server_name loadingm.xyz *.loadingm.xyz;
location /.well-known/acme-challenge/ {
root /var/www/certbot;
}
# Uncomment to redirect HTTP to HTTPS
location / {
return 301 https://$host$request_uri;
}
}
# Default server configuration
#
server {
# SSL configuration
listen 443 ssl default_server;
listen [::]:443 ssl default_server;
http2 on;
server_name loadingm.xyz;
acme_certificate letsencrypt;
ssl_certificate $acme_certificate;
ssl_certificate_key $acme_certificate_key;
ssl_certificate_cache max=2;
ssl_certificate /etc/letsencrypt/live/loadingm.xyz/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/loadingm.xyz/privkey.pem;
# include /etc/letsencrypt/options-ssl-nginx.conf;
# ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
ssl_trusted_certificate /etc/letsencrypt/live/loadingm.xyz/chain.pem;
root /data/site;
@@ -22,4 +60,11 @@ server {
# as directory, then fall back to displaying a 404.
try_files $uri $uri/ =404;
}
# deny access to .htaccess files, if Apache's document root
# concurs with nginx's one
#
#location ~ /\.ht {
# deny all;
#}
}

View File

@@ -1,46 +0,0 @@
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

@@ -1,21 +1,19 @@
server {
# Nginx versions 1.25+
listen 443 ssl;
listen [::]:443 ssl;
http2 on;
server_name servarr.loadingm.xyz;
acme_certificate letsencrypt;
ssl_certificate $acme_certificate;
ssl_certificate_key $acme_certificate_key;
ssl_certificate_cache max=2;
include /etc/nginx/snippets/letsencrypt.conf;
include /etc/nginx/snippets/authelia-location.conf;
location /qbt/ {
# include /etc/nginx/snippets/proxy.conf;
include /etc/nginx/snippets/authelia-authrequest.conf;
# proxy_pass http://qbittorrent:8080/;
proxy_pass http://gluetun:8080/;
proxy_pass http://qbittorrent:8080/;
proxy_http_version 1.1;
proxy_set_header Host $proxy_host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
@@ -65,8 +63,7 @@ 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://gluetun:9117;
proxy_pass http://jackett:9117;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $host;

View File

@@ -0,0 +1,25 @@
# 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'";
## The default `client_max_body_size` is 1M, this might not be enough for some posters, etc.
client_max_body_size 20M;
ssl_certificate /etc/letsencrypt/live/loadingm.xyz/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/loadingm.xyz/privkey.pem;
# include /etc/letsencrypt/options-ssl-nginx.conf;
# ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
ssl_trusted_certificate /etc/letsencrypt/live/loadingm.xyz/chain.pem;
# 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 /.well-known/acme-challenge/ {
root /var/www/certbot;
}

View File

@@ -1,130 +0,0 @@
# 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