Compare commits

..
18 Commits
Author SHA1 Message Date
lucas 2e273985b7 download ubuntu images and keep them current 2026-10-14 20:51:31 +00:00
lucas f7865f05a1 script to reference moved song in playlists 2026-10-14 20:51:31 +00:00
lucas 719c7068e2 smartd.conf add start stop hostname, qbittorrenthost 2026-10-14 17:43:31 +02:00
lucas 580b667119 node exporter: counter corretion for samsung hdd 2026-10-14 17:42:52 +02:00
lucas 3bf1fc1be6 add exportfs config
ads
2026-10-14 07:31:43 +02:00
lucas 7b0b438740 add nextcloud app update to upgrade script 2026-10-13 20:15:03 +02:00
lucas 2eda7cd33e align convert heic with mediahost and new picture sync
asd
2026-10-13 20:15:03 +02:00
lucas efc150d9ce ssh config and hosts
asd
2026-10-13 20:15:03 +02:00
lucas 044fbd81ad working smartmon node exporter script for sd/nvme 2026-10-12 21:54:40 +02:00
lucas 01ab319eea node exporter: add hostname dependent docker count and default value for smartd script 2026-10-12 19:19:15 +00:00
lucas d5e627325d add quiethost to smartd 2026-10-12 20:49:53 +02:00
lucas deaff35bc3 remove raspberry from bash_aliases
add mediahost to wol.sh
2026-10-12 20:40:34 +02:00
lucas 27d570fc5c node exporter script for smartd 2026-10-12 18:39:53 +00:00
lucas d5fb01adb2 docker backup serverhost
add cadvisor to serverhost
change node-exporter to network host to see propper netw traffic
refine torrentscomplete script
2026-10-12 20:10:54 +02:00
lucas 52c02beb3d mediahost docker backup
add gite to shared proxy
add usb dev and NET privilige to HA
add immich image server
remove sonarr-en
add jackett indexer for ABB
add gluetun-proxy for general proxy
add blackbox exporter to check https sites
set node-exporter to network host to see interface traffic
decrease resolution of cadvisor to save RAM
add status and code SANs for nginx
add upstream block so sites are not redirecte to cloud...
add homeassistant config
add nginx exporter for prometheus
2026-10-12 18:10:41 +00:00
lucas 3f14f53184 add serverhost to smartd.conf 2026-10-12 17:59:00 +00:00
lucas c41bf36afb add smartd conf 2026-10-12 17:50:54 +00:00
lucas 07bab58ae0 add smartctl service 2026-10-12 15:01:20 +00:00
29 changed files with 788 additions and 152 deletions

No files matched your search

