mirror of
https://github.com/samjage/lab.git
synced 2026-06-06 05:30:43 +00:00
Compare commits
2 Commits
81afb34e4f
..
master
| Author | SHA1 | Date | |
|---|---|---|---|
| c948d5cbde | |||
| 12892ec9db |
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
|
Before Width: | Height: | Size: 3.0 KiB After Width: | Height: | Size: 3.0 KiB |
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
@@ -0,0 +1,150 @@
|
||||
#!/bin/bash
|
||||
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
PURPLE='\033[0;35m'
|
||||
CYAN='\033[0;36m'
|
||||
GRAY='\033[0;90m'
|
||||
BOLD='\033[1m'
|
||||
NC='\033[0m'
|
||||
|
||||
COLS=${COLUMNS:-$(tput cols 2>/dev/null)}
|
||||
[[ "$COLS" =~ ^[0-9]+$ ]] || COLS=80
|
||||
SEP="${GRAY}$(printf '━%.0s' $(seq 1 $COLS))${NC}"
|
||||
|
||||
# ── Logo ─────────────────────────────────────────────────────────────────────
|
||||
echo -e "${CYAN}${BOLD}"
|
||||
echo '██ ██ ███ ██ ██ ██'
|
||||
echo '██ ██ ████ ██ ██ ██ '
|
||||
echo '██ ██ ██ ██ ██ █████ '
|
||||
echo '██ ██ ██ ██ ██ ██ ██ '
|
||||
echo '███████ ██ ██ ████ ██ ██'
|
||||
echo -e "${NC}"
|
||||
echo -e "$SEP"
|
||||
|
||||
# ── Date & Time ───────────────────────────────────────────────────────────────
|
||||
echo -e " ${PURPLE}${BOLD}$(date '+%A, %B %d %Y')${NC} ${GRAY}·${NC} ${PURPLE}$(date '+%I:%M %p')${NC}"
|
||||
echo -e "$SEP"
|
||||
|
||||
# ── Weather ───────────────────────────────────────────────────────────────────
|
||||
WEATHER=$(curl -s --max-time 4 "https://api.open-meteo.com/v1/forecast?latitude=39.84&longitude=-82.81¤t=temperature_2m,apparent_temperature,relative_humidity_2m,wind_speed_10m,weather_code&temperature_unit=fahrenheit&timezone=America/New_York" 2>/dev/null)
|
||||
echo -e " ${YELLOW}${BOLD}☁ Canal Winchester${NC}"
|
||||
if echo "$WEATHER" | python3 -c "import sys,json; json.load(sys.stdin)" &>/dev/null; then
|
||||
TEMP=$(echo "$WEATHER" | python3 -c "import sys,json; d=json.load(sys.stdin)['current']; print(round(d['temperature_2m']))")
|
||||
FEELS=$(echo "$WEATHER" | python3 -c "import sys,json; d=json.load(sys.stdin)['current']; print(round(d['apparent_temperature']))")
|
||||
HUMID=$(echo "$WEATHER" | python3 -c "import sys,json; d=json.load(sys.stdin)['current']; print(round(d['relative_humidity_2m']))")
|
||||
WIND=$(echo "$WEATHER" | python3 -c "import sys,json; d=json.load(sys.stdin)['current']; print(round(d['wind_speed_10m']))")
|
||||
CODE=$(echo "$WEATHER" | python3 -c "import sys,json; d=json.load(sys.stdin)['current']; print(d['weather_code'])")
|
||||
case $CODE in
|
||||
0) ICON="☀️ Clear";;
|
||||
1|2) ICON="⛅ Partly Cloudy";;
|
||||
3) ICON="☁️ Overcast";;
|
||||
45|48) ICON="🌫️ Fog";;
|
||||
51|53|55|61|63|65|80|81|82) ICON="🌧️ Rain";;
|
||||
71|73|75|85|86) ICON="❄️ Snow";;
|
||||
95|96|99) ICON="⛈️ Storms";;
|
||||
*) ICON="🌥️ Cloudy";;
|
||||
esac
|
||||
echo -e " ${ICON} ${BOLD}${TEMP}°F${NC} ${GRAY}feels ${FEELS}°F · 💧${HUMID}% · 💨 ${WIND} km/h${NC}"
|
||||
else
|
||||
echo -e " ${GRAY}weather unavailable${NC}"
|
||||
fi
|
||||
echo -e "$SEP"
|
||||
|
||||
# ── Docker ────────────────────────────────────────────────────────────────────
|
||||
echo -e " ${GREEN}${BOLD}🐳 Docker${NC}"
|
||||
if command -v docker &> /dev/null; then
|
||||
RUNNING=$(docker ps -q 2>/dev/null | wc -l)
|
||||
TOTAL=$(docker ps -a -q 2>/dev/null | wc -l)
|
||||
DOWN=$((TOTAL - RUNNING))
|
||||
RESTART=$(docker ps --filter "status=restarting" -q 2>/dev/null | wc -l)
|
||||
echo ""
|
||||
echo -e " ${GREEN}●${NC} ${RUNNING} running ${GRAY}·${NC} ${RED}●${NC} ${DOWN} stopped ${GRAY}·${NC} 🔄 ${RESTART} restarting ${GRAY}·${NC} 📦 ${TOTAL} total"
|
||||
echo ""
|
||||
|
||||
# Outdated images — parsed live from Watchtower logs
|
||||
echo -e " ${CYAN}image updates${NC}"
|
||||
if docker inspect watchtower &>/dev/null 2>&1; then
|
||||
LAST_SCAN=$(docker logs watchtower --since 72h 2>&1 | grep "Session done" | tail -1 | grep -oP '\d{4}-\d{2}-\d{2}T\d{2}:\d{2}' || true)
|
||||
OUTDATED_LIST=$(docker logs watchtower --since 36h 2>&1 | grep "Found new" | grep -oP '(?<=Found new )\S+(?= image)' || true)
|
||||
if [ -n "$OUTDATED_LIST" ]; then
|
||||
COUNT=$(echo "$OUTDATED_LIST" | wc -l)
|
||||
echo -e " ${YELLOW}↑ ${COUNT} update(s) available${NC}"
|
||||
while IFS= read -r img; do
|
||||
CT=$(docker ps -a --format '{{.Names}}|{{.Image}}' | awk -F'|' -v i="$img" '$2==i {printf "%s ", $1}')
|
||||
echo -e " ${GRAY} · ${img}${NC} ${CT}"
|
||||
done <<< "$OUTDATED_LIST"
|
||||
else
|
||||
echo -e " ${GREEN}●${NC} all images current"
|
||||
fi
|
||||
[ -n "$LAST_SCAN" ] && echo -e " ${GRAY}last scan: ${LAST_SCAN}${NC}"
|
||||
echo -e " ${GRAY}details: bash /opt/stacks/scripts/update-check.sh${NC}"
|
||||
else
|
||||
echo -e " ${GRAY}watchtower not running${NC}"
|
||||
fi
|
||||
else
|
||||
echo -e " ${RED}docker not available${NC}"
|
||||
fi
|
||||
echo -e "$SEP"
|
||||
|
||||
# ── System ────────────────────────────────────────────────────────────────────
|
||||
echo -e " ${BLUE}${BOLD}💻 System${NC}"
|
||||
echo ""
|
||||
|
||||
LOCAL_IP=$(hostname -I | awk '{print $1}')
|
||||
EXT_IP=$(curl -s --max-time 3 ifconfig.me 2>/dev/null || echo "unavailable")
|
||||
|
||||
CPU_CORES=$(nproc 2>/dev/null || echo 1)
|
||||
CPU_PCT=$(top -bn1 | grep "Cpu(s)" | sed "s/.*, *\([0-9.]*\)%* id.*/\1/" | awk '{printf "%.0f", 100 - $1}')
|
||||
CPU_FILLED=$((CPU_PCT * 10 / 100))
|
||||
CPU_EMPTY=$((10 - CPU_FILLED))
|
||||
CPU_ON="$(printf '█%.0s' $(seq 1 $CPU_FILLED) 2>/dev/null)"
|
||||
CPU_OFF="$(printf '░%.0s' $(seq 1 $CPU_EMPTY) 2>/dev/null)"
|
||||
|
||||
RAM_USED=$(free -m | awk 'NR==2 {printf "%.1f", $3/1024}')
|
||||
RAM_TOTAL=$(free -m | awk 'NR==2 {printf "%.1f", $2/1024}')
|
||||
RAM_PCT=$(free | awk 'NR==2 {printf "%.0f", $3/$2*100}')
|
||||
RAM_FILLED=$((RAM_PCT * 10 / 100))
|
||||
RAM_EMPTY=$((10 - RAM_FILLED))
|
||||
BAR_ON="$(printf '█%.0s' $(seq 1 $RAM_FILLED) 2>/dev/null)"
|
||||
BAR_OFF="$(printf '░%.0s' $(seq 1 $RAM_EMPTY) 2>/dev/null)"
|
||||
|
||||
LOAD=$(awk '{print $1" "$2" "$3}' /proc/loadavg)
|
||||
LOAD1=$(awk '{print $1}' /proc/loadavg)
|
||||
LOAD_PCT=$(awk -v l="$LOAD1" -v c="$CPU_CORES" 'BEGIN {v=int((l/c)*100); if(v>100) v=100; print v}')
|
||||
LOAD_FILLED=$((LOAD_PCT * 10 / 100))
|
||||
LOAD_EMPTY=$((10 - LOAD_FILLED))
|
||||
LOAD_ON="$(printf '█%.0s' $(seq 1 $LOAD_FILLED) 2>/dev/null)"
|
||||
LOAD_OFF="$(printf '░%.0s' $(seq 1 $LOAD_EMPTY) 2>/dev/null)"
|
||||
|
||||
TOP_NAME=$(ps aux --sort=-%cpu | awk 'NR==2 {split($11,a,"/"); print a[length(a)]}')
|
||||
TOP_CPU=$(ps aux --sort=-%cpu | awk 'NR==2 {printf "%.1f%%", $3}')
|
||||
|
||||
printf " ${GRAY}%-10s${NC} %s\n" "uptime" "$(uptime -p | sed 's/up //')"
|
||||
printf " ${GRAY}%-10s${NC} %s\n" "local ip" "$LOCAL_IP"
|
||||
printf " ${GRAY}%-10s${NC} %s\n" "ext ip" "$EXT_IP"
|
||||
echo ""
|
||||
printf " ${GRAY}%-10s${NC} ${GREEN}${CPU_ON}${GRAY}${CPU_OFF}${NC} ${CPU_PCT}%%\n" "cpu"
|
||||
printf " ${GRAY}%-10s${NC} ${GREEN}${BAR_ON}${GRAY}${BAR_OFF}${NC} ${RAM_USED}/${RAM_TOTAL} GB ${RAM_PCT}%%\n" "ram"
|
||||
printf " ${GRAY}%-10s${NC} ${GREEN}${LOAD_ON}${GRAY}${LOAD_OFF}${NC} ${LOAD} ${GRAY}/ ${CPU_CORES} cores${NC}\n" "load"
|
||||
echo ""
|
||||
printf " ${GRAY}%-10s${NC} ${YELLOW}%s${NC} ${GRAY}%s${NC}\n" "top proc" "$TOP_NAME" "$TOP_CPU"
|
||||
printf " ${GRAY}%-10s${NC} %s\n" "users" "$(who | wc -l) logged in"
|
||||
echo -e "$SEP"
|
||||
|
||||
# ── Quote ─────────────────────────────────────────────────────────────────────
|
||||
echo -e " ${PURPLE}${BOLD}✦ Quote${NC}"
|
||||
echo ""
|
||||
QDATA=$(curl -s --max-time 4 "https://zenquotes.io/api/today" 2>/dev/null)
|
||||
if echo "$QDATA" | python3 -c "import sys,json; json.load(sys.stdin)" &>/dev/null; then
|
||||
QUOTE=$(echo "$QDATA" | python3 -c "import sys,json; d=json.load(sys.stdin)[0]; print(d['q'])")
|
||||
AUTHOR=$(echo "$QDATA" | python3 -c "import sys,json; d=json.load(sys.stdin)[0]; print(d['a'])")
|
||||
echo -e " ${GRAY}\"${QUOTE}\"${NC}" | fold -s -w $((COLS - 4))
|
||||
echo -e " ${PURPLE}— ${AUTHOR}${NC}"
|
||||
else
|
||||
echo -e " ${GRAY}unavailable${NC}"
|
||||
fi
|
||||
echo -e "$SEP"
|
||||
echo ""
|
||||
Executable
+61
@@ -0,0 +1,61 @@
|
||||
invokesmoke.dev {
|
||||
header /.well-known/matrix/* Content-Type application/json
|
||||
header /.well-known/matrix/* Access-Control-Allow-Origin *
|
||||
respond /.well-known/matrix/server `{"m.server":"matrix.invokesmoke.dev:443"}`
|
||||
respond /.well-known/matrix/client `{"m.homeserver":{"base_url":"https://matrix.invokesmoke.dev"}}`
|
||||
handle {
|
||||
root * /srv
|
||||
file_server
|
||||
}
|
||||
}
|
||||
|
||||
matrix.invokesmoke.dev {
|
||||
handle /_version {
|
||||
respond `{"sha":"{env.GIT_SHA}"}`
|
||||
}
|
||||
handle /_matrix/* {
|
||||
reverse_proxy tuwunel:6167
|
||||
}
|
||||
handle /_synapse/* {
|
||||
reverse_proxy tuwunel:6167
|
||||
}
|
||||
handle {
|
||||
root * /srv
|
||||
file_server
|
||||
}
|
||||
}
|
||||
|
||||
matrix.invokesmoke.dev:8448 {
|
||||
reverse_proxy tuwunel:6167
|
||||
}
|
||||
|
||||
mealie.invokesmoke.dev {
|
||||
reverse_proxy mealie:9000
|
||||
}
|
||||
|
||||
dockge.invokesmoke.dev {
|
||||
reverse_proxy dockge:5001
|
||||
}
|
||||
|
||||
code.invokesmoke.dev {
|
||||
reverse_proxy code-server:8443
|
||||
}
|
||||
|
||||
pihole.invokesmoke.dev {
|
||||
reverse_proxy pihole:80
|
||||
}
|
||||
|
||||
gitea.invokesmoke.dev {
|
||||
reverse_proxy gitea:3000
|
||||
}
|
||||
|
||||
wetty.invokesmoke.dev {
|
||||
reverse_proxy wetty:3000 {
|
||||
header_up Upgrade {http.request.header.Upgrade}
|
||||
header_up Connection {http.request.header.Connection}
|
||||
}
|
||||
}
|
||||
|
||||
vpn.invokesmoke.dev {
|
||||
reverse_proxy wireguard:51821
|
||||
}
|
||||
Executable
+47
@@ -0,0 +1,47 @@
|
||||
services:
|
||||
caddy:
|
||||
container_name: caddy
|
||||
image: caddy:2-alpine
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- "80:80"
|
||||
- "443:443"
|
||||
- "8448:8448"
|
||||
volumes:
|
||||
- ./caddy/Caddyfile:/etc/caddy/Caddyfile:ro
|
||||
- caddy-data:/data
|
||||
- caddy-config:/config
|
||||
- /opt/srv:/srv:ro
|
||||
networks:
|
||||
- backbone
|
||||
|
||||
pihole:
|
||||
container_name: pihole
|
||||
image: pihole/pihole:latest
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- "53:53/tcp"
|
||||
- "53:53/udp"
|
||||
- "8053:80/tcp"
|
||||
environment:
|
||||
- WEBPASSWORD=${PIHOLE_PASSWORD}
|
||||
- ServerIP=192.168.1.40
|
||||
volumes:
|
||||
- etc-pihole:/etc/pihole
|
||||
- etc-dnsmasq.d:/etc/dnsmasq.d
|
||||
networks:
|
||||
- backbone
|
||||
|
||||
volumes:
|
||||
caddy-data:
|
||||
external: true
|
||||
name: backbone_caddy-data
|
||||
caddy-config:
|
||||
external: true
|
||||
name: backbone_caddy-config
|
||||
etc-pihole:
|
||||
etc-dnsmasq.d:
|
||||
|
||||
networks:
|
||||
backbone:
|
||||
name: backbone
|
||||
Executable
+83
@@ -0,0 +1,83 @@
|
||||
invokesmoke.dev {
|
||||
handle /.well-known/matrix/server {
|
||||
header Content-Type application/json
|
||||
header Access-Control-Allow-Origin *
|
||||
respond `{"m.server":"matrix.invokesmoke.dev:443"}`
|
||||
}
|
||||
handle /.well-known/matrix/client {
|
||||
header Content-Type application/json
|
||||
header Access-Control-Allow-Origin *
|
||||
respond `{"m.homeserver":{"base_url":"https://matrix.invokesmoke.dev"},"org.matrix.msc4143.rtc_foci":[{"type":"livekit","livekit_service_url":"https://livekit.invokesmoke.dev"}]}`
|
||||
}
|
||||
handle {
|
||||
root * /srv
|
||||
file_server
|
||||
}
|
||||
}
|
||||
|
||||
matrix.invokesmoke.dev {
|
||||
handle /_matrix/* {
|
||||
reverse_proxy tuwunel:6167 {
|
||||
header_up Upgrade {http.request.header.Upgrade}
|
||||
header_up Connection {http.request.header.Connection}
|
||||
}
|
||||
}
|
||||
handle /_synapse/* {
|
||||
reverse_proxy tuwunel:6167 {
|
||||
header_up Upgrade {http.request.header.Upgrade}
|
||||
header_up Connection {http.request.header.Connection}
|
||||
}
|
||||
}
|
||||
respond 404
|
||||
}
|
||||
|
||||
matrix.invokesmoke.dev:8448 {
|
||||
reverse_proxy tuwunel:6167
|
||||
}
|
||||
|
||||
livekit.invokesmoke.dev {
|
||||
handle /sfu/* {
|
||||
reverse_proxy lk-jwt-service:8080
|
||||
}
|
||||
handle /livekit/jwt* {
|
||||
reverse_proxy lk-jwt-service:8080
|
||||
}
|
||||
handle {
|
||||
reverse_proxy host.docker.internal:7880 {
|
||||
header_up Upgrade {http.request.header.Upgrade}
|
||||
header_up Connection {http.request.header.Connection}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mealie.invokesmoke.dev {
|
||||
reverse_proxy mealie:9000
|
||||
}
|
||||
|
||||
dockge.invokesmoke.dev {
|
||||
reverse_proxy dockge:5001
|
||||
}
|
||||
|
||||
code.invokesmoke.dev {
|
||||
reverse_proxy code-server:8443
|
||||
}
|
||||
|
||||
pihole.invokesmoke.dev {
|
||||
reverse_proxy pihole:80
|
||||
}
|
||||
|
||||
gitea.invokesmoke.dev {
|
||||
reverse_proxy gitea:3000
|
||||
}
|
||||
|
||||
wetty.invokesmoke.dev {
|
||||
reverse_proxy wetty:3000 {
|
||||
header_up Upgrade {http.request.header.Upgrade}
|
||||
header_up Connection {http.request.header.Connection}
|
||||
}
|
||||
}
|
||||
|
||||
vpn.invokesmoke.dev {
|
||||
reverse_proxy wireguard:51821
|
||||
}
|
||||
|
||||
Executable
+30
@@ -0,0 +1,30 @@
|
||||
services:
|
||||
caddy:
|
||||
container_name: caddy
|
||||
image: caddy:2-alpine
|
||||
extra_hosts:
|
||||
- "host.docker.internal:host-gateway"
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- "80:80"
|
||||
- "443:443"
|
||||
- "8448:8448"
|
||||
volumes:
|
||||
- ./caddy/Caddyfile:/etc/caddy/Caddyfile:ro
|
||||
- caddy-data:/data
|
||||
- caddy-config:/config
|
||||
- /opt/srv:/srv:ro
|
||||
networks:
|
||||
- backbone
|
||||
|
||||
volumes:
|
||||
caddy-data:
|
||||
external: true
|
||||
name: backbone_caddy-data
|
||||
caddy-config:
|
||||
external: true
|
||||
name: backbone_caddy-config
|
||||
|
||||
networks:
|
||||
backbone:
|
||||
external: true
|
||||
Executable
+26
@@ -0,0 +1,26 @@
|
||||
services:
|
||||
code-server:
|
||||
image: lscr.io/linuxserver/code-server:latest
|
||||
container_name: code-server
|
||||
hostname: code-server
|
||||
environment:
|
||||
- PUID=1000
|
||||
- PGID=998
|
||||
- TZ=America/New_York
|
||||
- PASSWORD=${CODE_PASSWORD}
|
||||
- SUDO_PASSWORD=${CODE_SUDO_PASSWORD}
|
||||
- DOCKER_MODS=linuxserver/mods:universal-docker
|
||||
volumes:
|
||||
- /opt:/opt
|
||||
- /home/sam:/home/sam
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
- /opt/codeserver/config:/config
|
||||
ports:
|
||||
- "8443:8443"
|
||||
restart: unless-stopped
|
||||
networks:
|
||||
- backbone
|
||||
|
||||
networks:
|
||||
backbone:
|
||||
external: true
|
||||
@@ -0,0 +1,24 @@
|
||||
services:
|
||||
socket-proxy:
|
||||
image: tecnativa/docker-socket-proxy
|
||||
container_name: docker-socket
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock:ro
|
||||
ports:
|
||||
- 2375:2375
|
||||
environment:
|
||||
CONTAINERS: 1
|
||||
IMAGES: 1
|
||||
INFO: 1
|
||||
NETWORKS: 1
|
||||
VOLUMES: 1
|
||||
SERVICES: 1
|
||||
TASKS: 1
|
||||
POST: 1
|
||||
ALLOW_START: 1
|
||||
ALLOW_STOP: 1
|
||||
ALLOW_RESTARTS: 1
|
||||
networks:
|
||||
backbone:
|
||||
external: true
|
||||
@@ -0,0 +1,20 @@
|
||||
services:
|
||||
dockge:
|
||||
image: louislam/dockge:1
|
||||
container_name: dockge
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
- dockge-data:/app/data
|
||||
- /opt/stacks:/opt/stacks
|
||||
environment:
|
||||
DOCKGE_STACKS_DIR: /opt/stacks
|
||||
networks:
|
||||
- backbone
|
||||
|
||||
volumes:
|
||||
dockge-data:
|
||||
|
||||
networks:
|
||||
backbone:
|
||||
external: true
|
||||
Executable
+20
@@ -0,0 +1,20 @@
|
||||
services:
|
||||
gitea:
|
||||
image: gitea/gitea:latest
|
||||
container_name: gitea
|
||||
environment:
|
||||
- USER_UID=1000
|
||||
- USER_GID=1000
|
||||
- GITEA__database__DB_TYPE=sqlite3
|
||||
volumes:
|
||||
- /opt/gitea/data:/data
|
||||
ports:
|
||||
- "3001:3000"
|
||||
- "222:22"
|
||||
restart: unless-stopped
|
||||
networks:
|
||||
- backbone
|
||||
|
||||
networks:
|
||||
backbone:
|
||||
external: true
|
||||
Executable
+62
@@ -0,0 +1,62 @@
|
||||
services:
|
||||
homebridge:
|
||||
container_name: homebridge
|
||||
image: homebridge/homebridge:latest
|
||||
restart: unless-stopped
|
||||
network_mode: host
|
||||
environment:
|
||||
- HOMEBRIDGE_CONFIG_UI_PORT=8581
|
||||
- ENABLE_AVAHI=1
|
||||
volumes:
|
||||
- homebridge-data:/homebridge
|
||||
|
||||
scrypted:
|
||||
container_name: scrypted
|
||||
image: koush/scrypted:latest
|
||||
restart: unless-stopped
|
||||
network_mode: host
|
||||
environment:
|
||||
- SCRYPTED_WEBHOOK_UPDATE_AUTHORIZATION=SET_THIS_TO_SOME_RANDOM_TEXT_BROHAM
|
||||
- SCRYPTED_WEBHOOK_UPDATE=http://localhost:10444/v1/update
|
||||
- ENABLE_AUDIO=True
|
||||
volumes:
|
||||
- /.scrypted/volume:/server/volume
|
||||
labels:
|
||||
- "com.centurylinklabs.watchtower.scope=scrypted"
|
||||
|
||||
wyze-bridge:
|
||||
container_name: wyze-bridge
|
||||
image: mrlt8/wyze-bridge:latest
|
||||
restart: unless-stopped
|
||||
network_mode: host
|
||||
environment:
|
||||
- WYZE_EMAIL=acwallace520@gmail.com
|
||||
- WYZE_PASSWORD=Alexander!626
|
||||
- API_ID=b98f65a0-92b6-4772-baa7-cde4663143f8
|
||||
- API_KEY=vhEztGgO1gRNL5utan5Bw1V6Z0TgTyle4EhYPpkmZD5klwBJ2nHQHCcItHUi
|
||||
- WB_AUTH=False
|
||||
- ENABLE_AUDIO=True
|
||||
- AUDIO_CODEC=AAC
|
||||
- RTSP_FW=Force
|
||||
|
||||
scrypted-watchtower:
|
||||
container_name: scrypted-watchtower
|
||||
image: containrrr/watchtower
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
- WATCHTOWER_SCOPE=scrypted
|
||||
- WATCHTOWER_HTTP_API_PERIODIC_POLLS=true
|
||||
- WATCHTOWER_HTTP_API_TOKEN=SET_THIS_TO_SOME_RANDOM_TEXT_BRO
|
||||
- WATCHTOWER_HTTP_API_UPDATE=true
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
command: --interval 3600 --cleanup --scope scrypted
|
||||
labels:
|
||||
- "com.centurylinklabs.watchtower.scope=scrypted"
|
||||
ports:
|
||||
- "10444:8080"
|
||||
|
||||
volumes:
|
||||
homebridge-data:
|
||||
external: true
|
||||
name: homebridge_homebridge
|
||||
Executable
+16
@@ -0,0 +1,16 @@
|
||||
services:
|
||||
homebridge:
|
||||
container_name: homebridge
|
||||
image: homebridge/homebridge:latest
|
||||
restart: unless-stopped
|
||||
network_mode: host
|
||||
environment:
|
||||
- HOMEBRIDGE_CONFIG_UI_PORT=8581
|
||||
- ENABLE_AVAHI=1
|
||||
volumes:
|
||||
- homebridge-data:/homebridge
|
||||
|
||||
volumes:
|
||||
homebridge-data:
|
||||
external: true
|
||||
name: homebridge_homebridge
|
||||
Submodule
+1
Submodule stacks/matrix added at 46f1bded39
Executable
+23
@@ -0,0 +1,23 @@
|
||||
services:
|
||||
mealie:
|
||||
container_name: mealie
|
||||
image: ghcr.io/mealie-recipes/mealie:latest
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- "9925:9000"
|
||||
environment:
|
||||
BASE_URL: "https://mealie.invokesmoke.dev"
|
||||
volumes:
|
||||
- mealie-data:/app/data
|
||||
networks:
|
||||
- backbone
|
||||
|
||||
volumes:
|
||||
mealie-data:
|
||||
external: true
|
||||
name: "766bc8605e066d1eba7287428e4e4130442f8a9473d730ed4abfd5fdd47c9076"
|
||||
|
||||
networks:
|
||||
backbone:
|
||||
external: true
|
||||
name: backbone
|
||||
Executable
+29
@@ -0,0 +1,29 @@
|
||||
services:
|
||||
pihole:
|
||||
container_name: pihole
|
||||
image: pihole/pihole:latest
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- "53:53/tcp"
|
||||
- "53:53/udp"
|
||||
- "8053:80/tcp"
|
||||
environment:
|
||||
- WEBPASSWORD=${PIHOLE_PASSWORD}
|
||||
- ServerIP=192.168.1.40
|
||||
volumes:
|
||||
- etc-pihole:/etc/pihole
|
||||
- etc-dnsmasq.d:/etc/dnsmasq.d
|
||||
networks:
|
||||
- backbone
|
||||
|
||||
volumes:
|
||||
etc-pihole:
|
||||
external: true
|
||||
name: etc-pihole
|
||||
etc-dnsmasq.d:
|
||||
external: true
|
||||
name: etc-dnsmasq.d
|
||||
|
||||
networks:
|
||||
backbone:
|
||||
name: backbone
|
||||
@@ -0,0 +1,158 @@
|
||||
#!/usr/bin/env bash
|
||||
# =============================================================
|
||||
# do-update.sh
|
||||
# Interactive picker to update containers flagged by Watchtower.
|
||||
# Pulls new image, recreates container via its compose file,
|
||||
# and prunes old images.
|
||||
#
|
||||
# Usage:
|
||||
# bash /opt/stacks/scripts/do-update.sh
|
||||
# =============================================================
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
CYAN='\033[0;36m'
|
||||
GRAY='\033[0;90m'
|
||||
BOLD='\033[1m'
|
||||
NC='\033[0m'
|
||||
|
||||
# ── Check Watchtower is running ───────────────────────────────
|
||||
if ! docker inspect watchtower &>/dev/null; then
|
||||
echo -e "${RED}✗ Watchtower is not running.${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# ── Get outdated images from Watchtower logs ──────────────────
|
||||
OUTDATED_IMAGES=()
|
||||
while IFS= read -r line; do
|
||||
img=$(echo "$line" | grep -oP '(?<=Found new )\S+(?= image)')
|
||||
[ -n "$img" ] && OUTDATED_IMAGES+=("$img")
|
||||
done < <(docker logs watchtower --since 36h 2>&1 | grep "Found new")
|
||||
|
||||
if [ ${#OUTDATED_IMAGES[@]} -eq 0 ]; then
|
||||
echo -e "${GREEN}✓ No updates available per last Watchtower scan.${NC}"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# ── Build list of containers to update ───────────────────────
|
||||
declare -a CONTAINER_NAMES
|
||||
declare -a CONTAINER_IMAGES
|
||||
declare -a CONTAINER_COMPOSE_DIRS
|
||||
declare -a CONTAINER_SERVICES
|
||||
|
||||
for image in "${OUTDATED_IMAGES[@]}"; do
|
||||
while IFS='|' read -r cname cimage; do
|
||||
COMPOSE_DIR=$(docker inspect "$cname" \
|
||||
--format '{{index .Config.Labels "com.docker.compose.project.working_dir"}}' 2>/dev/null || echo "")
|
||||
SERVICE=$(docker inspect "$cname" \
|
||||
--format '{{index .Config.Labels "com.docker.compose.service"}}' 2>/dev/null || echo "")
|
||||
CONTAINER_NAMES+=("$cname")
|
||||
CONTAINER_IMAGES+=("$cimage")
|
||||
CONTAINER_COMPOSE_DIRS+=("$COMPOSE_DIR")
|
||||
CONTAINER_SERVICES+=("$SERVICE")
|
||||
done < <(docker ps -a --format '{{.Names}}|{{.Image}}' | awk -F'|' -v img="$image" '$2==img')
|
||||
done
|
||||
|
||||
if [ ${#CONTAINER_NAMES[@]} -eq 0 ]; then
|
||||
echo -e "${YELLOW}⚠ Outdated images found but no matching running containers.${NC}"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# ── Show menu ─────────────────────────────────────────────────
|
||||
echo ""
|
||||
echo -e "${BOLD}Available updates:${NC}"
|
||||
echo ""
|
||||
for i in "${!CONTAINER_NAMES[@]}"; do
|
||||
idx=$((i + 1))
|
||||
name="${CONTAINER_NAMES[$i]}"
|
||||
image="${CONTAINER_IMAGES[$i]}"
|
||||
svc="${CONTAINER_SERVICES[$i]}"
|
||||
dir="${CONTAINER_COMPOSE_DIRS[$i]}"
|
||||
printf " ${CYAN}%2d)${NC} %-20s ${GRAY}%-40s${NC}\n" "$idx" "$name" "$image"
|
||||
if [ -n "$dir" ]; then
|
||||
printf " ${GRAY}compose: %s service: %s${NC}\n" "$dir" "$svc"
|
||||
fi
|
||||
done
|
||||
echo ""
|
||||
echo -e " ${GRAY}a)${NC} update all"
|
||||
echo -e " ${GRAY}q)${NC} quit"
|
||||
echo ""
|
||||
read -rp " Enter numbers to update (e.g. 1 3 5): " SELECTION
|
||||
|
||||
if [ "$SELECTION" = "q" ] || [ -z "$SELECTION" ]; then
|
||||
echo -e "\n ${GRAY}Cancelled.${NC}"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# ── Build list of selected indices ────────────────────────────
|
||||
SELECTED=()
|
||||
if [ "$SELECTION" = "a" ]; then
|
||||
for i in "${!CONTAINER_NAMES[@]}"; do SELECTED+=("$i"); done
|
||||
else
|
||||
for num in $SELECTION; do
|
||||
idx=$((num - 1))
|
||||
if [ "$idx" -ge 0 ] && [ "$idx" -lt "${#CONTAINER_NAMES[@]}" ]; then
|
||||
SELECTED+=("$idx")
|
||||
else
|
||||
echo -e " ${YELLOW}⚠ Skipping invalid selection: ${num}${NC}"
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
if [ ${#SELECTED[@]} -eq 0 ]; then
|
||||
echo -e " ${YELLOW}No valid selections.${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# ── Confirm ───────────────────────────────────────────────────
|
||||
echo ""
|
||||
echo -e "${BOLD}Will update:${NC}"
|
||||
for i in "${SELECTED[@]}"; do
|
||||
echo -e " ${GREEN}→${NC} ${CONTAINER_NAMES[$i]} ${GRAY}(${CONTAINER_IMAGES[$i]})${NC}"
|
||||
done
|
||||
echo ""
|
||||
read -rp " Proceed? [y/N] " CONFIRM
|
||||
[[ "$CONFIRM" =~ ^[Yy]$ ]] || { echo -e " ${GRAY}Aborted.${NC}"; exit 0; }
|
||||
|
||||
# ── Update selected containers ────────────────────────────────
|
||||
PRUNED=0
|
||||
for i in "${SELECTED[@]}"; do
|
||||
name="${CONTAINER_NAMES[$i]}"
|
||||
image="${CONTAINER_IMAGES[$i]}"
|
||||
dir="${CONTAINER_COMPOSE_DIRS[$i]}"
|
||||
svc="${CONTAINER_SERVICES[$i]}"
|
||||
|
||||
echo ""
|
||||
echo -e "${CYAN}── Updating ${name} ──────────────────────────────────────${NC}"
|
||||
|
||||
echo -e " ${GRAY}pulling ${image}...${NC}"
|
||||
docker pull "$image"
|
||||
|
||||
if [ -n "$dir" ] && [ -d "$dir" ]; then
|
||||
echo -e " ${GRAY}recreating via compose...${NC}"
|
||||
docker compose -f "$dir/docker-compose.yml" up -d --force-recreate "$svc"
|
||||
else
|
||||
echo -e " ${YELLOW}⚠ No compose dir found — recreating container manually${NC}"
|
||||
docker stop "$name" 2>/dev/null || true
|
||||
docker rm "$name" 2>/dev/null || true
|
||||
echo -e " ${YELLOW} Container removed. Restart manually with your compose file.${NC}"
|
||||
fi
|
||||
|
||||
echo -e " ${GREEN}✓ ${name} updated${NC}"
|
||||
PRUNED=1
|
||||
done
|
||||
|
||||
# ── Prune old images ──────────────────────────────────────────
|
||||
if [ "$PRUNED" -eq 1 ]; then
|
||||
echo ""
|
||||
echo -e "${GRAY}Pruning dangling images...${NC}"
|
||||
docker image prune -f
|
||||
echo -e "${GREEN}✓ Done.${NC}"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo -e "${GREEN}${BOLD}All selected containers updated.${NC}"
|
||||
echo ""
|
||||
@@ -0,0 +1,39 @@
|
||||
# image-sources.conf
|
||||
# Maps Docker image names to their GitHub repos for changelog lookup.
|
||||
# Format: ["image/name"]="github-owner/repo"
|
||||
# Add entries here as you add new services.
|
||||
|
||||
declare -A IMAGE_REPOS=(
|
||||
# Matrix stack
|
||||
["jevolk/tuwunel"]="jevolk/tuwunel"
|
||||
["livekit/livekit-server"]="livekit/livekit"
|
||||
["ghcr.io/element-hq/lk-jwt-service"]="element-hq/lk-jwt-service"
|
||||
["coturn/coturn"]="coturn/coturn"
|
||||
|
||||
# Code Server
|
||||
["lscr.io/linuxserver/code-server"]="linuxserver/docker-code-server"
|
||||
|
||||
# Caddy
|
||||
["caddy"]="caddyserver/caddy"
|
||||
|
||||
# Gitea
|
||||
["gitea/gitea"]="go-gitea/gitea"
|
||||
|
||||
# Homebridge
|
||||
["homebridge/homebridge"]="homebridge/homebridge"
|
||||
|
||||
# Mealie
|
||||
["ghcr.io/mealie-recipes/mealie"]="mealie-recipes/mealie"
|
||||
|
||||
# Pi-hole
|
||||
["pihole/pihole"]="pi-hole/pi-hole"
|
||||
|
||||
# Scrypted
|
||||
["koush/scrypted"]="koush/scrypted"
|
||||
|
||||
# Wyze Bridge
|
||||
["mrlt8/wyze-bridge"]="mrlt8/docker-wyze-bridge"
|
||||
|
||||
# Watchtower
|
||||
["containrrr/watchtower"]="containrrr/watchtower"
|
||||
)
|
||||
@@ -0,0 +1,114 @@
|
||||
#!/usr/bin/env bash
|
||||
# =============================================================
|
||||
# update-check.sh
|
||||
# Reads Watchtower's recent logs to find outdated images,
|
||||
# maps them to containers, and fetches GitHub release notes.
|
||||
#
|
||||
# Usage:
|
||||
# bash /opt/stacks/scripts/update-check.sh
|
||||
# =============================================================
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
source "$SCRIPT_DIR/image-sources.conf"
|
||||
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
CYAN='\033[0;36m'
|
||||
GRAY='\033[0;90m'
|
||||
BOLD='\033[1m'
|
||||
NC='\033[0m'
|
||||
|
||||
SEP="${GRAY}$(printf '─%.0s' $(seq 1 60))${NC}"
|
||||
|
||||
# ── Check Watchtower is running ───────────────────────────────
|
||||
if ! docker inspect watchtower &>/dev/null; then
|
||||
echo -e "${RED}✗ Watchtower is not running.${NC}"
|
||||
echo -e " Start it: cd /opt/stacks/watchtower && docker compose up -d"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# ── Parse Watchtower logs for outdated images (last 36h) ─────
|
||||
echo -e "${BOLD}Checking Watchtower logs for updates...${NC}"
|
||||
echo ""
|
||||
|
||||
OUTDATED_IMAGES=()
|
||||
while IFS= read -r line; do
|
||||
# Extract image name from: "Found new some/image:tag image (sha256:...)"
|
||||
img=$(echo "$line" | grep -oP '(?<=Found new )\S+(?= image)')
|
||||
[ -n "$img" ] && OUTDATED_IMAGES+=("$img")
|
||||
done < <(docker logs watchtower --since 36h 2>&1 | grep "Found new")
|
||||
|
||||
if [ ${#OUTDATED_IMAGES[@]} -eq 0 ]; then
|
||||
echo -e "${GREEN}✓ All images are up to date${NC} ${GRAY}(per last Watchtower scan)${NC}"
|
||||
echo ""
|
||||
LAST=$(docker logs watchtower --since 72h 2>&1 | grep "Session done" | tail -1 | grep -oP '\d{4}-\d{2}-\d{2}T\d{2}:\d{2}')
|
||||
[ -n "$LAST" ] && echo -e "${GRAY} Last scan: ${LAST}${NC}"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo -e "${YELLOW}${BOLD}${#OUTDATED_IMAGES[@]} image update(s) available:${NC}"
|
||||
echo ""
|
||||
|
||||
# ── For each outdated image: find container + fetch notes ─────
|
||||
gh_release_notes() {
|
||||
local repo=$1
|
||||
local result
|
||||
result=$(curl -sf "https://api.github.com/repos/${repo}/releases/latest" 2>/dev/null) || true
|
||||
if [ -n "$result" ]; then
|
||||
TAG=$(echo "$result" | python3 -c "import sys,json; d=json.load(sys.stdin); print(d.get('tag_name','?'))" 2>/dev/null)
|
||||
BODY=$(echo "$result" | python3 -c "
|
||||
import sys,json,re
|
||||
d=json.load(sys.stdin)
|
||||
body=d.get('body','No release notes available.')
|
||||
# Strip markdown links/badges, collapse whitespace
|
||||
body=re.sub(r'!\[.*?\]\(.*?\)','',body)
|
||||
body=re.sub(r'\[([^\]]+)\]\([^\)]+\)',r'\1',body)
|
||||
body=re.sub(r'<!--.*?-->','',body,flags=re.DOTALL)
|
||||
lines=[l.strip() for l in body.split('\n') if l.strip()]
|
||||
print('\n'.join(lines[:6]))
|
||||
" 2>/dev/null || echo "No release notes available.")
|
||||
echo "$TAG|$BODY"
|
||||
fi
|
||||
}
|
||||
|
||||
for image in "${OUTDATED_IMAGES[@]}"; do
|
||||
# Find container(s) using this image
|
||||
CONTAINERS=$(docker ps -a --format '{{.Names}}|{{.Image}}' | awk -F'|' -v img="$image" '$2==img {print $1}' | tr '\n' ' ')
|
||||
[ -z "$CONTAINERS" ] && CONTAINERS="${GRAY}(no running containers)${NC}"
|
||||
|
||||
echo -e "$SEP"
|
||||
echo -e " ${CYAN}${BOLD}${image}${NC}"
|
||||
echo -e " ${GRAY}containers:${NC} ${CONTAINERS}"
|
||||
|
||||
# Strip tag for image name lookup
|
||||
base_image=$(echo "$image" | sed 's/:.*//')
|
||||
|
||||
if [ -n "${IMAGE_REPOS[$base_image]+_}" ]; then
|
||||
REPO="${IMAGE_REPOS[$base_image]}"
|
||||
RELEASE=$(gh_release_notes "$REPO")
|
||||
if [ -n "$RELEASE" ]; then
|
||||
TAG=$(echo "$RELEASE" | cut -d'|' -f1)
|
||||
NOTES=$(echo "$RELEASE" | cut -d'|' -f2-)
|
||||
echo -e " ${GRAY}latest tag:${NC} ${GREEN}${TAG}${NC}"
|
||||
echo -e " ${GRAY}notes:${NC}"
|
||||
while IFS= read -r line; do
|
||||
echo -e " ${GRAY}${line}${NC}"
|
||||
done <<< "$NOTES"
|
||||
echo -e " ${GRAY}full notes:${NC} https://github.com/${REPO}/releases/latest"
|
||||
else
|
||||
echo -e " ${GRAY}→ https://hub.docker.com/r/${base_image}/tags${NC}"
|
||||
fi
|
||||
else
|
||||
echo -e " ${GRAY}no GitHub mapping — add to scripts/image-sources.conf${NC}"
|
||||
echo -e " ${GRAY}→ https://hub.docker.com/r/${base_image}/tags${NC}"
|
||||
fi
|
||||
echo ""
|
||||
done
|
||||
|
||||
echo -e "$SEP"
|
||||
echo ""
|
||||
echo -e " Ready to update? Run: ${CYAN}bash /opt/stacks/scripts/do-update.sh${NC}"
|
||||
echo ""
|
||||
Executable
+31
@@ -0,0 +1,31 @@
|
||||
services:
|
||||
scrypted:
|
||||
container_name: scrypted
|
||||
image: koush/scrypted:latest
|
||||
restart: unless-stopped
|
||||
network_mode: host
|
||||
environment:
|
||||
- SCRYPTED_WEBHOOK_UPDATE_AUTHORIZATION=23e46534ef408ec7c221da15c2cda92892ca5c4a637249075fbdf39358dbbaaa
|
||||
- SCRYPTED_WEBHOOK_UPDATE=http://localhost:10444/v1/update
|
||||
- ENABLE_AUDIO=True
|
||||
volumes:
|
||||
- /.scrypted/volume:/server/volume
|
||||
labels:
|
||||
- "com.centurylinklabs.watchtower.scope=scrypted"
|
||||
|
||||
scrypted-watchtower:
|
||||
container_name: scrypted-watchtower
|
||||
image: containrrr/watchtower
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
- WATCHTOWER_SCOPE=scrypted
|
||||
- WATCHTOWER_HTTP_API_PERIODIC_POLLS=true
|
||||
- WATCHTOWER_HTTP_API_TOKEN=18fc4c286cb14ce86e8719b939fd23036dbb843c451c88344f2e2edd0160a4eb
|
||||
- WATCHTOWER_HTTP_API_UPDATE=true
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
command: --interval 3600 --cleanup --scope scrypted
|
||||
labels:
|
||||
- "com.centurylinklabs.watchtower.scope=scrypted"
|
||||
ports:
|
||||
- "10444:8080"
|
||||
@@ -0,0 +1,20 @@
|
||||
services:
|
||||
watchtower:
|
||||
image: containrrr/watchtower:latest
|
||||
container_name: watchtower
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
command:
|
||||
- --monitor-only
|
||||
- --schedule
|
||||
- "0 0 3 * * *"
|
||||
- --include-stopped
|
||||
- --log-level=info
|
||||
networks:
|
||||
- backbone
|
||||
|
||||
networks:
|
||||
backbone:
|
||||
external: true
|
||||
name: backbone
|
||||
Executable
+29
@@ -0,0 +1,29 @@
|
||||
services:
|
||||
wg-easy:
|
||||
image: ghcr.io/wg-easy/wg-easy
|
||||
container_name: wireguard
|
||||
environment:
|
||||
- LANG=en
|
||||
- WG_HOST=104.230.231.144
|
||||
- PASSWORD_HASH=$$2a$$12$$BSBRXnlt8Bdcqb25qruo9.6HamIVlsmreo33ja0pHZUEghUnzPCIK
|
||||
- WG_PORT=51820
|
||||
- WG_DEFAULT_DNS=192.168.1.40
|
||||
- WG_ALLOWED_IPS=192.168.1.0/24
|
||||
volumes:
|
||||
- /opt/wireguard/data:/etc/wireguard
|
||||
ports:
|
||||
- "51820:51820/udp"
|
||||
- "41821:51821/tcp"
|
||||
restart: unless-stopped
|
||||
cap_add:
|
||||
- NET_ADMIN
|
||||
- SYS_MODULE
|
||||
sysctls:
|
||||
- net.ipv4.ip_forward=1
|
||||
- net.ipv4.conf.all.src_valid_mark=1
|
||||
networks:
|
||||
- backbone
|
||||
|
||||
networks:
|
||||
backbone:
|
||||
external: true
|
||||
Executable
+15
@@ -0,0 +1,15 @@
|
||||
services:
|
||||
wyze-bridge:
|
||||
container_name: wyze-bridge
|
||||
image: mrlt8/wyze-bridge:latest
|
||||
restart: unless-stopped
|
||||
network_mode: host
|
||||
environment:
|
||||
- WYZE_EMAIL=acwallace520@gmail.com
|
||||
- WYZE_PASSWORD=Alexander!626
|
||||
- API_ID=b98f65a0-92b6-4772-baa7-cde4663143f8
|
||||
- API_KEY=vhEztGgO1gRNL5utan5Bw1V6Z0TgTyle4EhYPpkmZD5klwBJ2nHQHCcItHUi
|
||||
- WB_AUTH=False
|
||||
- ENABLE_AUDIO=True
|
||||
- AUDIO_CODEC=AAC
|
||||
- RTSP_FW=Force
|
||||
Regular → Executable
Reference in New Issue
Block a user