Compare commits

...

2 Commits

Author SHA1 Message Date
9eb3333931 cleanup 2026-02-25 00:48:06 +03:00
ea00ad6d25 added node exporher 2026-02-25 00:22:44 +03:00
10 changed files with 229 additions and 105 deletions

83
README.md Normal file
View File

@@ -0,0 +1,83 @@
# Homelab
## Prerequisites
- **Docker** and **Docker Compose**
- Host paths used by the stacks:
- `/srv/homelab`
- `/srv/media`
- `/backup`
## Setup
### 1. Media dirs
```bash
sudo mkdir -p /srv/media/{movies,shows,downloads,immich}
sudo chown -R 1000:1000 /srv/media
```
### 2. Monitoring permissions
```bash
sudo mkdir -p /srv/homelab/data/monitoring/{prometheus,loki,grafana,alloy}
sudo chown -R 65534:65534 /srv/homelab/data/monitoring/prometheus
sudo chown -R 10001:10001 /srv/homelab/data/monitoring/loki
sudo chown -R 472:472 /srv/homelab/data/monitoring/grafana
sudo chown -R 10001:10001 /srv/homelab/data/monitoring/alloy
```
### 3. Env
- **Glance:** `stacks/monitoring/glance.env`
- **Immich:** `stacks/media/immich.env`
## Deploying
From the repo root (`/srv/homelab`):
| Stack | Command |
|------------|---------|
| **Media** | `docker compose -f stacks/media/compose.yaml up -d` |
| **Monitoring** | `docker compose -f stacks/monitoring/compose.yaml up -d` |
| **Storage** | `docker compose -f stacks/storage/compose.yaml up -d` |
To update images:
```bash
docker compose -f stacks/media/compose.yaml pull
docker compose -f stacks/media/compose.yaml up -d
```
To stop a stack:
```bash
docker compose -f stacks/media/compose.yaml down
```
## Ports
| Service | Port(s) | Stack |
|---------------|----------------------|-----------|
| **Media** | | |
| Sonarr | 8989 | media |
| Radarr | 7878 | media |
| Lidarr | 8686 | media |
| Prowlarr | 9696 | media |
| qBittorrent | 8081, 6881 (tcp/udp) | media |
| Jellyfin | 8096 | media |
| Immich | 2283 | media |
| Navidrome | 4533 | media |
| Seer | 5055 | media |
| **Monitoring**| | |
| Grafana | 3034 | monitoring|
| Prometheus | 9094 | monitoring|
| Loki | 3100 | monitoring|
| Node Exporter | 9100 | monitoring|
| Alloy | 12345 | monitoring|
| cAdvisor | 8088 | monitoring|
| Glance | 9090 | monitoring|
| Portainer | 9443, 8000 | monitoring|
| **Storage** | | |
| Gitea | 3000, 222 | storage |
| Copyparty | 3923 | storage |

View File

@@ -0,0 +1,72 @@
// Log pipeline: files, Docker, journald → Loki (replaces Promtail).
// See: https://grafana.com/docs/alloy/latest/set-up/migrate/from-promtail/
loki.write "default" {
endpoint {
url = "http://loki:3100/loki/api/v1/push"
}
}
// varlogs: /var/log/**/*.log
loki.source.file "varlogs" {
targets = [
{ __path__ = "/var/log/**/*.log", job = "varlogs", host = "cyberdeck" },
]
forward_to = [loki.write.default.receiver]
file_match {
enabled = true
sync_period = "10s"
}
}
// docker: container logs with docker parsing and container label from path
loki.source.file "docker" {
targets = [
{ __path__ = "/var/lib/docker/containers/*/*-json.log", job = "docker", host = "cyberdeck" },
]
forward_to = [loki.process.docker.receiver]
file_match {
enabled = true
sync_period = "10s"
}
}
loki.process "docker" {
forward_to = [loki.relabel.docker.receiver]
stage.docker {}
}
loki.relabel "docker" {
forward_to = [loki.write.default.receiver]
rule {
source_labels = ["filename"]
regex = "/var/lib/docker/containers/([^/]+)/.*"
target_label = "container"
replacement = "$1"
}
}
// journald: systemd journal with unit, host, level labels
loki.relabel "journald" {
forward_to = []
rule {
source_labels = ["__journal__systemd_unit"]
target_label = "unit"
}
rule {
source_labels = ["__journal__hostname"]
target_label = "host"
}
rule {
source_labels = ["__journal__priority_keyword"]
target_label = "level"
}
}
loki.source.journal "journald" {
forward_to = [loki.write.default.receiver]
relabel_rules = loki.relabel.journald.rules
labels = { job = "journald", host = "cyberdeck" }
path = "/var/log/journal"
max_age = "12h"
}

