Changed folder structure; added authelia config files
This commit is contained in:
23
homelab/applications/authelia/compose.yaml
Normal file
23
homelab/applications/authelia/compose.yaml
Normal file
@ -0,0 +1,23 @@
|
||||
services:
|
||||
authelia:
|
||||
image: authelia/authelia:latest
|
||||
container_name: authelia
|
||||
volumes:
|
||||
# Config files are still mounted as volumes
|
||||
- ./config/configuration.yml:/config/configuration.yml:ro
|
||||
- ./config/users_database.yml:/config/users_database.yml:ro
|
||||
|
||||
# Persistent SQLite database directory
|
||||
- ./db:/config/db
|
||||
ports:
|
||||
- '9091:9091'
|
||||
environment:
|
||||
- TZ=Etc/UTC
|
||||
|
||||
restart: always
|
||||
healthcheck:
|
||||
test: ["CMD", "authelia", "healthcheck"]
|
||||
interval: 5s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
start_period: 5s
|
||||
63
homelab/applications/authelia/config/configuration.yml
Normal file
63
homelab/applications/authelia/config/configuration.yml
Normal file
@ -0,0 +1,63 @@
|
||||
server:
|
||||
host: 0.0.0.0
|
||||
port: 9091
|
||||
endpoints:
|
||||
authz:
|
||||
forward-auth:
|
||||
implementation: 'ForwardAuth'
|
||||
|
||||
log:
|
||||
level: info
|
||||
|
||||
# --- Storage ---
|
||||
storage:
|
||||
sqlite:
|
||||
path: /config/db/authelia.sqlite.db
|
||||
|
||||
# --- Authentication ---
|
||||
authentication_backend:
|
||||
file:
|
||||
path: /config/users_database.yml
|
||||
password:
|
||||
algorithm: argon2id
|
||||
iterations: 1
|
||||
memory: 2097152
|
||||
parallelism: 4
|
||||
salt_length: 16
|
||||
key_length: 32
|
||||
password_reset:
|
||||
disable: true
|
||||
password_change:
|
||||
disable: false
|
||||
|
||||
# --- Session ---
|
||||
session:
|
||||
cookies:
|
||||
- domain: 'saljic.me'
|
||||
authelia_url: 'https://auth.saljic.me'
|
||||
default_redirection_url: 'https://auth.saljic.me'
|
||||
# name: authelia_session
|
||||
# expiration: 1h
|
||||
# inactivity: 5m
|
||||
|
||||
# --- Notifier (No Mail) ---
|
||||
notifier:
|
||||
filesystem:
|
||||
filename: /config/db/notifications.log
|
||||
|
||||
# --- Access Control ---
|
||||
access_control:
|
||||
default_policy: deny
|
||||
rules:
|
||||
- domain: "*.saljic.me"
|
||||
policy: one_factor
|
||||
|
||||
# --- Password policies ---
|
||||
password_policy:
|
||||
standard:
|
||||
enabled: true
|
||||
min_length: 8
|
||||
require_uppercase: true
|
||||
require_lowercase: true
|
||||
require_number: true
|
||||
require_special: true
|
||||
23
homelab/applications/caddy/Caddyfile
Normal file
23
homelab/applications/caddy/Caddyfile
Normal file
@ -0,0 +1,23 @@
|
||||
# --- Authelia Portal ---
|
||||
# This is the login page itself. It does NOT have forward_auth.
|
||||
auth.saljic.me {
|
||||
# Proxy to the Authelia Docker container on port 9091
|
||||
reverse_proxy localhost:9091
|
||||
}
|
||||
|
||||
# --- Home Assistant (Protected App) ---
|
||||
ha.saljic.me {
|
||||
# 1. Apply authentication using Caddy's 'forward_auth'
|
||||
forward_auth localhost:9091 {
|
||||
uri /api/authz/forward-auth
|
||||
copy_headers Remote-User Remote-Groups Remote-Name Remote-Email
|
||||
}
|
||||
|
||||
# 2. If auth is successful, proxy to your Home Assistant instance
|
||||
reverse_proxy 10.10.10.6:8123
|
||||
}
|
||||
|
||||
# --- Immich ---
|
||||
tagebuch.saljic.me {
|
||||
reverse_proxy 10.10.10.6:2283
|
||||
}
|
||||
155
homelab/applications/caddy/caddy.json
Normal file
155
homelab/applications/caddy/caddy.json
Normal file
@ -0,0 +1,155 @@
|
||||
{
|
||||
"admin": {
|
||||
"listen": "127.0.0.1:2019"
|
||||
},
|
||||
"apps": {
|
||||
"http": {
|
||||
"servers": {
|
||||
"srv0": {
|
||||
"listen": [
|
||||
":443"
|
||||
],
|
||||
"logs": {
|
||||
"default_logger_name": "default"
|
||||
},
|
||||
"routes": [
|
||||
{
|
||||
"handle": [
|
||||
{
|
||||
"handler": "reverse_proxy",
|
||||
"upstreams": [
|
||||
{
|
||||
"dial": "10.10.10.6:8123"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"match": [
|
||||
{
|
||||
"host": [
|
||||
"ha.saljic.me"
|
||||
],
|
||||
"remote_ip": {
|
||||
"ranges": [
|
||||
"217.82.27.57"
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"handle": [
|
||||
{
|
||||
"error": "Unauthorized",
|
||||
"handler": "error",
|
||||
"status_code": "401" }
|
||||
],
|
||||
"match": [
|
||||
{
|
||||
"host": [
|
||||
"ha.saljic.me"
|
||||
],
|
||||
"not": [
|
||||
{
|
||||
"remote_ip": {
|
||||
"ranges": [
|
||||
"217.82.27.57"
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"handle": [
|
||||
{
|
||||
"handler": "reverse_proxy",
|
||||
"upstreams": [
|
||||
{
|
||||
"dial": "10.10.10.6:8000"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"match": [
|
||||
{
|
||||
"host": [
|
||||
"baby.saljic.me"
|
||||
],
|
||||
"remote_ip": {
|
||||
"ranges": [
|
||||
"217.82.27.57"
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{ "handle": [
|
||||
{
|
||||
"error": "Unauthorized",
|
||||
"handler": "error",
|
||||
"status_code": "401"
|
||||
}
|
||||
],
|
||||
"match": [
|
||||
{
|
||||
"host": [
|
||||
"baby.saljic.me"
|
||||
],
|
||||
"not": [
|
||||
{
|
||||
"remote_ip": {
|
||||
"ranges": [
|
||||
"217.82.27.57"
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"handle": [
|
||||
{
|
||||
"handler": "reverse_proxy",
|
||||
"upstreams": [
|
||||
{
|
||||
"dial": "10.10.10.6:2283"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"match": [
|
||||
{
|
||||
"host": [
|
||||
"tagebuch.saljic.me"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"logging": {
|
||||
"logs": {
|
||||
"default": {
|
||||
"encoder": {
|
||||
"format": "json"
|
||||
},
|
||||
"level": "INFO",
|
||||
"writer": {
|
||||
"filename": "/var/log/caddy/access.log",
|
||||
"output": "file",
|
||||
"roll_gzip": false,
|
||||
"roll_keep": 5,
|
||||
"roll_keep_days": 60,
|
||||
"roll_local_time": false,
|
||||
"roll_size_mb": 100
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
1
homelab/mikrotik/README.md
Normal file
1
homelab/mikrotik/README.md
Normal file
@ -0,0 +1 @@
|
||||
Installation instructions for Bonjour reflection: https://github.com/nberlee/bonjour-reflector/blob/main/docs/RouterOS/README.md
|
||||
145
homelab/mikrotik/arp-monitor.rsc
Normal file
145
homelab/mikrotik/arp-monitor.rsc
Normal file
@ -0,0 +1,145 @@
|
||||
# ARP Table Monitor Script for MikroTik RouterOS
|
||||
# This script monitors ARP table and sends REST API notifications for new MAC+IP combinations
|
||||
|
||||
# Configuration variables
|
||||
:local apiEndpoint "http://10.10.10.6:8500/mikrotik-389210-instant"
|
||||
:local monitorInterfaces {"vlan-guest"; "vlan-iot"; "vlan-home"}
|
||||
|
||||
# Create global variable to store known MAC+IP combinations if it doesn't exist
|
||||
:global arpKnownDevices
|
||||
:if ([:typeof $arpKnownDevices] = "nothing") do={
|
||||
:set arpKnownDevices [:toarray ""]
|
||||
}
|
||||
# Uncomment while testing, comment for production
|
||||
# :set arpKnownDevices [:toarray ""]
|
||||
|
||||
# Get current ARP entries
|
||||
:local currentArpEntries [:toarray ""]
|
||||
:local arpEntries
|
||||
|
||||
# Get ARP entries - filter by interface if specified
|
||||
:if ([:len $monitorInterfaces] > 0) do={
|
||||
:set arpEntries [:toarray ""]
|
||||
:foreach iface in=$monitorInterfaces do={
|
||||
:do {
|
||||
:local ifaceEntries [/ip arp find interface=$iface]
|
||||
:foreach entry in=$ifaceEntries do={
|
||||
:if ([:len $arpEntries] = 0) do={
|
||||
:set arpEntries $entry
|
||||
} else={
|
||||
:set arpEntries ($arpEntries, $entry)
|
||||
}
|
||||
}
|
||||
} on-error={
|
||||
:log warning "Could not access interface: $iface"
|
||||
}
|
||||
}
|
||||
:if ([:len $arpEntries] > 0) do={
|
||||
:set arpEntries [:toarray $arpEntries]
|
||||
}
|
||||
} else={
|
||||
# Monitor all interfaces
|
||||
:set arpEntries [/ip arp find]
|
||||
}
|
||||
|
||||
# Check for new MAC+IP combinations
|
||||
:local newDevicesFound false
|
||||
:local requestBody ""
|
||||
|
||||
:if ([:len $arpEntries] > 0) do={
|
||||
:foreach arpEntry in=$arpEntries do={
|
||||
:local arpInfo [/ip arp get $arpEntry]
|
||||
|
||||
# Skip incomplete, invalid, or dynamic entries if desired
|
||||
:local arpStatus ($arpInfo->"status")
|
||||
:if ($arpStatus = "reachable" || $arpStatus = "stale" || $arpStatus = "delay") do={
|
||||
|
||||
:local macAddress ($arpInfo->"mac-address")
|
||||
:local ipAddress ($arpInfo->"address")
|
||||
:local interface ($arpInfo->"interface")
|
||||
|
||||
# Create unique identifier for MAC+IP combination
|
||||
:local deviceId ($macAddress . "-" . $ipAddress)
|
||||
|
||||
# Check if this MAC+IP combination is already known
|
||||
:local isKnown false
|
||||
:if ([:len $arpKnownDevices] > 0) do={
|
||||
:if ([:find $arpKnownDevices $deviceId] >= 0) do={
|
||||
:set isKnown true
|
||||
}
|
||||
}
|
||||
|
||||
# If not known, process as new device
|
||||
:if (!$isKnown) do={
|
||||
:set newDevicesFound true
|
||||
|
||||
# Get additional info
|
||||
:local arpComment ""
|
||||
:if ([:typeof ($arpInfo->"comment")] != "nothing") do={
|
||||
:set arpComment ($arpInfo->"comment")
|
||||
} else={
|
||||
:set arpComment "N/A"
|
||||
}
|
||||
|
||||
# Try to get hostname from DHCP lease table (if available)
|
||||
:local hostname "Unknown"
|
||||
:do {
|
||||
:local dhcpLease [/ip dhcp-server lease find address=$ipAddress]
|
||||
:if ([:len $dhcpLease] > 0) do={
|
||||
:local leaseInfo [/ip dhcp-server lease get [:pick $dhcpLease 0]]
|
||||
:if ([:typeof ($leaseInfo->"host-name")] != "nothing") do={
|
||||
:set hostname ($leaseInfo->"host-name")
|
||||
}
|
||||
}
|
||||
} on-error={
|
||||
# DHCP lookup failed, keep hostname as "Unknown"
|
||||
}
|
||||
|
||||
# Build notification body
|
||||
:set requestBody ($requestBody . "MAC+IP Address: " . $deviceId . "\n")
|
||||
:set requestBody ($requestBody . "Interface: " . $interface . "\n")
|
||||
:set requestBody ($requestBody . "ARP Status: " . $arpStatus . "\n")
|
||||
:set requestBody ($requestBody . "Hostname: " . $hostname . "\n")
|
||||
:set requestBody ($requestBody . "----------------------------------------\n")
|
||||
|
||||
# Add to known devices
|
||||
:if ([:len $arpKnownDevices] = 0) do={
|
||||
:set arpKnownDevices $deviceId
|
||||
} else={
|
||||
:set arpKnownDevices ($arpKnownDevices . "," . $deviceId)
|
||||
}
|
||||
|
||||
:log info "New ARP entry detected: $macAddress at $ipAddress on $interface"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Send REST API notification for new devices
|
||||
:if ($newDevicesFound) do={
|
||||
:do {
|
||||
/tool fetch \
|
||||
url=$apiEndpoint \
|
||||
http-method=post \
|
||||
http-header-field="Priority: 3,Title: New device detected in network,Tags: warning" \
|
||||
http-data=$requestBody \
|
||||
keep-result=no
|
||||
|
||||
:log info "ARP monitoring notification API request sent"
|
||||
} on-error={
|
||||
:log error "Failed to send ARP monitoring notification API request"
|
||||
}
|
||||
} else={
|
||||
:log info "No new mac/ip combinations in ARP"
|
||||
}
|
||||
|
||||
# Clean up known devices list if it gets too large
|
||||
:local knownCount 0
|
||||
:if ([:len $arpKnownDevices] > 0) do={
|
||||
:set knownCount [:len [:toarray $arpKnownDevices]]
|
||||
}
|
||||
:if ($knownCount > 2000) do={
|
||||
:log warning "Known ARP devices list is getting large ($knownCount entries), consider resetting it"
|
||||
# Uncomment the next line to auto-reset when list gets too large
|
||||
# :global arpKnownDevices ""
|
||||
}
|
||||
39
homelab/mikrotik/config.toml
Normal file
39
homelab/mikrotik/config.toml
Normal file
@ -0,0 +1,39 @@
|
||||
net_interface = "eth0"
|
||||
|
||||
[devices]
|
||||
|
||||
[devices."B0:22:7A:91:01:CB"]
|
||||
description = "HP Printer"
|
||||
origin_pool = 10
|
||||
shared_pools = [30]
|
||||
|
||||
[devices."48:A6:B8:A5:BC:7E"]
|
||||
description = "Sonos One #1"
|
||||
origin_pool = 10
|
||||
shared_pools = [30]
|
||||
|
||||
[devices."48:A6:B8:A5:BB:7C"]
|
||||
description = "Sonos One #2"
|
||||
origin_pool = 10
|
||||
shared_pools = [30]
|
||||
|
||||
[devices."48:A6:B8:B0:4C:80"]
|
||||
description = "Sonos Arc"
|
||||
origin_pool = 10
|
||||
shared_pools = [30]
|
||||
|
||||
[devices."F0:B3:EC:05:48:3D"]
|
||||
description = "Apple TV"
|
||||
origin_pool = 10
|
||||
shared_pools = [30]
|
||||
|
||||
[vlan]
|
||||
|
||||
[vlan.10]
|
||||
ip_source = "10.10.10.2"
|
||||
|
||||
[vlan.20]
|
||||
ip_source = "10.10.20.2"
|
||||
|
||||
[vlan.30]
|
||||
ip_source = "10.10.30.2"
|
||||
15
homelab/mikrotik/mqtt.rsc
Normal file
15
homelab/mikrotik/mqtt.rsc
Normal file
@ -0,0 +1,15 @@
|
||||
:local cpuLoad [/system/resource/get cpu-load]
|
||||
:local cpuTemperature [/system health get [find name="temperature"] value]
|
||||
|
||||
:local sfp1Info [/interface ethernet monitor sfp-sfpplus1 once as-value]
|
||||
:local sfpTemperature ($sfp1Info->"sfp-temperature")
|
||||
|
||||
:local pppoeClientInfo [/interface pppoe-client monitor [find name="pppoe-telekom"] once as-value]
|
||||
:local pppoeUptime ($pppoeClientInfo->"uptime")
|
||||
|
||||
:local totalRAM [/system/resource/get total-memory]
|
||||
:local freeRAM [/system/resource/get free-memory]
|
||||
:local usedRAM ($totalRAM - $freeRAM)
|
||||
:local ramUtilization (($usedRAM * 100) / $totalRAM)
|
||||
|
||||
/iot mqtt publish message="{\"cpu\": \"$cpuLoad\", \"ram\": \"$ramUtilization\", \"cpu_temp\": \"$cpuTemperature\", \"sfp_temp\": \"$sfpTemperature\", \"pppoe_telekom_uptime\": \"$pppoeUptime\"}" broker="mosquitto" topic="mikrotik-info"
|
||||
86
homelab/vps/wg_monitor.sh
Normal file
86
homelab/vps/wg_monitor.sh
Normal file
@ -0,0 +1,86 @@
|
||||
#!/bin/bash
|
||||
|
||||
# IP address to ping
|
||||
IP="10.10.10.6"
|
||||
|
||||
# Number of ping attempts
|
||||
COUNT=5
|
||||
|
||||
# Log file
|
||||
LOG_FILE="/var/log/wg_monitor.log"
|
||||
|
||||
# Function to log messages with timestamp
|
||||
log_message() {
|
||||
# Create log file if it doesn't exist and set proper permissions
|
||||
if [ ! -f "$LOG_FILE" ]; then
|
||||
touch "$LOG_FILE"
|
||||
chmod 644 "$LOG_FILE"
|
||||
fi
|
||||
local message="$(date '+%Y-%m-%d %H:%M:%S') - $1"
|
||||
echo "$message" >> "$LOG_FILE"
|
||||
echo "$message" # Also print to console for debugging
|
||||
}
|
||||
|
||||
# Always log script start
|
||||
log_message "Script started - pinging $IP"
|
||||
|
||||
# Ping the IP address
|
||||
echo "Executing ping command..."
|
||||
ping_result=$(ping -c $COUNT -W 5 $IP 2>&1)
|
||||
exit_code=$?
|
||||
|
||||
echo "Ping exit code: $exit_code"
|
||||
echo "Ping result:"
|
||||
echo "$ping_result"
|
||||
|
||||
# Check if ping failed completely
|
||||
if [ $exit_code -eq 1 ]; then
|
||||
log_message "Ping failed with exit code 1"
|
||||
|
||||
# Extract packet loss percentage
|
||||
packet_loss=$(echo "$ping_result" | grep -o '[0-9]*% packet loss' | grep -o '[0-9]*')
|
||||
|
||||
echo "Packet loss: $packet_loss%"
|
||||
log_message "Packet loss detected: $packet_loss%"
|
||||
|
||||
# If 100% packet loss, restart WireGuard
|
||||
if [ "$packet_loss" = "100" ]; then
|
||||
log_message "100% packet loss detected for $IP. Restarting WireGuard interface wg0..."
|
||||
|
||||
# Stop WireGuard interface
|
||||
echo "Stopping WireGuard..."
|
||||
/usr/bin/wg-quick down wg0
|
||||
down_result=$?
|
||||
|
||||
if [ $down_result -eq 0 ]; then
|
||||
log_message "WireGuard interface wg0 stopped successfully"
|
||||
else
|
||||
log_message "Failed to stop WireGuard interface wg0 (exit code: $down_result)"
|
||||
fi
|
||||
|
||||
sleep 2
|
||||
|
||||
# Start WireGuard interface
|
||||
echo "Starting WireGuard..."
|
||||
/usr/bin/wg-quick up wg0
|
||||
up_result=$?
|
||||
|
||||
if [ $up_result -eq 0 ]; then
|
||||
log_message "WireGuard interface wg0 started successfully"
|
||||
else
|
||||
log_message "Failed to start WireGuard interface wg0 (exit code: $up_result)"
|
||||
fi
|
||||
else
|
||||
log_message "Ping failed but not 100% packet loss ($packet_loss%)"
|
||||
fi
|
||||
elif [ $exit_code -eq 0 ]; then
|
||||
# Ping successful
|
||||
log_message "Ping to $IP successful"
|
||||
echo "Ping successful"
|
||||
else
|
||||
log_message "Ping command failed with exit code $exit_code"
|
||||
echo "Ping failed with exit code $exit_code"
|
||||
fi
|
||||
|
||||
log_message "Script completed"
|
||||
echo "Script completed"
|
||||
Reference in New Issue
Block a user