@@ -16,4 +16,10 @@ services:
- /data/gitea:/data
- /etc/timezone:/etc/timezone:ro
- /etc/localtime:/etc/localtime:ro
networks:
- default
- shared-proxy-services
networks:
default:
shared-proxy-services:
external: true
@@ -9,6 +9,11 @@ services:
TZ: Europe/Vienna
volumes:
- /srv/homeassistant:/config
devices:
- /dev/bus/usb:/dev/bus/usb
cap_add:
- NET_ADMIN
- NET_RAW
mosquitto:
container_name: mosquitto
@@ -0,0 +1,81 @@
#
# WARNING: To install Immich, follow our guide: https://docs.immich.app/install/docker-compose
#
# Make sure to use the docker-compose.yml of the current release:
#
# https://github.com/immich-app/immich/releases/latest/download/docker-compose.yml
#
# The compose file on main may not be compatible with the latest release.
name: immich
services:
immich-server:
container_name: immich_server
image: ghcr.io/immich-app/immich-server:${IMMICH_VERSION:-release}
# extends:
# file: hwaccel.transcoding.yml
# service: cpu # set to one of [nvenc, quicksync, rkmpp, vaapi, vaapi-wsl] for accelerated transcoding
volumes:
# Do not edit the next line. If you want to change the media storage location on your system, edit the value of UPLOAD_LOCATION in the .env file
- ${UPLOAD_LOCATION}:/data
- /data/immich/pictures:/libary
- /etc/localtime:/etc/localtime:ro
env_file:
- .env
ports:
- '2283:2283'
depends_on:
- database
restart: always
healthcheck:
disable: false
networks:
- immich
- shared-redis-services
immich-machine-learning:
container_name: immich_machine_learning
# For hardware acceleration, add one of -[armnn, cuda, rocm, openvino, rknn] to the image tag.
# Example tag: ${IMMICH_VERSION:-release}-cuda
image: ghcr.io/immich-app/immich-machine-learning:${IMMICH_VERSION:-release}
# 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:
- model-cache:/cache
env_file:
- .env
restart: always
healthcheck:
disable: false
networks:
- immich
database:
container_name: immich_postgres
image: ghcr.io/immich-app/postgres:14-vectorchord0.4.3-pgvectors0.2.0@sha256:bcf63357191b76a916ae5eb93464d65c07511da41e3bf7a8416db519b40b1c23
environment:
POSTGRES_PASSWORD: ${DB_PASSWORD}
POSTGRES_USER: ${DB_USERNAME}
POSTGRES_DB: ${DB_DATABASE_NAME}
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:
# Do not edit the next line. If you want to change the database storage location on your system, edit the value of DB_DATA_LOCATION in the .env file
- ${DB_DATA_LOCATION}:/var/lib/postgresql/data
shm_size: 128mb
restart: always
healthcheck:
disable: false
networks:
- immich
volumes:
model-cache:
networks:
immich:
shared-redis-services:
external: true
@@ -15,7 +15,6 @@ services:
networks:
- default
- shared-proxy-services
seerr:
image: ghcr.io/seerr-team/seerr:latest
container_name: seerr
@@ -29,6 +28,7 @@ services:
networks:
- default
- shared-proxy-services
networks:
default:
external: true
@@ -1,22 +1,5 @@
services:
sonarr-en:
image: lscr.io/linuxserver/sonarr:latest
container_name: sonarr-en
restart: unless-stopped
ports:
- "8989:8989"
environment:
- PUID=1000
- PGID=1000
- TZ=Europe/Berlin
volumes:
- ./sonarr_EN:/config
- /data/jellyfin/media/series-english:/JellyfinSeriesEnglish
- /data/jellyfin/media/anime-english:/JellyfinAnimeEnglish
- /data/jellyfin/media/documentaries-english:/JellyfinDocus
- /data/jellyfin/buffer:/buffer
- /torrent/qbittorrent/downloads:/downloads
sonarr-de:
image: lscr.io/linuxserver/sonarr:latest
container_name: sonarr-de
@@ -31,10 +14,13 @@ services:
- ./sonarr_DE:/config
- /data/jellyfin/media/series-german:/JellyfinSeriesGerman
- /data/jellyfin/media/anime-german:/JellyfinAnimeGerman
- /data/jellyfin/media/series-english:/JellyfinSeriesEnglish
- /data/jellyfin/media/anime-english:/JellyfinAnimeEnglish
- /data/jellyfin/media/documentaries-english:/JellyfinDocus
- /data/jellyfin/media/series-kids:/JellyfinKinder
- /data/jellyfin/buffer:/buffer
- /torrent/qbittorrent/downloads:/downloads
- /torrent/rundfunkarr:/downloads-rundfunkarr
- /torrent/rundfunkarr-de:/downloads-rundfunkarr
radarr-en:
image: lscr.io/linuxserver/radarr:latest
container_name: radarr-en
@@ -67,7 +53,7 @@ services:
- /data/jellyfin/media/movies-kids:/JellyfinKinder
- /data/jellyfin/buffer:/buffer
- /torrent/qbittorrent/downloads:/downloads
- /torrent/rundfunkarr:/downloads-rundfunkarr
- /torrent/rundfunkarr-de:/downloads-rundfunkarr
prowlarr:
image: lscr.io/linuxserver/prowlarr:latest
container_name: prowlarr
@@ -177,7 +163,7 @@ services:
- TZ=Europe/Berlin
volumes:
- ./lidarr:/config
- /data/navidrome/music:/music
- /data/navidrome/music/music:/music
- /torrent/qbittorrent/downloads:/downloads
ports:
@@ -261,14 +247,43 @@ services:
- /data/jellyfin/media/comedy-english:/data/comedy-english:ro
- /data/jellyfin/media/movies-german:/data/movies-german:ro
- /data/jellyfin/media/movies-kids:/data/movies-kids:ro
# - /data/audiobookshelf/podcasts:/podcasts
# - /data/audiobookshelf/audiobooks-englisch:/audiobooks
- /data/navidrome/music:/data/music:ro
- /data/audiobookshelf/data/audiobooks-englisch:/data/audiobooks-english:ro
- /data/audiobookshelf/data/audiobooks-deutsch:/data/audiobooks-german:ro
- /data/audiobookshelf/data/audiobooks-kinder:/data/audiobooks-kinder:ro
# Download location
- /torrent/qbittorrent/downloads:/downloads
jackett:
image: lscr.io/linuxserver/jackett:latest
container_name: jackett
environment:
- PUID=1000
- PGID=1000
- TZ=Europe/Vienna
volumes:
- ./jackett/config:/config
- ./jackett/downloads:/downloads
ports:
- "9117:9117"
restart: unless-stopped
gluetun-proxy:
image: qmcgaw/gluetun:latest
container_name: gluetun-proxy
cap_add:
- NET_ADMIN
ports:
- "8889:8888" # HTTP proxy
- "8388:8388" # SOCKS5 proxy
volumes:
- ./gluetun-proxy:/gluetun/wireguard
- /dev/net/tun:/dev/net/tun
environment:
- VPN_SERVICE_PROVIDER=custom
- VPN_TYPE=wireguard
- SOCKS5_ENABLED=on
- HTTPPROXY=on
- SOCKSPROXY=on
restart: unless-stopped
networks:
default:
@@ -0,0 +1,11 @@
#
# Use this configuration with WireGuard client
#
[Interface]
Address = 10.14.0.2/16
PrivateKey = mKeDQdxtM1iFJS7WLlb2jPGabZIt3NkoA/nGCcNOU1I=
DNS = 162.252.172.57, 149.154.159.92
[Peer]
PublicKey = dPZe8Jq3Hu0k07MDk+Y4+AS2XHSLYalyg91TSFXRYEA=
AllowedIPs = 0.0.0.0/0
Endpoint = 87.249.133.4:51820
@@ -0,0 +1,8 @@
modules:
http_2xx:
prober: http
timeout: 5s
http:
valid_status_codes: []
method: GET
preferred_ip_protocol: ip4
@@ -8,6 +8,9 @@ services:
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml:ro
- prometheus-data:/prometheus
networks:
- default
- shared-proxy-services
grafana:
image: grafana/grafana:latest
@@ -47,9 +50,9 @@ services:
volumes:
- '/:/host:ro,rslave'
- ./node_exporter/textfile_collector:/textfile:ro
ports:
- '9100:9100'
# ports:
# - '9100:9100'
network_mode: host
cadvisor:
image: gcr.io/cadvisor/cadvisor:latest
container_name: cadvisor
@@ -58,9 +61,24 @@ services:
- "8080:8080"
volumes:
- /:/rootfs:ro
- /data:/data:ro
- /docker:/docker:ro
# - /data:/data:ro
# - /docker:/docker:ro
- /var/run:/var/run:ro
- /sys:/sys:ro
- /var/lib/docker:/var/lib/docker:ro
command:
- "--disable_metrics=percpu,tcp,udp,process,sched"
- "--housekeeping_interval=30s"
- "--housekeeping_interval=1m"
- "--docker_only=true"
blackbox-exporter:
image: prom/blackbox-exporter:latest
container_name: blackbox-exporter
restart: unless-stopped
ports:
- "9115:9115"
volumes:
- ./blackbox.yml:/etc/blackbox_exporter/config.yml:ro
volumes:
prometheus-data:
grafana-data:
@@ -1,6 +1,6 @@
global:
scrape_interval: 15s
evaluation_interval: 15s
scrape_interval: 30s
evaluation_interval: 30s
scrape_configs:
@@ -8,6 +8,35 @@ scrape_configs:
static_configs:
- targets:
- "prometheus:9090"
- job_name: "nginx"
static_configs:
- targets:
- nginx-exporter:9113
- job_name: blackbox_https
metrics_path: /probe
params:
module: [http_2xx]
static_configs:
- targets:
- https://cloud.someoneslinux.selfhost.eu
- https://media.someoneslinux.selfhost.eu
- https://audiobooks.someoneslinux.selfhost.eu
# - https://login.someoneslinux.selfhost.eu
- https://auto.someoneslinux.selfhost.eu
- https://music.someoneslinux.selfhost.eu
- https://passwd.someoneslinux.selfhost.eu
- https://requests.someoneslinux.selfhost.eu
- https://torrent.someoneslinux.selfhost.eu
- https://status.someoneslinux.selfhost.eu
relabel_configs:
- source_labels: [__address__]
target_label: __param_target
- source_labels: [__param_target]
target_label: instance
- target_label: __address__
replacement: blackbox-exporter:9115
- job_name: "node-exporter"
static_configs:
@@ -16,20 +45,33 @@ scrape_configs:
labels:
host: serverhost
- targets:
- "node-exporter:9100"
- "192.168.0.4:9100"
labels:
host: "mediahost"
- targets:
- "192.168.0.39:9100"
labels:
host: "quiethost"
- job_name: "cadvisor"
static_configs:
- targets:
- "cadvisor:8080"
labels:
host: mediahost
- targets:
- "192.168.0.2:8081"
labels:
host: serverhost
- job_name: "smartctl"
static_configs:
- targets:
- "192.168.0.2:9633"
labels:
host: serverhost
- targets:
- "192.168.0.39:9633"
labels:
host: "quiethost"
- targets:
- "192.168.0.4:9633"
labels:
@@ -23,6 +23,7 @@ services:
- /data/navidrome/music/kamerun:/kamerun:ro
- /data/navidrome/music/weihnachten:/weihnachten:ro
- /data/navidrome/music/playlists:/playlists:ro
- /data/navidrome/music/playlists-export:/playlists-export
networks:
- shared-proxy-services
- default
@@ -17,7 +17,8 @@ server {
passwd.someoneslinux.selfhost.eu
requests.someoneslinux.selfhost.eu
torrent.someoneslinux.selfhost.eu
status.someoneslinux.selfhost.eu;
status.someoneslinux.selfhost.eu
code.someoneslinux.selfhost.eu;
#ssl_conf_command Groups X25519:secp256r1:secp384r1;
# ssl_conf_command Groups X25519:prime256v1:secp384r1;
location /.well-known/acme-challenge/ {
@@ -27,12 +28,28 @@ server {
location / {
return 301 https://$host$request_uri;
}
listen 8080;
location /nginx_status {
stub_status;
allow 172.16.0.0/12;
deny all;
}
}
# Common SSL settings
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
server {
listen 443 ssl default_server;
server_name _;
ssl_certificate /etc/nginx/certs/live/cloud.someoneslinux.selfhost.eu/fullchain.pem;
ssl_certificate_key /etc/nginx/certs/live/cloud.someoneslinux.selfhost.eu/privkey.pem;
return 404;
}
###################
# NEXTCLOUD
@@ -51,6 +68,8 @@ server {
location / {
proxy_pass http://nextcloud:80;
# Do not try another upstream on errors
proxy_next_upstream off;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
@@ -76,6 +95,8 @@ server {
location / {
proxy_pass http://jellyfin:8096;
# Do not try another upstream on errors
proxy_next_upstream off;
proxy_http_version 1.1;
proxy_set_header Host $host;
@@ -103,6 +124,8 @@ server {
location / {
proxy_pass http://audiobookshelf:80;
# Do not try another upstream on errors
proxy_next_upstream off;
proxy_http_version 1.1;
proxy_set_header Host $host;
@@ -112,40 +135,14 @@ server {
}
}
###################
# AUTHENTIK
###################
server {
listen 443 ssl;http2 on;
server_name login.someoneslinux.selfhost.eu;
add_header Content-Security-Policy "frame-ancestors 'self';" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
ssl_certificate /etc/nginx/certs/live/cloud.someoneslinux.selfhost.eu/fullchain.pem;
ssl_certificate_key /etc/nginx/certs/live/cloud.someoneslinux.selfhost.eu/privkey.pem;
location / {
proxy_pass http://authentik-server-1:9000;
proxy_http_version 1.1;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
####################
## HOME ASSISTANT
## AUTHENTIK
####################
#server {
# listen 443 ssl;http2 on;
# server_name auto.someoneslinux.selfhost.eu;
# server_name login.someoneslinux.selfhost.eu;
#
# add_header Content-Security-Policy "default-src 'self'; frame-ancestors 'self';" always;
# add_header Content-Security-Policy "frame-ancestors 'self';" always;
# add_header X-Frame-Options "SAMEORIGIN" always;
# add_header X-Content-Type-Options "nosniff" always;
# add_header Referrer-Policy "strict-origin-when-cross-origin" always;
@@ -155,17 +152,45 @@ server {
# ssl_certificate_key /etc/nginx/certs/live/cloud.someoneslinux.selfhost.eu/privkey.pem;
#
# location / {
# proxy_pass http://192.168.0.4:8123;
# proxy_pass http://authentik-server-1:9000;
# proxy_http_version 1.1;
#
# proxy_set_header Host $host;
# proxy_set_header Upgrade $http_upgrade;
# proxy_set_header Connection $connection_upgrade;
# proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# proxy_set_header X-Forwarded-Proto https;
# proxy_set_header X-Forwarded-Host $host;
# proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# }
#}
###################
# HOME ASSISTANT
###################
server {
listen 443 ssl;http2 on;
server_name auto.someoneslinux.selfhost.eu;
# add_header Content-Security-Policy "default-src 'self'; frame-ancestors 'self';" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
ssl_certificate /etc/nginx/certs/live/cloud.someoneslinux.selfhost.eu/fullchain.pem;
ssl_certificate_key /etc/nginx/certs/live/cloud.someoneslinux.selfhost.eu/privkey.pem;
location / {
proxy_pass http://192.168.0.4:8123;
# Do not try another upstream on errors
proxy_next_upstream off;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto https;
}
}
###################
# NAVIDROME
###################
@@ -184,6 +209,8 @@ server {
location / {
proxy_pass http://navidrome:4533;
# Do not try another upstream on errors
proxy_next_upstream off;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header X-Real-IP $remote_addr;
@@ -208,6 +235,8 @@ server {
location / {
proxy_pass http://vaultwarden:80;
# Do not try another upstream on errors
proxy_next_upstream off;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto https;
@@ -216,6 +245,8 @@ server {
location /notifications/hub {
proxy_pass http://vaultwarden:3012;
# Do not try another upstream on errors
proxy_next_upstream off;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
@@ -240,6 +271,8 @@ server {
location / {
proxy_pass http://seerr:5055;
# Do not try another upstream on errors
proxy_next_upstream off;
proxy_http_version 1.1;
proxy_set_header Host $host;
@@ -268,6 +301,8 @@ server {
location / {
proxy_pass http://192.168.0.2:8080;
# Do not try another upstream on errors
proxy_next_upstream off;
proxy_http_version 1.1;
proxy_set_header Host $host;
@@ -275,6 +310,7 @@ server {
proxy_set_header Connection $connection_upgrade;
proxy_set_header X-Forwarded-Proto https;
}
}
###################
@@ -294,6 +330,8 @@ server {
location / {
proxy_pass http://grafana:3000;
# Do not try another upstream on errors
proxy_next_upstream off;
proxy_http_version 1.1;
proxy_set_header Host $host;
@@ -302,3 +340,33 @@ server {
proxy_set_header X-Forwarded-Proto https;
}
}
###################
# GITEA
###################
server {
listen 443 ssl;http2 on;
server_name code.someoneslinux.selfhost.eu;
add_header Content-Security-Policy "frame-ancestors 'self';" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
ssl_certificate /etc/nginx/certs/live/cloud.someoneslinux.selfhost.eu/fullchain.pem;
ssl_certificate_key /etc/nginx/certs/live/cloud.someoneslinux.selfhost.eu/privkey.pem;
location / {
proxy_pass http://gitea:3000;
# Do not try another upstream on errors
proxy_next_upstream off;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
}
}
@@ -3,11 +3,9 @@ services:
image: nginx:stable
container_name: nginx
restart: unless-stopped
ports:
- "80:80"
- "443:443"
volumes:
- ./conf.d:/etc/nginx/conf.d
- ./certs:/etc/nginx/certs
@@ -15,6 +13,21 @@ services:
# Access and error logs
- ./logs:/var/log/nginx
networks:
- default
- shared-proxy-services
nginx-exporter:
image: nginx/nginx-prometheus-exporter:latest
container_name: nginx-exporter
restart: unless-stopped
command:
- --nginx.scrape-uri=http://nginx:8080/nginx_status
ports:
- "9113:9113"
depends_on:
- nginx
networks:
- default
- shared-proxy-services
crowdsec:
@@ -29,7 +42,8 @@ services:
- crowdsec-db:/var/lib/crowdsec/data
- ./logs:/var/log/nginx:ro
- /etc/localtime:/etc/localtime:ro
networks:
- default
certbot:
image: certbot/certbot:latest
@@ -41,7 +55,9 @@ services:
- shared-proxy-services
networks:
default:
shared-proxy-services:
external: true
volumes:
crowdsec-db:
@@ -3,7 +3,7 @@ services:
image: redis:7
container_name: redis
restart: unless-stopped
command: redis-server --appendonly yes --requirepass PerCent7heStorySp0tInOrd3r
command: redis-server --appendonly yes --requirepass ${REDIS_PASSWORD}
healthcheck:
test:
@@ -10,6 +10,19 @@ services:
volumes:
- '/:/host:ro,rslave'
- ./node_exporter/textfile_collector:/textfile:ro
# ports:
# - '9100:9100'
network_mode: host
cadvisor:
image: gcr.io/cadvisor/cadvisor:latest
container_name: cadvisor
restart: unless-stopped
ports:
- '9100:9100'
- "8081:8080"
volumes:
- /:/rootfs:ro
- /data:/data:ro
- /docker:/docker:ro
- /var/run:/var/run:ro
- /sys:/sys:ro
- /var/lib/docker:/var/lib/docker:ro
@@ -72,8 +72,8 @@ fi
TORRENT_NAME="$1"
ROOT_PATH="$2"
CATEGORY="$3"
if [[ "$CATEGORY" != *arr* && "$CATEGORY" != "mytorrents" ]]; then
if [[ "$CATEGORY" != *arr* ]]; then
###############################################################################
# Start
###############################################################################
@@ -155,7 +155,7 @@ if [[ "$CATEGORY" != *arr* ]]; then
lucas@mediahost "mkdir -p \"/torrent/qbittorrent/mediahost/$remote_dir\""
SSH_STATUS=$?
scp -i /config/.ssh/id_ed25519 -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null \
-r "$ROOT_PATH"/. lucas@mediahost:/torrent/qbittorrent/mediahost/
-r "$ROOT_PATH"/. lucas@mediahost:/torrent/qbittorrent/mediahost/$remote_dir/
SCP_STATUS=$?
echo "scp exit status: $SCP_STATUS"
+8 -5
View File
@@ -167,19 +167,22 @@ process_file() {
HOSTNAME_EXPECTED="mediahost"
SOURCE_DIR="/data/nextcloud/syncuser/alina/Dropfolder"
TARGET_DIR="/data/nextcloud/syncuser/camera"
SOURCE_DIR="/data/nextcloud/syncuser/pictures/Alina Share/Dropfolder"
TARGET_DIR="/data/nextcloud/syncuser/pictures/Camera"
# If running on serverhost, perform initial sync
if [[ "$(hostname)" == "$HOSTNAME_EXPECTED" ]]; then
syncNC -d -c
echo Sync Nextcloud
syncNC -c
cd "$SOURCE_DIR" || exit 1
fi
if [[ $# -gt 0 ]]; then
echo Process single file $1
process_file "$1"
else
echo Process dir .
shopt -s nullglob
files=( *.heic *.mov )
@@ -202,7 +205,7 @@ if [[ "$(hostname)" == "$HOSTNAME_EXPECTED" ]]; then
fi
done
shopt -u nullglob
syncNC -d -c
echo Sync Nextcloud
syncNC -c
fi
+164
View File
@@ -0,0 +1,164 @@
#!/usr/bin/env python3
import os
import re
import logging
from pathlib import Path
dry_run = True
WORKDIR = Path("/data/navidrome/music/")
PLAYLIST_DIR = WORKDIR / "playlists"
MUSIC_DIR = WORKDIR / "music"
AUDIO_EXTS = {
".mp3", ".flac", ".m4a", ".ogg", ".opus",
".aac", ".wav", ".ape"
}
logger = logging.getLogger(__name__)
logging.basicConfig(
level=logging.DEBUG,
format="%(asctime)s %(levelname)s %(message)s",
handlers=[
#logging.FileHandler("reference_playlists.log"),
logging.StreamHandler()
]
)
logger.info('Started')
def words(text):
return set(re.findall(r"\b[\w']+\b", text.lower()))
def find_replacement(old_path):
p = Path(old_path)
# Find the second "music" directory
music_idx = p.parts.index("music", p.parts.index("music") + 1)
folder_count = len(p.parts) - music_idx - 2
try:
artist = p.parts[-(folder_count + 1)] # /music/Artist/Album/File
logger.debug(f"Artist: {artist}")
except IndexError:
logger.error(f"No Artist found for {p}")
return None
artist_dir = Path(MUSIC_DIR) / artist
logger.debug(f"Artist path: {artist_dir}")
if not artist_dir.exists():
logger.error(f"Artist dir {artist_dir} dors not exist")
return None
if folder_count > 1:
try:
album = p.parts[-(folder_count)] # .../Artist/Album/File
logger.debug(f"Album: {album}")
except IndexError:
logger.error(f"No album found for {p}")
return None
album_dir = Path(MUSIC_DIR).rglob(album)
try:
album_dir = next(album_dir)
logger.debug(f"Album path: {album_dir}")
except StopIteration:
logger.error(f"Album dir for '{album}' does not exist")
return None
search_words = words(p.stem)
best_match = None
best_score = 0
for root, _, files in os.walk(artist_dir):
for filename in files:
candidate = Path(root) / filename
candidate_parts = candidate.stem.split(" - ")
logger.debug(f"Candidate: {candidate}")
logger.debug(f"parts: {candidate_parts}")
if candidate.suffix.lower() not in AUDIO_EXTS:
continue
if len(candidate_parts) == 4:
logger.debug(f"Lidarr Filename: {len(candidate_parts)} ")
candidate_words = words(" ".join(candidate_parts[2:]))
logger.debug(f"Go on with: {candidate_words} ")
score = len(search_words & candidate_words)
if score > best_score:
best_score = score
best_match = candidate
else:
continue
logger.debug(f"Fallback Filename: {len(candidate_parts)} ")
candidate_words = words(candidate.stem)
logger.debug(f"words: {candidate_words}")
score = len(search_words & candidate_words)
if score > best_score:
best_score = score
best_match = candidate
# Require all words to match
if best_match and best_score == len(search_words):
return str(best_match)
return None
def main():
for playlist in Path(PLAYLIST_DIR).glob("*.m3u"):
logger.info(f"\nProcessing {playlist}")
changed = False
output = []
with open(playlist, "r", encoding="utf-8", errors="ignore") as f:
lines = f.readlines()
for line in lines:
if not line or line.startswith("#"):
output.append(line)
continue
path = WORKDIR / Path(line.strip()).relative_to("/")
if not path.is_absolute() or path.exists():
output.append(path)
continue
logger.info(f"Missing: {path}")
replacement = find_replacement(path)
if replacement:
logger.info(f" -> Found: {replacement}")
output.append(replacement + "\n")
changed = True
else:
logger.info(" -> No match")
output.append(line)
exit()
if changed and not dry_run:
backup = playlist.with_suffix(playlist.suffix + ".bak")
if not backup.exists():
backup.write_text(
playlist.read_text(encoding="utf-8"),
encoding="utf-8"
)
with open(playlist, "w", encoding="utf-8") as f:
f.writelines(output)
logger.info("Updated playlist")
if __name__ == "__main__":
main()
+39
View File
@@ -0,0 +1,39 @@
#!/bin/bash
OUT="/docker/monitoring/node_exporter/textfile_collector/smart_selftest.prom"
> "$OUT"
for dev in $(smartctl --scan-open | awk '{print $1}'); do
name=$(basename "$dev")
LAST=0
if [[ "$dev" == *nvme* ]]; then
POWER_ON=$(smartctl -a "$dev" | awk -F': *' '/Power On Hours:/ {print $2}')
LAST=$(smartctl -l selftest "$dev" 2>/dev/null \
| grep "Completed" \
| head -1 \
| awk '{print $(NF-5)}')
elif [[ "$dev" == *sd* ]]; then
POWER_ON=$(smartctl -a "$dev" | awk '/Power_On_Hours/ {print $10}')
LAST=$(smartctl -l selftest "$dev" 2>/dev/null \
| grep "Completed" \
| head -1 \
| awk '{print $(NF-1)}')
MODEL=$(smartctl -i "$dev" | awk -F': *' '/Device Model/ {print $2}')
# ST2000LM003 self-test hour counter rolls over at 65536
if [[ "$MODEL" == "ST2000LM003 HN-M201RAD" ]] && \
[[ "$LAST" =~ ^[0-9]+$ ]] && \
[[ "$POWER_ON" =~ ^[0-9]+$ ]] && \
(( POWER_ON > 65535 && LAST < 65536 )); then
LAST=$((LAST + 65536))
fi
else
POWER_ON=99999999999
echo $dev
fi
# Skip devices without self-test history
echo $name: Last: ${LAST}, PowerOn: ${POWER_ON}
echo "smart_last_selftest_poweron_hours{device=\"$name\"} $LAST" >> "$OUT"
done
@@ -2,7 +2,13 @@
OUT=/docker/monitoring/node_exporter/textfile_collector/custom.prom
TS=$(date +%s%3N)
if [[ "$(hostname)" == "mediahost" ]]; then
DOCKER_CONTAINER_NUM=44
elif [[ "$(hostname)" == "serverhost" ]]; then
DOCKER_CONTAINER_NUM=4
elif [[ "$(hostname)" == "quiethost" ]]; then
DOCKER_CONTAINER_NUM=1
fi
{
# Docker container states
docker ps -a --format '{{.Names}}' | while read -r name; do
+2
View File
@@ -2,6 +2,8 @@
device=$1
if [ "$device" == "serverhost" ]; then
mac="64:51:06:51:cb:39"
elif [ "$device" == "mediahost" ]; then
mac="9c:6b:00:a3:36:c7"
elif [ "$device" == "quiethost" ]; then
mac="24:4B:FE:DE:93:3E"
elif [ "$(echo ${device} | grep -E -o "([0-9A-Fa-f]{2}[\:]){5}[0-9A-Fa-f]{2}")" != "" ]; then
+1 -18
View File
@@ -25,7 +25,6 @@ SYNC_MEMES=1
SYNC_AUDIOBOOKS=1
SYNC_RECIPIES=1
SYNC_ALINA=1
SYNC_ALINA_DROP=1
SYNC_WALLPAPER=1
SYNC_PICTURES=1
SYNC_SYNCFOLDER=1
@@ -39,13 +38,12 @@ Synchronize configured directories with Nextcloud.
Options:
-h, --help Show this help message and exit
-l Show synchronization output
-d Enable Alina Share synchronization
-c Enable Pictures synchronization
-w Enable Wallpaper synchronization
-m Enable Memes synchronization
-s Enable Syncfolder synchronization
-ab Enable Audiobook synchronization
-al Enable Alina synchronization
-al Enable Alina Documents synchronization
-all Enable all synchronization operations
-del Remove the Nextcloud sync marker
--version Show script version
@@ -109,11 +107,6 @@ parse_args() {
-w)
SYNC_WALLPAPER=0
;;
-d)
SYNC_ALINA_DROP=0
;;
-s)
SYNC_SYNCFOLDER=0
;;
@@ -139,7 +132,6 @@ parse_args() {
SYNC_RECIPIES=0
SYNC_ALINA=0
SYNC_MEMES=0
SYNC_ALINA_DROP=0
SYNC_WALLPAPER=0
SYNC_PICTURES=0
;;
@@ -172,7 +164,6 @@ validate_sync_options() {
SYNC_ALINA == 1 &&
SYNC_MEMES == 1 &&
SYNC_SYNCFOLDER == 1 &&
SYNC_ALINA_DROP == 1 &&
SYNC_WALLPAPER == 1 &&
SYNC_PICTURES == 1 )); then
@@ -202,14 +193,6 @@ sync_all() {
"/data/nextcloud/syncuser/Syncfolder"
(( ret += $? ))
fi
if (( SYNC_ALINA_DROP == 0 )); then
sync_directory \
"Alina Share" \
"Alina Share/" \
"/data/nextcloud/syncuser/alina"
(( ret += $? ))
fi
if (( SYNC_MEMES == 0 )); then
sync_directory \
"Memes" \
+4 -52
View File
@@ -1,24 +1,6 @@
HOST=$(hostname)
if [ "${HOST}" == "quiethost" ]; then
DOC_DIR="/home/lucas/Documents"
UNSYNCED="SW"
elif [ "${HOST}" == "vivohost" ];then
UNSYNCED="Music\nSW\nPictures\nDokumente/Studium\nDokumente/Auslandsdienst"
DOC_DIR="/home/lucas/Documents"
rasp_host="someoneslinux.ddns.net"
elif [ "${HOST}" != "raspberry" ]; then
UNSYNCED="Music\nSW\nPictures "
DOC_DIR="/home/lucas/Documents"
fi
if [ "${HOST}" == "raspberry" ]; then
LOCAL_SCRIPTS="/home/lucas/Raspberry/scripts"
DOC_DIR="/home/lucas/Documents"
else
LOCAL_SCRIPTS="/home/lucas/scripts"
rasp_host=raspberry
fi
NC_SCRIPTS="$DOC_DIR/Dokumente/Projekte/Server/scripts"
alias please="sudo"
alias NC_scripts="cd ${NC_SCRIPTS}"
alias regex_rename="${LOCAL_SCRIPTS}/rename.sh"
@@ -35,6 +17,10 @@ alias pubip="wget -T 5 -qO- ifconfig.co"
alias pubip_country="wget -T 5 -qO- ifconfig.co/country"
alias ipinfo='${LOCAL_SCRIPTS}/ip_info.sh'
alias pygen="/home/lucas/scripts/.venv/bin/python3"
alias mediawake="bash ${LOCAL_SCRIPTS}/network/wol.sh mediahost -c"
alias serverwake="bash ${LOCAL_SCRIPTS}/network/wol.sh serverhost -c"
alias quietwake="bash ${LOCAL_SCRIPTS}/network/wol.sh quiethost"
if [[ "${HOST}" == "quiethost" ]] || [[ "${HOST}" == "serverhost" ]]; then
### Veracrypt aliases
#Passwd Mount and Grep
@@ -52,40 +38,6 @@ if [[ "${HOST}" == "quiethost" ]] || [[ "${HOST}" == "serverhost" ]]; then
alias recipeAI="~/.venv_general/bin/python3 ~/scripts/quiethost/generateNutritionInfowithGemini.py /data/Nextcloud/Documents/Dokumente/Shared/Diverses/Kochbuch/RecepiesLucas/"
alias ffmepeg_handling="~/.venv_general/bin/python3 ~/scripts/ffmpeg_handling.py"
fi
if [ "${HOST}" != "raspberry" ]; then
# Shutdown
alias alldown='ssh ${rasp_host} hostdown all -c'
alias serverdown='ssh ${rasp_host} hostdown serverhost -c'
alias delldown='ssh ${rasp_host} hostdown quiethost -c'
# Wake
alias serverwake="ssh ${rasp_host} wake serverhost"
alias quietwake="bash ${LOCAL_SCRIPTS}/network/wol.sh quiethost"
# SSH
alias rasp="ssh ${rasp_host}"
alias raspcopy='bash ${LOCAL_SCRIPTS}/copy.sh -h ${rasp_host} -f '
#NW Stat
alias NWscan="ssh ${rasp_host} hoststatus netw -c"
alias hoststat="ssh ${rasp_host} hoststatus hosts -c"
elif [ "${HOST}" != "vivohost" ];then
# Raspberry Shutdown
alias serverdown='hostdown serverhost -c'
alias delldown='hostdown quiethost -c'
alias alldown='hostdown all -c'
alias pcdown='hostdown pc -c'
# Raspberry Wake
alias serverwake='wake serverhost'
alias quietwake='wake quiethost'
# Raspberry Hoststatus
alias hoststat="hoststatus hosts -c"
alias NWscan="hoststatus netw -c"
# Raspberry Network Settings
alias IFchange="sudo bash ${LOCAL_SCRIPTS}/IFchange.sh"
alias IPsettings="sudo bash /home/lucas/Raspberry/scripts/iptables.sh"
alias IPtables-save='sudo sh -c '\''iptables-save > /etc/network/iptables'\'''
# Raspberry Owncloud
alias syncNC="nextcloudcmd --path Dokumente/Dokumente/Projekte/Server /home/lucas/Documents/Dokumente/Projekte/Server https://lucas:S1mpleRe1e4sedP1ayingDesign@someoneslinux.ddns.net"
fi
if [ "${HOST}" != "serverhost" ]; then
alias serverhost="ssh -X serverhost"
alias lstorr="ssh serverhost du -a -d1 -h /torrent/complete/ | sed 's/\/torrent\/complete\///'g | head -n -1"
+15
View File
@@ -0,0 +1,15 @@
# /etc/exports: the access control list for filesystems which may be exported
# to NFS clients. See exports(5).
#
# Example for NFSv2 and NFSv3:
# /srv/homes hostname1(rw,sync,no_subtree_check) hostname2(ro,sync,no_subtree_check)
#
# Example for NFSv4:
# /srv/nfs4 gss/krb5i(rw,sync,fsid=0,crossmnt,no_subtree_check)
# /srv/nfs4/homes gss/krb5i(rw,sync,no_subtree_check)
#
# sudo apt install nfs-kernel-server
# sudo exportfs -ra
/torrent/qbittorrent/downloads 192.168.0.4(rw,sync,no_subtree_check)
/backup/homeassistant 192.168.0.4(rw,sync,no_subtree_check)
+5
View File
@@ -0,0 +1,5 @@
192.168.0.2 serverhost qbittorrenthost
192.168.0.39 quiethost
192.168.0.4 mediahost
192.168.0.81 vivohost
#192.168.0.122 homeassistant
+83
View File
@@ -0,0 +1,83 @@
## /etc/smartd.conf
# ============================================================================
# Common options:
#
# -a Enable all standard SMART monitoring:
# * SMART health status
# * Error logs
# * Self-test logs
# * Attribute monitoring
#
# -o on Enable automatic offline data collection
#
# -S on Enable SMART attribute autosave
#
# -s (...) Schedule SMART self-tests
#
# Test schedule syntax:
# S = Short self-test
# L = Long/Extended self-test
#
# Fields:
# (TYPE/MM/DD/DW/HH)
#
# MM = month (01-12 or .. for every month)
# DD = day of month (01-31 or .. for every day)
# DW = day of week (1-7, where 7=Sunday)
# HH = hour (00-23)
#
# Schedule used below:
# S/../../7/02
# → Run SHORT test every Sunday at 02:00
#
# L/../01/./03
# → Run LONG test on the 1st day of every month at 03:00
#
## serverhost
#
# # WD Red 3 TB Backup Drive
#/dev/sda -a -o on -S on -s (S/../../7/02|L/../01/./03)
# Samsung/Seagate 2 TB Laptop Drive
# /dev/sdb -a -o on -S on -s (S/../../7/02|L/../01/./03)
## serverhost end
## mediahost
#
## WD Gold 16 TB
#/dev/sda -a -o on -S on -s (S/../../7/02|L/../01/./03)
#
## WD Red Pro 16 TB
#/dev/sdb -a -o on -S on -s (S/../../7/02|L/../01/./03)
#
## WD Red Pro 16 TB
#/dev/sdc -a -o on -S on -s (S/../../7/02|L/../01/./03)
#
## Seagate Exos 8 TB
#/dev/sdd -a -o on -S on -s (S/../../7/02|L/../01/./03)
#
## WD Blue SN5100 NVMe
## NVMe drives support SMART differently, so -o and -S are not needed.
#/dev/nvme0n1 -a -s (S/../../7/02|L/../01/./03)
#
## mediahost end
#
## quiethost
#
## Seagate IronWolf 8TB
## /dev/sda
#/dev/sda -a -o on -S on -s (S/../../7/02|L/../01/./03)
#
## Intenso 250GB NVMe
## /dev/nvme0n1
## NVMe devices do not use ATA offline data collection,
## therefore -o on and -S on are omitted.
#/dev/nvme0n1 -a -s (S/../../7/02|L/../01/./03)
#
## Crucial P1 1TB NVMe
## /dev/nvme1n1
#/dev/nvme1n1 -a -s (S/../../7/02|L/../01/./03)#
#
## quiethost end
+15
View File
@@ -0,0 +1,15 @@
Host serverhost
HostName someoneslinux.ddns.net
User lucas
Host raspberry
HostName raspberry
User lucas
Host quiethost
HostName quiethost
User lucas
Host mediahost
HostName mediahost
User lucas
+12
View File
@@ -0,0 +1,12 @@
[Unit]
Description=Prometheus Smartctl Exporter
After=network.target
[Service]
User=root
ExecStart=/opt/smartctl_exporter/smartctl_exporter
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target
+69
View File
@@ -0,0 +1,69 @@
#!/usr/bin/env bash
set -euo pipefail
DOWNLOAD_DIR="/data/ubuntu"
mkdir -p "$DOWNLOAD_DIR"
ARCH="amd64"
# Supported:
# 24.04 desktop
# 24.04 server
# 26.04 desktop
# 26.04 server
declare -A URLS=(
["24-desktop"]="https://releases.ubuntu.com/24.04/"
["24-server"]="https://releases.ubuntu.com/24.04/"
["26-desktop"]="https://releases.ubuntu.com/resolute/"
["26-server"]="https://releases.ubuntu.com/resolute/"
)
download_if_newer() {
local key="$1"
local base_url="${URLS[$key]}"
echo "Checking $key..."
iso_name=$(curl -fsSL "$base_url" \
| grep -oE 'ubuntu-[0-9.]+(-live-server|-desktop)-amd64\.iso' \
| sort -Vu \
| tail -1)
if [[ -z "$iso_name" ]]; then
echo "Could not determine latest ISO for $key"
return 1
fi
latest_version=$(echo "$iso_name" | grep -oE '[0-9]+(\.[0-9]+)+')
local_iso=$(find "$DOWNLOAD_DIR" -name "*$(basename "$iso_name" | sed 's/[0-9.]\+//')*" 2>/dev/null | sort | tail -1 || true)
if [[ -n "$local_iso" ]]; then
local_version=$(basename "$local_iso" | grep -oE '[0-9]+(\.[0-9]+)+' | head -1)
if [[ "$local_version" == "$latest_version" ]]; then
echo "Already up to date: $iso_name"
return 0
fi
echo "Outdated local ISO found:"
echo " Local : $local_version"
echo " Latest: $latest_version"
fi
echo "Downloading $iso_name..."
wget --limit-rate=4M -c -P "$DOWNLOAD_DIR" "${base_url}${iso_name}"
echo "Done."
echo
}
download_if_newer "24-desktop"
download_if_newer "24-server"
download_if_newer "26-desktop"
download_if_newer "26-server"
echo "Finished."
+4
View File
@@ -268,6 +268,10 @@ if command -v docker >/dev/null 2>&1; then
fi
)
;;
nextcloud:*)
docker pull "$image"
docker exec -it nextcloud php occ app:update --all
;;
*"<none>"*)
;;
*)