View File

@@ -1,49 +1,55 @@
# Loki 3.6 single-binary config (from official loki-local-config.yaml).
# See: https://grafana.com/docs/loki/latest/configure/
auth_enabled: false auth_enabled: false
server: server:
http_listen_port: 3100 http_listen_port: 3100
http_listen_address: 0.0.0.0
grpc_listen_port: 9096
log_level: info log_level: info
grpc_server_max_concurrent_streams: 1000
ingester: common:
wal: instance_addr: 127.0.0.1
dir: /loki/wal path_prefix: /loki
lifecycler: storage:
ring: filesystem:
kvstore: chunks_directory: /loki/chunks
store: inmemory rules_directory: /loki/rules
replication_factor: 1 replication_factor: 1
chunk_idle_period: 5m ring:
chunk_target_size: 1048576 kvstore:
max_transfer_retries: 0 store: inmemory
query_range:
results_cache:
cache:
embedded_cache:
enabled: true
max_size_mb: 100
limits_config:
metric_aggregation_enabled: true
enable_multi_variant_queries: true
schema_config: schema_config:
configs: configs:
- from: 2020-10-24 - from: 2020-10-24
store: boltdb store: tsdb
object_store: filesystem object_store: filesystem
schema: v11 schema: v13
index: index:
prefix: index_ prefix: index_
period: 168h period: 24h
storage_config: pattern_ingester:
boltdb: enabled: true
directory: /loki/index metric_aggregation:
filesystem: loki_address: localhost:3100
directory: /loki/chunks
limits_config: ruler:
enforce_metric_name: false alertmanager_url: http://localhost:9093
reject_old_samples: true
reject_old_samples_max_age: 168h
split_queries_by_interval: 15m
querier: frontend:
max_outstanding_per_tenant: 4096 encoding: protobuf
chunk_store_config:
max_look_back_period: 0s
table_manager:
retention_deletes_enabled: true
retention_period: 168h

View File

