commit 70db1934bee975840a27385e81594f00747011d4 Author: Leon van Kammen Date: Thu Mar 5 14:02:37 2026 +0100 🔧 master: work in progress [might break] diff --git a/admin b/admin new file mode 100755 index 0000000..f571c51 --- /dev/null +++ b/admin @@ -0,0 +1,149 @@ +#!/bin/bash +# +# curlcheck: https://playterm.org +# curlcheck: https://electribrary.electribers.com +# curlcheck: https://2wa.isvery.ninja + +disk(){ + space(){ + df -h | awk '$6 ~ /^\/$/ {print $3" total used ("$5") of "$4}' + #echo '-------' + #ls /home | while read user; do du -hs /home/$user; done + } + "$@" +} + +health(){ + echo "URL ONLINE SSL TIME" + echo "- - - -" + awk '/^# curlcheck: / {print $3}' $0 | while read url; do + printf "%s" "$url" | sed 's|.*://||g' + curl -v -w 'Total: %{time_total}s\n' ${url} 2>&1 | \ + awk ' + BEGIN{ + err="\033[5m\033[36;5;94m❌\033[0m" + ok="\033[1;36m♥\033[0m" + c["SSL"]=err + c["ONL"]=ok + c["TIM"]="?" + } + /SSL certificate verify ok/ {c["SSL"]=ok } + /Could not resolve host:/ {c["ONL"]=err } + /^Total: / {c["TIM"]=$2 } + END { printf "\r\t\t\t\t"c["ONL"]" "c["SSL"]" "c["TIM"]"\n" } + ' + done +} + +init(){ + grep ulimit /etc/profile || echo 'ulimit -n 65535 || true' >> /etc/profile # compensate alpine's low fd's +} + +proxy(){ + install(){ + echo -e "\n[forwarded ports]" > .ports + iptables -t nat -F # flush + iptables -t nat -X # flush + iptables -F # flush + ip6tables -F -t nat# flush + ip6tables -F # flush + ip6tables -X # flush + ip6tables -t nat -F + ip6tables -t nat -X + ip_external=$(curl -s https://checkip.amazonaws.com) + ipv6_external=$(ip addr | awk '/inet6.*scope global/ { print $2 }') + # proxies + proxyport(){ + printf " %-5s => %-10s [%s]\n" $1 $2 $3 >> .ports + iptables -t nat -A PREROUTING -i eth0 -p tcp --dport $1 -j REDIRECT --to-ports $2 + #ip6tables -t nat -A PREROUTING -i eth0 -p tcp --dport $1 -j REDIRECT --to-ports $2 + #iptables -t nat -I OUTPUT -p tcp -d 127.0.0.1 --dport $1 -j REDIRECT --to-ports $2 + iptables -t nat -I OUTPUT -p tcp -d $ip_external --dport $1 -j REDIRECT --to-ports $2 # reverse ip + #ip6tables -t nat -I OUTPUT -p tcp -d $ipv6_external --dport $1 -j REDIRECT --to-ports $2 # reverse ip + ip6tables -A INPUT -p tcp --dport $1 -j ACCEPT + ip6tables -A OUTPUT -p tcp --dport $1 -j ACCEPT + #iptables -t nat -A POSTROUTING -p tcp --dport $2 -j MASQUERADE + #iptables -t nat -A POSTROUTING -p tcp --dport $2 -j MASQUERADE + } + proxyport 80 8080 nginx-proxy-manager + #proxyport 81 8181 nginx-proxy-manager + proxyport 443 4443 nginx-proxy-manager + #proxyport 993 9993 stalwart-mail + #proxyport 25 2225 stalwart-mail + #proxyport 465 4465 stalwart-mail + #proxyport 587 5587 nodered + #proxyport 25 5587 nodered + + # block port 3000 (nginx-proxy-manager exposes it) + iptables -A INPUT -p tcp -d $ip_external --dport 3000 -j REJECT + ip6tables -A INPUT -p tcp -d $ip_external --dport 3000 -j REJECT --reject-with icmp6-adm-unreach-3 + + # block port 25 + #iptables -A INPUT -p tcp -d $ip_external --dport 25 -j REJECT + #ip6tables -A INPUT -p tcp -d $ip_external --dport 25-j REJECT + + # block irc 0.0.0.0:6667 port except for nodered docker + iptables -A INPUT -i lo -p tcp --dport 6667 -j ACCEPT + iptables -A INPUT -s 10.0.2.2 -p tcp --dport 6667 -j ACCEPT + iptables -A INPUT -p tcp --dport 6667 -j REJECT + ip6tables -A INPUT -i lo -j ACCEPT + ip6tables -A INPUT -s fd00::/64 -p tcp --dport 6667 -j ACCEPT + ip6tables -A INPUT -p tcp --dport 6667 -j REJECT + + # rateliming per ip + #iptables --new-chain RATE-LIMIT + #iptables --append RATE-LIMIT \ + # --match hashlimit \ + # --hashlimit-mode srcip \ + # --hashlimit-upto 50/sec \ + # --hashlimit-burst 20 \ + # --hashlimit-name conn_rate_limit \ + # --jump ACCEPT + #iptables --append RATE-LIMIT --jump DROP + rc-update add iptables + rc-update add ip6tables + /etc/init.d/iptables save + /etc/init.d/ip6tables save + } + + clear + "$@" + { + iptables -t nat -L -n -v + iptables -L + ip6tables -L + } | more + cat .ports +} + +logs(){ + tail -qf /home/2wa/nginx-proxy-manager/data/log/*.log | grep -v favicon | sed 's|\] \[.*|]|g' +} + +backup(){ + cd /root + echo "$(date) ./admin backup [start]" >> .cron.log + BACKUP=backup-2wa.isvery.ninja.zip + crontab -l > crontab.root.txt + apk list -i > alpine.packages.txt + echo "$(su -c 'crontab -l' 2wa)" > crontab.2wa.txt + nice -n 19 /usr/bin/ionice -c2 -n7 zip -r $BACKUP \ + /root/admin /root/crontab.* /root/alpine*.txt /root/.ssh \ + /home/2wa/.ssh /home/2wa/.config /home/2wa/nginx-proxy-manager/{app.sh,data,*.key} \ + /home/2wa/weechat-redbean \ + /home/2wa/invoiceninja \ + /home/2wa/mailtrain \ + /home/2wa/stalwart-mail \ + /home/2wa/node-red \ + /home/2wa/ntfy \ + /home/2wa/portsleep* \ + /home/2wa/tcgi* \ + /home/2wa/stats \ + -x '*.log.*' -x '*.weecha*' -x 'postfix/*' | awk '{ printf( "\r"$0 ) } END{ print ""}' + ls -lah $BACKUP + rclone copy $BACKUP stack:backup/. --progress + echo "$(date) ./admin backup [stop]" >> /root/.cron.log +} + +test -z $1 && { echo "Usage: "; grep '(){' $0; } +"$@" diff --git a/docker-compose.yaml b/docker-compose.yaml new file mode 100644 index 0000000..19504a6 --- /dev/null +++ b/docker-compose.yaml @@ -0,0 +1,13 @@ +# docker-compose.yml +services: + traefik: + image: traefik:v3.6 + command: + - "--api.insecure=true" + - "--providers.docker=true" + - "--entrypoints.web.address=:80" + ports: + - "80:80" + - "8080:8080" + volumes: + - /var/run/docker.sock:/var/run/docker.sock diff --git a/glance.yml b/glance.yml new file mode 100644 index 0000000..495c9de --- /dev/null +++ b/glance.yml @@ -0,0 +1,86 @@ +server: + host: localhost + port: 8081 +pages: + - name: Home + columns: + - size: small + widgets: + - type: calendar + first-day-of-week: monday + + - type: rss + limit: 10 + collapse-after: 3 + cache: 12h + feeds: + - url: https://selfh.st/rss/ + title: selfh.st + limit: 4 + - url: https://ciechanow.ski/atom.xml + - url: https://www.joshwcomeau.com/rss.xml + title: Josh Comeau + - url: https://samwho.dev/rss.xml + - url: https://ishadeed.com/feed.xml + title: Ahmad Shadeed + + - type: twitch-channels + channels: + - theprimeagen + - j_blow + - piratesoftware + - cohhcarnage + - christitustech + - EJ_SA + + - size: full + widgets: + - type: group + widgets: + - type: hacker-news + - type: lobsters + + - type: videos + channels: + - UCXuqSBlHAE6Xw-yeJA0Tunw # Linus Tech Tips + - UCR-DXc1voovS8nhAvccRZhg # Jeff Geerling + - UCsBjURrPoezykLs9EqgamOA # Fireship + - UCBJycsmduvYEL83R_U4JriQ # Marques Brownlee + - UCHnyfMqiRRG1u-2MsSQLbXA # Veritasium + + - type: group + widgets: + - type: reddit + subreddit: technology + show-thumbnails: true + - type: reddit + subreddit: selfhosted + show-thumbnails: true + + - size: small + widgets: + - type: weather + location: London, United Kingdom + units: metric + hour-format: 12h + + - type: markets + markets: + - symbol: SPY + name: S&P 500 + - symbol: BTC-USD + name: Bitcoin + - symbol: NVDA + name: NVIDIA + - symbol: AAPL + name: Apple + - symbol: MSFT + name: Microsoft + + - type: releases + cache: 1d + repositories: + - glanceapp/glance + - go-gitea/gitea + - immich-app/immich + - syncthing/syncthing diff --git a/process-compose.yaml b/process-compose.yaml new file mode 100644 index 0000000..4efbef0 --- /dev/null +++ b/process-compose.yaml @@ -0,0 +1,56 @@ +mcp_server: + host: localhost + port: 3000 + transport: sse + +version: "0.5" +disable_env_expansion: true +vars: + FOO: 1 # {{.FOO}} + +processes: + install: + disabled: true # run `process-compose run install` + command: | + util/wget a69b6424cda4887e84247b1e01dbfb36ae613ac2cb37f19e307889db2cecc39b https://github.com/glanceapp/glance/releases/download/v0.8.4/glance-linux-amd64.tar.gz + + paramjob: + command: "echo @{foo}" + description: "parametrized job" + disabled: true # MCP processes must be disabled initially + working_dir: "/var/log" + mcp: + type: tool + arguments: + - name: foo + type: string + description: "example arg" + required: true + + #job_$next$next1: + # command: | + # sed -i 's|^ job_| job_$next|g' process-compose.yaml + # process-compose project update -f process-compose.yaml + + create_container: + command: | + ID="$RANDOM$RANDOM" + echo "starting $ID" + echo curl --data 'log=https://localhost:8080/process/logs/create_container' -X POST https://home.org/created_container/$ID + disabled: true # run `curl https://loclahost:8080/process/start/create_container` + + glance: + command: pkg/glance + availability: + restart: on_failure # other options: "exit_on_failure", "always", "no" (default) + backoff_seconds: 2 # default: 1 + max_restarts: 5 # default: 0 (unlimited) + readiness_probe: + http_get: + host: "localhost" + port: 8081 + scheme: "http" + period_seconds: 2 + timeout_seconds: 5 + success_threshold: 1 + failure_threshold: 3 diff --git a/shell.nix b/shell.nix new file mode 100644 index 0000000..7e0e418 --- /dev/null +++ b/shell.nix @@ -0,0 +1,30 @@ +{ pkgs ? import {} } : +{ + + #pkgs = import (builtins.fetchGit { + # name = "nixos-25.05"; + # url = "https://github.com/nixos/nixpkgs"; + # rev = "11cb3517b3af6af300dd6c055aeda73c9bf52c48"; + #}) {}; + + foo = pkgs.mkShell { + # nativeBuildInputs is usually what you want -- tools you need to run + nativeBuildInputs = with pkgs.buildPackages; [ + + authbind + process-compose + docker-compose + + ]; + + shellHooks = '' + export NIX_SHELL_VPS=1 + + echo "available commands:" + + ''; + }; + + +} + diff --git a/util/wget b/util/wget new file mode 100755 index 0000000..ee36423 --- /dev/null +++ b/util/wget @@ -0,0 +1,17 @@ +#!/bin/sh +# downloads an url [+installs to path] [+checks bit-by-bit reproducability] +test -z "$1" && { echo "wget.install [sha256checksum] "; exit 0; } +set -e +test -n "$2" && url="$2" || url="$2" +file=$(basename "$url") +test -n "$OUT" || OUT="pkg" +wget -O "$file" "$url" +sha256sum "$file" +if test -n "$2"; then + echo "$1 $file" | sha256sum --check || { echo "[!] wrong checksum.."; rm $file; exit 1; } +fi +# extract +test -d $OUT || mkdir -p $OUT +mv $file $OUT/. && cd $OUT +echo $file | grep -q '\.zip' && unzip $file && rm $file +echo $file | grep -q '\.tar' && tar -xvf $file && rm $file