@@ -1,48 +0,0 @@
server:
http_listen_port: 9080
grpc_listen_port: 0
positions:
filename: /tmp/positions.yaml
clients:
- url: http://loki:3100/loki/api/v1/push
scrape_configs:
- job_name: varlogs
static_configs:
- targets: [localhost]
labels:
job: varlogs
host: cyberdeck
__path__: /var/log/**/*.log
- job_name: docker
static_configs:
- targets: [localhost]
labels:
job: docker
host: cyberdeck
__path__: /var/lib/docker/containers/*/*-json.log
pipeline_stages:
- docker: {}
relabel_configs:
- source_labels: [__path__]
regex: "/var/lib/docker/containers/([^/]+)/.*"
target_label: container
replacement: "$1"
- job_name: journald
journal:
path: /var/log/journal
max_age: 12h
labels:
job: journald
host: cyberdeck
relabel_configs:
- source_labels: [__journal__systemd_unit]
target_label: unit
- source_labels: [__journal__hostname]
target_label: host
- source_labels: [__journal__priority_keyword]
target_label: level

View File

@@ -39,7 +39,7 @@ services:
immich-redis: immich-redis:
container_name: immich_redis container_name: immich_redis
image: docker.io/valkey/valkey:9@sha256:546304417feac0874c3dd576e0952c6bb8f06bb4093ea0c9ca303c73cf458f63 image: docker.io/valkey/valkey:9
healthcheck: healthcheck:
test: redis-cli ping || exit 1 test: redis-cli ping || exit 1
restart: unless-stopped restart: unless-stopped
@@ -51,7 +51,7 @@ services:
immich-postgres: immich-postgres:
container_name: immich_postgres container_name: immich_postgres
image: ghcr.io/immich-app/postgres:14-vectorchord0.4.3-pgvectors0.2.0@sha256:bcf63357191b76a916ae5eb93464d65c07511da41e3bf7a8416db519b40b1c23 image: ghcr.io/immich-app/postgres:14-vectorchord0.4.3-pgvectors0.2.0
env_file: env_file:
- ./immich.env - ./immich.env
shm_size: 128mb shm_size: 128mb

View File

@@ -1,13 +0,0 @@
MY_SECRET_TOKEN=change_me
RADARR_URL=http://radarr.home
RADARR_API_URL=http://radarr.home
RADARR_KEY=change_me
SONARR_URL=http://sonarr.home
SONARR_API_URL=http://sonarr.home
SONARR_KEY=change_me
LIDARR_URL=http://lidarr.home
LIDARR_API_URL=http://lidarr.home
LIDARR_KEY=change_me
PORTAINER_URL=http://portainer.home
PORTAINER_ENDPOINT_ID=1
PORTAINER_API_KEY=change_me

View File

@@ -1,7 +1,7 @@
services: services:
glance: glance:
container_name: glance container_name: glance
image: glanceapp/glance image: glanceapp/glance:latest
restart: unless-stopped restart: unless-stopped
volumes: volumes:
- /srv/homelab/config/monitoring/glance:/app/config - /srv/homelab/config/monitoring/glance:/app/config

View File

@@ -2,7 +2,12 @@
# sudo chown -R 65534:65534 /srv/homelab/data/monitoring/prometheus # sudo chown -R 65534:65534 /srv/homelab/data/monitoring/prometheus
# sudo chown -R 10001:10001 /srv/homelab/data/monitoring/loki # sudo chown -R 10001:10001 /srv/homelab/data/monitoring/loki
# sudo chown -R 472:472 /srv/homelab/data/monitoring/grafana # sudo chown -R 472:472 /srv/homelab/data/monitoring/grafana
# sudo chown -R 10001:10001 /srv/homelab/data/monitoring/alloy
# #
networks:
default:
name: monitoring
services: services:
cadvisor: cadvisor:
image: gcr.io/cadvisor/cadvisor:latest image: gcr.io/cadvisor/cadvisor:latest
@@ -38,6 +43,22 @@ services:
max-size: "10m" max-size: "10m"
max-file: "5" max-file: "5"
node_exporter:
image: quay.io/prometheus/node-exporter:latest
container_name: node_exporter
command:
- '--path.rootfs=/host'
network_mode: host
pid: host
restart: unless-stopped
volumes:
- '/:/host:ro,rslave'
logging:
driver: json-file
options:
max-size: "10m"
max-file: "5"
grafana: grafana:
image: grafana/grafana:latest image: grafana/grafana:latest
container_name: grafana container_name: grafana
@@ -62,7 +83,7 @@ services:
max-file: "5" max-file: "5"
loki: loki:
image: grafana/loki:2.9.0 image: grafana/loki:3.6.0
container_name: loki container_name: loki
ports: ports:
- "3100:3100" - "3100:3100"
@@ -77,14 +98,17 @@ services:
max-size: "10m" max-size: "10m"
max-file: "5" max-file: "5"
promtail: alloy:
image: grafana/promtail:2.9.0 image: grafana/alloy:latest
container_name: promtail container_name: alloy
command: -config.file=/etc/promtail/config.yaml command: run --storage.path=/var/lib/alloy /etc/alloy/config.alloy
depends_on: depends_on:
- loki - loki
ports:
- "12345:12345"
volumes: volumes:
- /srv/homelab/config/monitoring/promtail-config.yaml:/etc/promtail/config.yaml:ro - /srv/homelab/config/monitoring/alloy.alloy:/etc/alloy/config.alloy:ro
- /srv/homelab/data/monitoring/alloy:/var/lib/alloy
- /var/log:/var/log:ro - /var/log:/var/log:ro
- /etc/machine-id:/etc/machine-id:ro - /etc/machine-id:/etc/machine-id:ro
- /var/lib/docker/containers:/var/lib/docker/containers:ro - /var/lib/docker/containers:/var/lib/docker/containers:ro

View File

@@ -1,7 +1,7 @@
services: services:
portainer: portainer:
container_name: portainer container_name: portainer
image: portainer/portainer-ce:lts image: portainer/portainer-ce:latest
restart: unless-stopped restart: unless-stopped
volumes: volumes:
- /var/run/docker.sock:/var/run/docker.sock - /var/run/docker.sock:/var/run/docker.sock

View File

@@ -4,7 +4,7 @@ networks:
services: services:
server: server:
image: docker.gitea.com/gitea:1.25.4 image: docker.gitea.com/gitea:latest
container_name: gitea container_name: gitea
environment: environment:
- USER_UID=1000 - USER_UID=1000