CHAT_OUTPUT_BEGIN
COMMAND_ID=SUPPORT-260922-HOMELAB-BACKUP-MOLDOVA-CONTROL-RCA-1123R1
STATUS=OK
RC=0
HOST=pve01
MODE=read-only
COMPONENT=homelab-backup-moldova-control-rca
REFERENCE_REGISTER_CHECK=OK
REFERENCE_SHA256=5a3d8e5154c41cb582a4e0aca68090be1f0138918bf82131a948df326f9d8d66
ERROR_REGISTER_CHECK=OK
ERROR_REGISTER_SHA256=3b09a553ec0f527ed3afeed4753f52a74ee3036045bbfb3c685e9f8af4ba7ba0
COMMAND_SHA256=0988f0ccf22795188f482b9de7d6e5bbd0042f96af78f459db72983c90a6fc99
DUPLICATE_FAILED_COMMAND_BLOCKED=false
EXECUTION_STARTED=true
CHANGE_DECLARED=false
RESULT_CONTRACT_VALID=true
RESULT_CONTRACT_STATUS=NOT_APPLICABLE
RESULT_CONTRACT_ERROR=NONE
COMMAND_RC=0
CHANGES_MADE=false
ROLLBACK_STARTED=false
ROLLBACK_RESTORED=null
MUTATION_OUTCOME=NO_MUTATION
SANITIZED=yes
SECRETS_INCLUDED=no
PRIVATE_ADDRESSES_INCLUDED=no
RAW_EVIDENCE_SHA256=e6275a6d7a9af5aa0706e1fc384f1c4cd5d89bdba7691222cc0ad8bbf480bf25
SANITIZED_OUTPUT_SHA256=e6275a6d7a9af5aa0706e1fc384f1c4cd5d89bdba7691222cc0ad8bbf480bf25
OUTPUT_BEGIN
WORKERS2_BACKUP_MOLDOVA_CONTROL_RCA_BEGIN=1
COMMAND_ID=SUPPORT-260922-HOMELAB-BACKUP-MOLDOVA-CONTROL-RCA-1123R1
MODE=read-only
COMPONENT=homelab-backup-moldova-control-rca
MUTATION_BOUNDARY=NONE;STATIC_CONTROL_PATH_CLASSIFICATION_ONLY;NO_PROVIDER_CALL;NO_NETWORK_MUTATION;NO_TARGET_SSH;NO_BACKUP;NO_SYSTEMD_ACTION;NO_GIT_WRITE;NO_SECRET_VALUE_READOUT
REFERENCE_SHA256=5a3d8e5154c41cb582a4e0aca68090be1f0138918bf82131a948df326f9d8d66
ERROR_REGISTER_SHA256=3b09a553ec0f527ed3afeed4753f52a74ee3036045bbfb3c685e9f8af4ba7ba0
RUNNER_SHA256=b248a4c32c9cc64e5747e7dce6c7fc0a23f5124a77c71ce72e27a81aceae9d2d
WRAPPER_SHA256=5077444065c732451cb84898680f62361b21a24ef9eb4f191253e82ead524ea2
AUDIT_SHA256=5777bbb204708ffcebba0753506b819833b76370ecda59b4574e1aff3b9e4593
LEGACY_SHA256=b6e79f087b9f1d21dac4f77a7b46b743299bbb85bc716e80d2ea67c2e038bcd7
SCHEDULER_RC=0
SELFTEST_REPLACEMENT486=PASS
SCHEDULER_LIVE_SELECTION={"due_seconds":86400,"enabled":true,"logical_id":"xf-newfi"}
TARGETS_CONFIG_SHA256=aa4a75455bbfe92afaf666e8d404b35c5b41e70bc014e770c9301865ee84e221
{"logical_id":"us-netbird","type":"vps_us","scope":"vps","user":"root","port":22,"enabled":true,"due_seconds":86400}
CONTROL_PATH_CLASSIFICATION_BEGIN=1
{"bytes":20163,"executable":true,"has_http":true,"has_netbird":true,"has_power_action":true,"has_provider_hint":false,"has_secret_reference":true,"has_ssh":true,"path":"/root/771r_edge_netbird_egress_capi_20260702T165517Z.sh","sha256":"9c6f911768869c984ec41016b3134be75620100fac8c60a8b21ef6bde58c6868"}
{"bytes":20006,"executable":true,"has_http":true,"has_netbird":true,"has_power_action":true,"has_provider_hint":false,"has_secret_reference":true,"has_ssh":true,"path":"/root/771s_edge_capi_netbird_20260702T170251Z.sh","sha256":"c4783c14a3a132616af5db6a065270ccd39a7690f9fd38d0ef27fe5de6bd07e5"}
{"bytes":8977,"executable":false,"has_http":true,"has_netbird":true,"has_power_action":true,"has_provider_hint":true,"has_secret_reference":true,"has_ssh":true,"path":"/root/771p_netbird_vps_peer_repair.sh","sha256":"f37aac25cac5b1c3983392070ddaff09e28497efa28884b03d23efc09a825747"}
{"bytes":6970,"executable":false,"has_http":true,"has_netbird":true,"has_power_action":false,"has_provider_hint":false,"has_secret_reference":true,"has_ssh":true,"path":"/root/771ad_final_crowdsec_capi_netbird_closure.sh","sha256":"c99d08385f5d7c0a266c1c8002b3c7b054e1bb561eb48b1f8a227f37fe430ab6"}
{"bytes":28134,"executable":false,"has_http":true,"has_netbird":true,"has_power_action":true,"has_provider_hint":false,"has_secret_reference":true,"has_ssh":true,"path":"/root/771l_crowdsec_capi_netbird_vps_egress.sh","sha256":"401396a25d4a5cfa487f67b355b45b27140ed1ac6b49b41e342306cb618dfdb5"}
{"bytes":24918,"executable":false,"has_http":true,"has_netbird":true,"has_power_action":true,"has_provider_hint":false,"has_secret_reference":true,"has_ssh":true,"path":"/root/771l_crowdsec_capi_netbird_vps_egress_remote_20260702T151045Z.sh","sha256":"6a6df3cc085363c2bbbb92b8c3083123fb0e583e14e242c583a321bdb5612002"}
{"bytes":31306,"executable":false,"has_http":true,"has_netbird":true,"has_power_action":true,"has_provider_hint":false,"has_secret_reference":true,"has_ssh":true,"path":"/root/771m_purge_warp_fix_netbird_egress.sh","sha256":"0ae3b0e1e8016da55cf1756e868c51a23fe12328fae6ef4baa61c50b9e48e715"}
{"bytes":27881,"executable":false,"has_http":true,"has_netbird":true,"has_power_action":true,"has_provider_hint":false,"has_secret_reference":true,"has_ssh":true,"path":"/root/771m_purge_warp_fix_netbird_remote_20260702T151637Z.sh","sha256":"941f683d148a01d9af9ef6ce938c8ee6874d7af1ac1ac5ee96c7d9ca7cc262a4"}
{"bytes":12586,"executable":false,"has_http":true,"has_netbird":true,"has_power_action":true,"has_provider_hint":false,"has_secret_reference":true,"has_ssh":true,"path":"/root/771n_netbird_usa_moldova_egress_only.sh","sha256":"420d835318960ae2644dafc93e0427584505acaffa9786927623aeb59ba6ac0e"}
{"bytes":10125,"executable":false,"has_http":true,"has_netbird":true,"has_power_action":true,"has_provider_hint":false,"has_secret_reference":true,"has_ssh":true,"path":"/root/771n_netbird_usa_moldova_egress_remote_20260702T152139Z.sh","sha256":"1c25cbc13f524d0f6974a71c255c5634c69380818cb1b5ad4f8f6ea9bf8c6a01"}
{"bytes":7440,"executable":false,"has_http":false,"has_netbird":true,"has_power_action":false,"has_provider_hint":false,"has_secret_reference":true,"has_ssh":true,"path":"/root/771o_netbird_management_acl_discovery.sh","sha256":"50526afeaeb99fa9a8018374abe82731dcb9e93eac4be64934d0c6a8610be322"}
{"bytes":25955,"executable":false,"has_http":true,"has_netbird":true,"has_power_action":true,"has_provider_hint":false,"has_secret_reference":true,"has_ssh":true,"path":"/root/771q_netbird_public_vps_repair_then_capi.sh","sha256":"0b6e42e5b4013f7ee2191b140c5c507877fb05e2a4fdd7b39bea7b7c6b108071"}
{"bytes":26359,"executable":false,"has_http":true,"has_netbird":true,"has_power_action":true,"has_provider_hint":false,"has_secret_reference":true,"has_ssh":true,"path":"/root/771r_netbird_public_vps_fixed_then_capi.sh","sha256":"dc8119b6815d60e08f442e77faba6ce6e9899c4120d78490886e222b8510efa7"}
{"bytes":28279,"executable":false,"has_http":true,"has_netbird":true,"has_power_action":true,"has_provider_hint":false,"has_secret_reference":true,"has_ssh":true,"path":"/root/771s_vps_identity_repair_netbird_capi.sh","sha256":"16121a810320b1517291830ba128baf6c68e7b3e6f78786481dedb78a1f061b9"}
{"bytes":25344,"executable":false,"has_http":true,"has_netbird":true,"has_power_action":true,"has_provider_hint":false,"has_secret_reference":true,"has_ssh":true,"path":"/root/771t_temp_hostkey_netbird_identity_then_capi.sh","sha256":"0c3d628b23b67849d52112322ab2e1ee3779012c10578a0b8cece0d8ddf639da"}
{"bytes":27834,"executable":false,"has_http":true,"has_netbird":true,"has_power_action":true,"has_provider_hint":false,"has_secret_reference":true,"has_ssh":true,"path":"/root/771u_find_key_fix_netbird_egress_capi.sh","sha256":"6b6511ec3d614793e3542777ccfcb5e8c5f09cff77ee2d57624b3ac980787bcb"}
{"bytes":30154,"executable":false,"has_http":true,"has_netbird":true,"has_power_action":true,"has_provider_hint":false,"has_secret_reference":true,"has_ssh":true,"path":"/root/771v_deep_key_backup_netbird_capi.sh","sha256":"92191ce6124981ee0468cc8f95c749c47bca5fc61f9aecaeedeef91cdd434170"}
{"bytes":13072,"executable":false,"has_http":true,"has_netbird":true,"has_power_action":true,"has_provider_hint":false,"has_secret_reference":true,"has_ssh":true,"path":"/root/771z_after_manual_netbird_egress_capi.sh","sha256":"f198ed621fd726ed6f15c4a0dd49fad307befd01e7a58ebbda1ddc379f5b49ee"}
{"bytes":9197,"executable":false,"has_http":true,"has_netbird":true,"has_power_action":true,"has_provider_hint":true,"has_secret_reference":true,"has_ssh":true,"path":"/srv/homelab-ops/kb/private/archive/2026-08-19/docs/01_CURRENT_AUTHORITATIVE_STATE.md","sha256":"844a17f9af701211699b078f5a5e8ff28bb401b377acc10fe364aa78aa3bfc9b"}
{"bytes":38895,"executable":false,"has_http":false,"has_netbird":true,"has_power_action":true,"has_provider_hint":true,"has_secret_reference":true,"has_ssh":false,"path":"/srv/homelab-ops/.git/index","sha256":"93bd029aaadbac051ea3e9c7266ae0d0643ec8d0eff24a02ccb44805dc9764d2"}
{"bytes":38895,"executable":false,"has_http":false,"has_netbird":true,"has_power_action":true,"has_provider_hint":true,"has_secret_reference":true,"has_ssh":false,"path":"/srv/homelab-ops/.git/worktrees/homelab-ops-cr-2026-0095/index","sha256":"6327b174188ff5b751c03ba3e6b14d884a1d61dda42df86d8cf2e2151d74efe1"}
{"bytes":53159,"executable":false,"has_http":false,"has_netbird":true,"has_power_action":true,"has_provider_hint":true,"has_secret_reference":true,"has_ssh":false,"path":"/srv/homelab-ops/.git/worktrees/homelab-ops-cr-2026-0096/index","sha256":"0f244e69df78feba15d92d1c45c7d456e62726609ff45a6000cc5f11cc6b8e64"}
{"bytes":75082,"executable":false,"has_http":false,"has_netbird":true,"has_power_action":true,"has_provider_hint":true,"has_secret_reference":true,"has_ssh":false,"path":"/srv/homelab-ops/.git/worktrees/homelab-ops-cr-2026-1005/index","sha256":"d7c61f503b6b7494e9aa4dde883d5a42493d81c346ba30938fe86386002dc388"}
{"bytes":31037,"executable":false,"has_http":true,"has_netbird":false,"has_power_action":true,"has_provider_hint":false,"has_secret_reference":true,"has_ssh":true,"path":"/srv/homelab-ops/docs/superpowers/plans/2026-08-18-gitea-edge-publisher-v3.md","sha256":"f42b0e0be98c7f6d9f0e06d5565ec1cfc277e4221cbc164f21c157fe4121ad72"}
{"bytes":3587,"executable":false,"has_http":true,"has_netbird":true,"has_power_action":false,"has_provider_hint":false,"has_secret_reference":true,"has_ssh":true,"path":"/srv/homelab-ops/kb/AI_CONTEXT.md","sha256":"5fc43e34a1f0714ddacf7c00ed5c4bbaf788df3b8407dcfebd1333a23a623acc"}
{"bytes":1322,"executable":false,"has_http":false,"has_netbird":false,"has_power_action":false,"has_provider_hint":false,"has_secret_reference":true,"has_ssh":false,"path":"/srv/homelab-ops/kb/current/03_ACCESS_AND_SECRETS.md","sha256":"e750284217dc41b5809268a0bbc54ed0948bdd14680fe2f282f307640937496c"}
{"bytes":805,"executable":false,"has_http":false,"has_netbird":true,"has_power_action":true,"has_provider_hint":false,"has_secret_reference":true,"has_ssh":true,"path":"/srv/homelab-ops/kb/current/04_P0_NEXT.md","sha256":"0f6eb8b23382becc1868e8a22318d5b7629184568205bad47c3c38967a346b8f"}
{"bytes":3063,"executable":false,"has_http":false,"has_netbird":true,"has_power_action":true,"has_provider_hint":true,"has_secret_reference":true,"has_ssh":false,"path":"/srv/homelab-ops/kb/private/archive/2026-08-19/README_FIRST.md","sha256":"02f7db5a75d4371a430a0034dc3e74a61ea355064fe44a1a221e8e175422a008"}
{"bytes":33401,"executable":false,"has_http":false,"has_netbird":true,"has_power_action":false,"has_provider_hint":true,"has_secret_reference":false,"has_ssh":false,"path":"/srv/homelab-ops/kb/private/archive/2026-08-19/SHA256SUMS","sha256":"0939f8b9ab4de481c6e68a6abd16cb14ae5348a94e3af0d0e3f107815d0d3169"}
{"bytes":2726,"executable":false,"has_http":false,"has_netbird":true,"has_power_action":true,"has_provider_hint":true,"has_secret_reference":true,"has_ssh":true,"path":"/srv/homelab-ops/kb/private/archive/2026-08-19/docs/00_START_HERE.md","sha256":"4c4e4c85805aa00bd5f94f64fc9c2c985c44bf467058546e3cbe9d8d166d044f"}
{"bytes":3259,"executable":false,"has_http":true,"has_netbird":true,"has_power_action":false,"has_provider_hint":false,"has_secret_reference":true,"has_ssh":true,"path":"/srv/homelab-ops/kb/private/archive/2026-08-19/docs/04_NETWORK_DNS_INGRESS.md","sha256":"e3edd29ea8754ce340929f531c0ff8c1ebda4fbbf7d20a53445a665e014fbc85"}
{"bytes":3828,"executable":false,"has_http":false,"has_netbird":true,"has_power_action":true,"has_provider_hint":true,"has_secret_reference":true,"has_ssh":true,"path":"/srv/homelab-ops/kb/private/archive/2026-08-19/docs/11_OPEN_ISSUES_AND_FUTURE_WORK.md","sha256":"8621c33341c93f6104e58821daeda1e534353290c685a273620b884014ddd647"}
{"bytes":2056,"executable":false,"has_http":false,"has_netbird":true,"has_power_action":true,"has_provider_hint":true,"has_secret_reference":false,"has_ssh":false,"path":"/srv/homelab-ops/kb/private/archive/2026-08-19/docs/12_NEW_CHAT_FIRST_MESSAGE.txt","sha256":"380315d5793449c258356145e7cff7dee7493d2c462dff3ca6f6d9eabfb673e0"}
{"bytes":1744,"executable":false,"has_http":false,"has_netbird":true,"has_power_action":false,"has_provider_hint":true,"has_secret_reference":false,"has_ssh":false,"path":"/srv/homelab-ops/kb/private/archive/2026-08-19/docs/13_PROVENANCE_AND_FRESHNESS.md","sha256":"804a09f8ae5fe307c3fb96243246ef4817bb98695068a80f181978933ee70089"}
{"bytes":1740,"executable":false,"has_http":false,"has_netbird":true,"has_power_action":false,"has_provider_hint":false,"has_secret_reference":true,"has_ssh":false,"path":"/srv/homelab-ops/kb/private/archive/2026-08-19/docs/15_CRITICAL_KEEP_RETIRE_DECISIONS.md","sha256":"ad3ea70345063e8a13608a83acb4d6a1118533eb6acab22929e0bf1ac20c06af"}
{"bytes":3638,"executable":false,"has_http":false,"has_netbird":true,"has_power_action":true,"has_provider_hint":true,"has_secret_reference":true,"has_ssh":true,"path":"/srv/homelab-ops/kb/private/archive/2026-08-19/docs/18_P0_CLOSEOUT_MASTER_PLAN_2026-08-19.md","sha256":"0ce52a34278e57ff3dba122e2e65c57251e75484025ba13588971d0979d78ec6"}
{"bytes":1792,"executable":false,"has_http":false,"has_netbird":true,"has_power_action":false,"has_provider_hint":true,"has_secret_reference":false,"has_ssh":false,"path":"/srv/homelab-ops/kb/private/archive/2026-08-19/docs/20_NETBIRD_USA_MIGRATION_2026-08-18.md","sha256":"12fe079849346352315aac76fae82d00cbd17f88a3553270ca2c5f2749840552"}
{"bytes":2265,"executable":false,"has_http":true,"has_netbird":true,"has_power_action":false,"has_provider_hint":false,"has_secret_reference":true,"has_ssh":false,"path":"/srv/homelab-ops/kb/private/archive/2026-08-19/docs/22_MOLDOVA_HEALTHCHECK_GOTIFY_2026-08-18.md","sha256":"fe0f5ca63837626583d150e8c4b9ce9c795832ae4f59af25369a00fa7825fdb5"}
{"bytes":3828,"executable":false,"has_http":false,"has_netbird":true,"has_power_action":true,"has_provider_hint":true,"has_secret_reference":true,"has_ssh":true,"path":"/srv/homelab-ops/kb/private/archive/2026-08-19/docs/24_GLOBAL_BACKLOG_MASTER_2026-08-19.md","sha256":"8621c33341c93f6104e58821daeda1e534353290c685a273620b884014ddd647"}
{"bytes":1733,"executable":false,"has_http":false,"has_netbird":false,"has_power_action":true,"has_provider_hint":false,"has_secret_reference":true,"has_ssh":true,"path":"/srv/homelab-ops/kb/private/archive/2026-08-19/docs/25_OPERATOR_CHAT_RULES_2026-08-19.md","sha256":"69bec1f0893c32c2ea67100355f8702f20bb6671177c6c1da69e1d2407c71232"}
{"bytes":1744,"executable":false,"has_http":false,"has_netbird":true,"has_power_action":false,"has_provider_hint":true,"has_secret_reference":false,"has_ssh":false,"path":"/srv/homelab-ops/kb/private/archive/2026-08-19/docs/28_PROVENANCE_AND_FRESHNESS_2026-08-19.md","sha256":"804a09f8ae5fe307c3fb96243246ef4817bb98695068a80f181978933ee70089"}
{"bytes":700,"executable":false,"has_http":false,"has_netbird":true,"has_power_action":false,"has_provider_hint":false,"has_secret_reference":true,"has_ssh":true,"path":"/srv/homelab-ops/kb/runbooks/04_NETBIRD_USA.md","sha256":"725e2068337b379ebdf47822d5871aa5f4d5ec5956546674b2cf55b3250fb7a3"}
{"bytes":4057,"executable":false,"has_http":false,"has_netbird":true,"has_power_action":true,"has_provider_hint":false,"has_secret_reference":true,"has_ssh":true,"path":"/srv/homelab-ops/kb/scripts/command_guard.py","sha256":"33c59d92a2b9c380d9208a0e2fd1353029e6edc4878053df95dbd7b9dd987d0b"}
CONTROL_PATH_CLASSIFICATION_END=1
CONTROL_TOTAL_ROWS=43
CONTROL_EXEC_ROWS=2
CONTROL_EXTERNAL_PROVIDER_ACTION_CANDIDATES=0
CONTROL_SSH_DEPENDENT_CANDIDATES=2
CONTROL_NETBIRD_ONLY_CANDIDATES=0
KNOWN_771_SAFE_STATIC_BEGIN=1
KNOWN_SCRIPT=/root/771n_netbird_usa_moldova_egress_only.sh SHA256=420d835318960ae2644dafc93e0427584505acaffa9786927623aeb59ba6ac0e EXECUTABLE=false
20:EGRESS_DIR=/etc/homelab-crowdsec-capi-netbird-egress
22:HEALTH_FILE="$HEALTH_DIR/crowdsec-capi.txt"
41:    echo "CHECK=crowdsec-capi"
53:      DISABLE_ONLINE_API: "true"
54:      ARGS: "-no-capi"
93:  cat >/etc/systemd/system/homelab-crowdsec-capi-netbird-egress.service <<'EOF'
95:Description=Homelab CrowdSec CAPI NetBird VPS SOCKS egress
102:EnvironmentFile=/etc/homelab-crowdsec-capi-netbird-egress/current.env
103:ExecStart=/bin/sh -lc 'exec /usr/bin/ssh -N -D "${SOCKS_BIND}:${SOCKS_PORT}" -o BatchMode=yes -o ExitOnForwardFailure=yes -o ServerAliveInterval=30 -o ServerAliveCountMax=3 -o StrictHostKeyChecking=accept-new "${SSH_USER}@${SSH_HOST}"'
104:Restart=always
105:RestartSec=5
111:  cat >/usr/local/sbin/homelab-crowdsec-capi-egress-switch <<'EOF'
115:base=/etc/homelab-crowdsec-capi-netbird-egress
123:systemctl restart homelab-crowdsec-capi-netbird-egress.service
124:systemctl restart privoxy 2>/dev/null || true
126:systemctl --no-pager --full status homelab-crowdsec-capi-netbird-egress.service | sed -n '1,30p'
128:  chmod 755 /usr/local/sbin/homelab-crowdsec-capi-egress-switch
131:  systemctl enable --now homelab-crowdsec-capi-netbird-egress.service
132:  systemctl restart homelab-crowdsec-capi-netbird-egress.service
134:  systemctl is-active homelab-crowdsec-capi-netbird-egress.service || true
146:    if "HOMELAB_771" in line and "CROWDSEC_CAPI" in line and "BEGIN" in line:
149:    if "HOMELAB_771" in line and "CROWDSEC_CAPI" in line and "END" in line:
160:out.append("# HOMELAB_771N_CROWDSEC_CAPI_NETBIRD_BEGIN")
163:out.append("# HOMELAB_771N_CROWDSEC_CAPI_NETBIRD_END")
168:    systemctl restart privoxy
189:    if timeout 12 ssh -n -o BatchMode=yes -o ConnectTimeout=7 -o StrictHostKeyChecking=accept-new "$user@$ip" "echo SSH_OK; hostname; uname -a | cut -c1-120" 2>&1 | redact; then
192:      if ssh -n -fN -M -S "$ctl" -o BatchMode=yes -o ConnectTimeout=8 -o ExitOnForwardFailure=yes -o ServerAliveInterval=30 -o ServerAliveCountMax=3 -o StrictHostKeyChecking=accept-new -D "[PRIVATE_IP]:${port}" "$user@$ip" 2>/tmp/771n_tunnel_${profile}.err; then
194:        code="$(curl -sk --proxy "socks5h://[PRIVATE_IP]:${port}" --connect-timeout 12 --max-time 45 -o /tmp/771n_capi_${profile}.body -w '%{http_code}' https://api.crowdsec.net/v3/watchers/login || true)"
195:        trace="$(curl -sk --proxy "socks5h://[PRIVATE_IP]:${port}" --connect-timeout 12 --max-time 45 https://www.cloudflare.com/cdn-cgi/trace 2>/dev/null | grep -E 'ip=|colo=' | sed -n '1,5p' || true)"
196:        echo "SOCKS_CAPI_HTTP=$code"
200:        ssh -S "$ctl" -O exit "$user@$ip" >/dev/null 2>&1 || true
232:docker exec crowdsec cscli lapi status 2>&1 | redact || true
233:docker exec crowdsec cscli capi status 2>&1 | redact || true
236:netbird status 2>&1 | redact || true
239:systemctl restart netbird 2>/dev/null || true
241:netbird status 2>&1 | redact || true
244:USA_IP="$(awk '$1 ~ /^e3qxxx\.netbird\.selfhosted$/ {print $2}' < <(netbird status 2>/dev/null || true) | head -1)"
245:MOLDOVA_IP="$(awk '$1 ~ /^e3qxxx-183-106\.netbird\.selfhosted$/ {print $2}' < <(netbird status 2>/dev/null || true) | head -1)"
261:  write_health "REVIEW_USA_MOLDOVA_NETBIRD_PEERS_NOT_REACHABLE" "WARP purged; USA/Moldova NetBird VPS peers are not reachable or do not allow SSH from edge"
262:  echo "NEEDED_ON_VPS=NetBird peer online, SSH reachable over NetBird, and outbound TLS to api.crowdsec.net working"
276:proxy_code="$(curl -sk --proxy "http://${b}:${HTTP_PROXY_PORT}" --connect-timeout 12 --max-time 45 -o /tmp/771n_active_proxy.body -w '%{http_code}' https://api.crowdsec.net/v3/watchers/login || true)"
277:echo "ACTIVE_HTTP_PROXY_CAPI_HTTP=$proxy_code"
280:  write_health "REVIEW_NETBIRD_EGRESS_PROXY_FAILED" "NetBird VPS SSH SOCKS profile exists but HTTP proxy did not reach CrowdSec CAPI"
286:write_health "OK_NETBIRD_EGRESS_PROFILE_READY_CAPI_REGISTRATION_NEXT" "NetBird VPS egress profile=$profile is ready; next command can register CrowdSec CAPI through proxy http://${b}:${HTTP_PROXY_PORT}"
287:echo "READY_PROXY=http://${b}:${HTTP_PROXY_PORT}"
288:echo "READY_SWITCH=homelab-crowdsec-capi-egress-switch $profile"
290:echo "REMOTE_STATUS=OK_NETBIRD_EGRESS_PROFILE_READY_CAPI_REGISTRATION_NEXT"
306:  scp -q "$LOCAL_REMOTE_SCRIPT" "debian@$EDGE:$REMOTE_SCRIPT"
315:  ssh "debian@$EDGE" "sudo bash '$REMOTE_SCRIPT' '$TS'"
KNOWN_SCRIPT=/root/771o_netbird_management_acl_discovery.sh SHA256=50526afeaeb99fa9a8018374abe82731dcb9e93eac4be64934d0c6a8610be322 EXECUTABLE=false
25:  ssh debian@$EDGE "sudo bash -lc '
35:    netbird status --json >/tmp/771o_netbird_status.json 2>/tmp/771o_netbird_status_json.err || true
109:      ssh -o BatchMode=yes -o ConnectTimeout=8 "$user@$host" "sudo bash -lc '
KNOWN_SCRIPT=/root/771p_netbird_vps_peer_repair.sh SHA256=f37aac25cac5b1c3983392070ddaff09e28497efa28884b03d23efc09a825747 EXECUTABLE=false
19:  echo "RULE=NO_WARP_FIX_NETBIRD_USA_MOLDOVA_PEERS_FOR_CROWDSEC_CAPI"
23:  echo "CONFIG_CHANGE=YES_RESTART_NETBIRD_ON_VPS_IF_PUBLIC_SSH_FOUND"
36:  ssh debian@$EDGE "sudo bash -lc '
46:    netbird status --json >/tmp/771p_edge_nb.json 2>/tmp/771p_edge_nb.err || true
80:    grep -nEi 'e3qxxx|183-106|moldova|молдов|usa|america|vps|netbird|alexhost|aeza|hetzner|public ip|external ip|ssh' /etc/pve/31_HOMELAB_REFERENCE.md 2>/dev/null | sed -n '1,260p' || true
138:  echo "TEST_PUBLIC_SSH_AND_RESTART_NETBIRD_ON_VPS_IF_FOUND"
158:  ssh debian@$EDGE "sudo bash -lc '
159:    systemctl restart netbird 2>/dev/null || true
174:  ssh debian@$EDGE "sudo bash -lc '
182:    echo "STATUS=OK_771P_VPS_PUBLIC_ACCESS_FOUND_RESTARTED_NETBIRD_REVIEW_RECHECK"
KNOWN_SCRIPT=/root/771q_netbird_public_vps_repair_then_capi.sh SHA256=0b6e42e5b4013f7ee2191b140c5c507877fb05e2a4fdd7b39bea7b7c6b108071 EXECUTABLE=false
8:PROOF="/root/evidence/771Q_NETBIRD_PUBLIC_VPS_REPAIR_THEN_CAPI_${TS}_PROOF.txt"
16:  echo "STEP=771Q_NETBIRD_PUBLIC_VPS_REPAIR_THEN_CAPI"
19:  echo "RULE=NO_WARP_REPAIR_NETBIRD_USA_MOLDOVA_THEN_CROWDSEC_CAPI"
23:  echo "CONFIG_CHANGE=YES_RESTART_PUBLIC_VPS_NETBIRD_AND_CAPI_IF_ROUTE_READY"
33:    if timeout 18 ssh -n \
38:      "echo SSH_OK; echo HOSTNAME=\$(hostname); command -v netbird >/dev/null 2>&1 && netbird status 2>&1 || echo NETBIRD_CLI_MISSING; curl -4 -sk --connect-timeout 8 --max-time 20 -o /tmp/771q_capi.body -w 'DIRECT_CAPI_HTTP=%{http_code}\n' https://api.crowdsec.net/v3/watchers/login || true" \
53:  ssh debian@$EDGE "sudo bash -lc 'command -v warp-cli >/dev/null 2>&1 && echo WARP_CLI_STILL_PRESENT || echo WARP_CLI_ABSENT=YES; dpkg -l 2>/dev/null | grep -E \"^ii[[:space:]]+cloudflare-warp\" || echo CLOUDFLARE_WARP_PACKAGE_ABSENT=YES; ss -ltnp | grep -E \":(40000|40001)\\b\" || echo WARP_PROXY_PORTS_ABSENT=YES'"
74:  echo "RESTART_NETBIRD_ON_REAL_PUBLIC_VPS_ONLY"
75:  : >/tmp/771q_restarted.tsv
80:        echo "RESTART_ATTEMPT profile=$profile user=$user host=$host"
81:        out="/tmp/771q_restart_${profile}_${user}_$(echo "$host" | tr -c A-Za-z0-9 _).out"
82:        if timeout 45 ssh -n \
87:          "echo BEFORE_HOSTNAME=\$(hostname); command -v netbird >/dev/null 2>&1 && netbird status 2>&1 || true; (sudo systemctl restart netbird 2>/dev/null || systemctl restart netbird 2>/dev/null || true); sleep 15; echo AFTER; command -v netbird >/dev/null 2>&1 && netbird status 2>&1 || true; curl -4 -sk --connect-timeout 8 --max-time 20 -o /tmp/771q_capi_after.body -w 'DIRECT_CAPI_HTTP_AFTER=%{http_code}\n' https://api.crowdsec.net/v3/watchers/login || true" \
91:          printf '%s\t%s\t%s\n' "$profile" "$user" "$host" >>/tmp/771q_restarted.tsv
94:          echo "RESTART_FAILED profile=$profile user=$user host=$host"
103:  echo "PUBLIC_VPS_RESTARTED"
104:  cat /tmp/771q_restarted.tsv || true
106:  echo "RECHECK_EDGE_USA_MOLDOVA_AFTER_PUBLIC_RESTART"
107:  ssh debian@$EDGE "sudo bash -lc '
109:    systemctl restart netbird 2>/dev/null || true
112:    netbird status --json >/tmp/771q_edge_nb.json 2>/tmp/771q_edge_nb.err || true
139:  echo "EDGE_BUILD_NETBIRD_EGRESS_AND_REGISTER_CAPI_IF_REACHABLE"
140:  ssh debian@$EDGE "sudo bash -s" <<'EDGE_SCRIPT'
146:EGRESS_DIR=/etc/homelab-crowdsec-capi-netbird-egress
148:HEALTH_FILE="$HEALTH_DIR/crowdsec-capi.txt"
167:    echo "CHECK=crowdsec-capi"
173:force_no_capi_stable() {
179:      DISABLE_ONLINE_API: "true"
180:      ARGS: "-no-capi"
201:wait_lapi() {
203:  echo "WAIT_LAPI=$label"
206:    health="$(curl -sk --connect-timeout 3 --max-time 6 -o /tmp/771q_health.html -w '%{http_code}' http://[PRIVATE_IP]:8088/health || true)"
208:    rc="$(printf '%s\n' "$out" | awk -F= '/^LAPI_RC=/{print $2}' | tail -1)"
209:    echo "LAPI_TRY=$n HEALTH=$health LAPI_RC=${rc:-NA}"
271:    raise SystemExit("api.server block not found")
274:    "      credentials_path: /etc/crowdsec/online_api_credentials.yaml",
310:  grep -nE 'DISABLE_ONLINE_API|ARGS|GODEBUG|HTTP_PROXY|HTTPS_PROXY|NO_PROXY|socket-proxy|published:|target:' /tmp/771q_compose.yml || true
311:  ! grep -qE 'DISABLE_ONLINE_API|ARGS:.*no-capi|-no-capi' /tmp/771q_compose.yml
321:    if timeout 12 ssh -n -o BatchMode=yes -o ConnectTimeout=7 -o StrictHostKeyChecking=accept-new "$user@$ip" "echo SSH_OK; hostname; curl -4 -sk --connect-timeout 8 --max-time 20 -o /tmp/771q_capi.body -w 'DIRECT_CAPI_HTTP=%{http_code}\n' https://api.crowdsec.net/v3/watchers/login || true" 2>&1 | redact; then
324:      if ssh -n -fN -M -S "$ctl" -o BatchMode=yes -o ConnectTimeout=8 -o ExitOnForwardFailure=yes -o ServerAliveInterval=30 -o ServerAliveCountMax=3 -o StrictHostKeyChecking=accept-new -D "[PRIVATE_IP]:${port}" "$user@$ip" 2>/tmp/771q_tunnel.err; then
326:        code="$(curl -sk --proxy "socks5h://[PRIVATE_IP]:${port}" --connect-timeout 12 --max-time 45 -o /tmp/771q_capi_proxy.body -w '%{http_code}' https://api.crowdsec.net/v3/watchers/login || true)"
327:        trace="$(curl -sk --proxy "socks5h://[PRIVATE_IP]:${port}" --connect-timeout 12 --max-time 45 https://www.cloudflare.com/cdn-cgi/trace 2>/dev/null | grep -E 'ip=|colo=' | sed -n '1,5p' || true)"
328:        echo "SOCKS_CAPI_HTTP=$code"
332:        ssh -S "$ctl" -O exit "$user@$ip" >/dev/null 2>&1 || true
360:  cat >/etc/systemd/system/homelab-crowdsec-capi-netbird-egress.service <<'EOF'
362:Description=Homelab CrowdSec CAPI NetBird VPS SOCKS egress
369:EnvironmentFile=/etc/homelab-crowdsec-capi-netbird-egress/current.env
370:ExecStart=/bin/sh -lc 'exec /usr/bin/ssh -N -D "${SOCKS_BIND}:${SOCKS_PORT}" -o BatchMode=yes -o ExitOnForwardFailure=yes -o ServerAliveInterval=30 -o ServerAliveCountMax=3 -o StrictHostKeyChecking=accept-new "${SSH_USER}@${SSH_HOST}"'
371:Restart=always
372:RestartSec=5
378:  cat >/usr/local/sbin/homelab-crowdsec-capi-egress-switch <<'EOF'
382:base=/etc/homelab-crowdsec-capi-netbird-egress
390:systemctl restart homelab-crowdsec-capi-netbird-egress.service
391:systemctl restart privoxy 2>/dev/null || true
393:systemctl --no-pager --full status homelab-crowdsec-capi-netbird-egress.service | sed -n '1,30p'
395:  chmod 755 /usr/local/sbin/homelab-crowdsec-capi-egress-switch
398:  systemctl enable --now homelab-crowdsec-capi-netbird-egress.service
399:  systemctl restart homelab-crowdsec-capi-netbird-egress.service
401:  systemctl is-active homelab-crowdsec-capi-netbird-egress.service || true
415:    if "HOMELAB_771" in line and "CROWDSEC_CAPI" in line and "BEGIN" in line:
417:    if "HOMELAB_771" in line and "CROWDSEC_CAPI" in line and "END" in line:
427:out.append("# HOMELAB_771Q_CROWDSEC_CAPI_NETBIRD_BEGIN")
430:out.append("# HOMELAB_771Q_CROWDSEC_CAPI_NETBIRD_END")
435:  systemctl restart privoxy
440:  code="$(curl -sk --proxy "http://${b}:${HTTP_PROXY_PORT}" --connect-timeout 12 --max-time 45 -o /tmp/771q_http_proxy_capi.body -w '%{http_code}' https://api.crowdsec.net/v3/watchers/login || true)"
441:  echo "HTTP_PROXY_CAPI_HTTP=$code"
445:register_capi() {
447:  proxy_url="http://${b}:${HTTP_PROXY_PORT}"
448:  echo "REGISTER_CAPI proxy=$proxy_url"
450:  force_no_capi_stable
451:  wait_lapi "BEFORE_CAPI_REGISTER" || return 10
455:  if test -f config/online_api_credentials.yaml; then
456:    mkdir -p /opt/stacks/crowdsec/manual-backups/771q-old-online-creds-"$TS"
457:    mv config/online_api_credentials.yaml /opt/stacks/crowdsec/manual-backups/771q-old-online-creds-"$TS"/online_api_credentials.yaml.before-register
462:  wait_lapi "REGISTER_MODE" || return 13
467:    if cscli capi register --help 2>&1 | grep -q -- "-y"; then
468:      timeout 240 cscli capi register -y >/tmp/771q_register.out 2>&1
470:      timeout 240 sh -c "yes | cscli capi register" >/tmp/771q_register.out 2>&1
483:  if ! test -f config/online_api_credentials.yaml; then
487:  stat -c 'ONLINE_CREDS path=%n mode=%a owner=%U group=%G size=%s' config/online_api_credentials.yaml || true
KNOWN_SCRIPT=/root/771r_edge_netbird_egress_capi_20260702T165517Z.sh SHA256=9c6f911768869c984ec41016b3134be75620100fac8c60a8b21ef6bde58c6868 EXECUTABLE=true
7:EGRESS_DIR=/etc/homelab-crowdsec-capi-netbird-egress
9:HEALTH_FILE="$HEALTH_DIR/crowdsec-capi.txt"
29:    echo "CHECK=crowdsec-capi"
35:force_no_capi_stable() {
41:      DISABLE_ONLINE_API: "true"
42:      ARGS: "-no-capi"
65:wait_lapi() {
68:  echo "WAIT_LAPI=$label"
71:    health="$(curl -sk --connect-timeout 3 --max-time 6 -o /tmp/771r_health.html -w '%{http_code}' http://[PRIVATE_IP]:8088/health || true)"
73:    rc="$(printf '%s\n' "$out" | awk -F= '/^LAPI_RC=/{print $2}' | tail -1)"
74:    fatal="$(docker logs --since 30s crowdsec 2>&1 | grep -Eic 'fatal|unable to run local API|failed to get docker info|lookup socket-proxy|server misbehaving|mapping value is not allowed' || true)"
75:    echo "LAPI_TRY=$n HEALTH=$health LAPI_RC=${rc:-NA} FATAL_COUNT_30S=$fatal"
149:    raise SystemExit("api.server block not found")
153:    "      credentials_path: /etc/crowdsec/online_api_credentials.yaml",
192:  grep -nE 'DISABLE_ONLINE_API|ARGS|GODEBUG|HTTP_PROXY|HTTPS_PROXY|NO_PROXY|socket-proxy|published:|target:' /tmp/771r_compose.yml || true
193:  ! grep -qE 'DISABLE_ONLINE_API|ARGS:.*no-capi|-no-capi' /tmp/771r_compose.yml
207:    timeout 12 ssh -n \
212:      "echo SSH_OK; hostname; curl -4 -sk --connect-timeout 8 --max-time 20 -o /tmp/771r_capi.body -w 'DIRECT_CAPI_HTTP=%{http_code}\n' https://api.crowdsec.net/v3/watchers/login || true" \
224:    if ssh -n -fN -M -S "$ctl" \
234:      code="$(curl -sk --proxy "socks5h://[PRIVATE_IP]:${port}" --connect-timeout 12 --max-time 45 -o /tmp/771r_capi_proxy.body -w '%{http_code}' https://api.crowdsec.net/v3/watchers/login || true)"
235:      trace="$(curl -sk --proxy "socks5h://[PRIVATE_IP]:${port}" --connect-timeout 12 --max-time 45 https://www.cloudflare.com/cdn-cgi/trace 2>/dev/null | grep -E 'ip=|colo=' | sed -n '1,5p' || true)"
236:      echo "SOCKS_CAPI_HTTP=$code"
240:      ssh -S "$ctl" -O exit "$user@$ip" >/dev/null 2>&1 || true
273:  cat >/etc/systemd/system/homelab-crowdsec-capi-netbird-egress.service <<'EOF'
275:Description=Homelab CrowdSec CAPI NetBird VPS SOCKS egress
282:EnvironmentFile=/etc/homelab-crowdsec-capi-netbird-egress/current.env
283:ExecStart=/bin/sh -lc 'exec /usr/bin/ssh -N -D "${SOCKS_BIND}:${SOCKS_PORT}" -o BatchMode=yes -o ExitOnForwardFailure=yes -o ServerAliveInterval=30 -o ServerAliveCountMax=3 -o StrictHostKeyChecking=accept-new "${SSH_USER}@${SSH_HOST}"'
284:Restart=always
285:RestartSec=5
291:  cat >/usr/local/sbin/homelab-crowdsec-capi-egress-switch <<'EOF'
295:base=/etc/homelab-crowdsec-capi-netbird-egress
303:systemctl restart homelab-crowdsec-capi-netbird-egress.service
304:systemctl restart privoxy 2>/dev/null || true
306:systemctl --no-pager --full status homelab-crowdsec-capi-netbird-egress.service | sed -n '1,30p'
308:  chmod 755 /usr/local/sbin/homelab-crowdsec-capi-egress-switch
311:  systemctl enable --now homelab-crowdsec-capi-netbird-egress.service
312:  systemctl restart homelab-crowdsec-capi-netbird-egress.service
314:  systemctl is-active homelab-crowdsec-capi-netbird-egress.service || true
328:    if "HOMELAB_771" in line and "CROWDSEC_CAPI" in line and "BEGIN" in line:
330:    if "HOMELAB_771" in line and "CROWDSEC_CAPI" in line and "END" in line:
340:out.append("# HOMELAB_771R_CROWDSEC_CAPI_NETBIRD_BEGIN")
343:out.append("# HOMELAB_771R_CROWDSEC_CAPI_NETBIRD_END")
348:  systemctl restart privoxy
353:  code="$(curl -sk --proxy "http://${b}:${HTTP_PROXY_PORT}" --connect-timeout 12 --max-time 45 -o /tmp/771r_http_proxy_capi.body -w '%{http_code}' https://api.crowdsec.net/v3/watchers/login || true)"
354:  echo "HTTP_PROXY_CAPI_HTTP=$code"
358:register_capi() {
359:  local b proxy_url reg_out reg_rc ready n health lapi_rc capi_out capi_rc fatal envbad rc_before rc_after health_after lapi_after capi_after fatal_after env_after
361:  proxy_url="http://${b}:${HTTP_PROXY_PORT}"
362:  echo "REGISTER_CAPI proxy=$proxy_url"
364:  force_no_capi_stable
365:  wait_lapi "BEFORE_CAPI_REGISTER" || return 10
369:  if test -f config/online_api_credentials.yaml; then
370:    mkdir -p /opt/stacks/crowdsec/manual-backups/771r-old-online-creds-"$TS"
371:    mv config/online_api_credentials.yaml /opt/stacks/crowdsec/manual-backups/771r-old-online-creds-"$TS"/online_api_credentials.yaml.before-register
376:  wait_lapi "REGISTER_MODE" || return 13
381:    if cscli capi register --help 2>&1 | grep -q -- "-y"; then
382:      timeout 240 cscli capi register -y >/tmp/771r_register.out 2>&1
384:      timeout 240 sh -c "yes | cscli capi register" >/tmp/771r_register.out 2>&1
397:  if ! test -f config/online_api_credentials.yaml; then
401:  stat -c 'ONLINE_CREDS path=%n mode=%a owner=%U group=%G size=%s' config/online_api_credentials.yaml || true
402:  awk -F: '/^[A-Za-z0-9_ -]+:/ {gsub(/^[ \t]+|[ \t]+$/, "", $1); print $1 ": REDACTED"}' config/online_api_credentials.yaml | sed -n '1,40p'
404:  grep -Eq '^[[:space:]]*login:' config/online_api_credentials.yaml || return 22
411:  echo "VALIDATE_CAPI"
415:    health="$(curl -sk --connect-timeout 3 --max-time 6 -o /tmp/771r_health2.html -w '%{http_code}' http://[PRIVATE_IP]:8088/health || true)"
416:    lapi_rc="$(docker exec crowdsec sh -lc 'cscli lapi status >/tmp/771r_lapi2.out 2>&1; echo LAPI_RC=$?' 2>/dev/null | awk -F= '/^LAPI_RC=/{print $2}' | tail -1 || true)"
418:    capi_rc="$(printf '%s\n' "$capi_out" | awk -F= '/^CAPI_RC=/{print $2}' | tail -1)"
419:    fatal="$(docker logs --since 60s crowdsec 2>&1 | grep -Eic 'fatal|TLS handshake timeout|unable to run local API|failed to get docker info|lookup socket-proxy|server misbehaving|mapping value is not allowed|missing credentials field|open /etc/crowdsec/online_api_credentials.yaml|proxyconnect tcp' || true)"
420:    envbad="$(docker inspect crowdsec --format '{{range .Config.Env}}{{println .}}{{end}}' 2>/dev/null | grep -E 'DISABLE_ONLINE_API|ARGS=.*no-capi|-no-capi' || true)"
421:    echo "VALIDATE_TRY=$n HEALTH=$health LAPI_RC=${lapi_rc:-NA} CAPI_RC=${capi_rc:-NA} FATAL=$fatal ENV_BAD=${envbad:-NONE}"
422:    printf '%s\n' "$capi_out"
423:    if test "$health" = "200" && test "${lapi_rc:-NA}" = "0" && test "${capi_rc:-NA}" = "0" && test "$fatal" = "0" && test -z "$envbad"; then
430:  rc_before="$(docker inspect crowdsec --format '{{.RestartCount}}' 2>/dev/null || echo NA)"
432:  rc_after="$(docker inspect crowdsec --format '{{.RestartCount}}' 2>/dev/null || echo NA)"
433:  health_after="$(curl -sk --connect-timeout 3 --max-time 6 -o /tmp/771r_health_after.html -w '%{http_code}' http://[PRIVATE_IP]:8088/health || true)"
434:  lapi_after="$(docker exec crowdsec sh -lc 'cscli lapi status >/tmp/771r_lapi_after.out 2>&1; echo LAPI_RC=$?' 2>/dev/null | awk -F= '/^LAPI_RC=/{print $2}' | tail -1 || true)"
435:  capi_after="$(docker exec crowdsec sh -lc 'cscli capi status >/tmp/771r_capi_after.out 2>&1; echo CAPI_RC=$?' 2>/dev/null | awk -F= '/^CAPI_RC=/{print $2}' | tail -1 || true)"
436:  fatal_after="$(docker logs --since 240s crowdsec 2>&1 | grep -Eic 'fatal|TLS handshake timeout|unable to run local API|failed to get docker info|lookup socket-proxy|server misbehaving|mapping value is not allowed|missing credentials field|open /etc/crowdsec/online_api_credentials.yaml|proxyconnect tcp' || true)"
437:  env_after="$(docker inspect crowdsec --format '{{range .Config.Env}}{{println .}}{{end}}' 2>/dev/null | grep -E 'DISABLE_ONLINE_API|ARGS=.*no-capi|-no-capi' || true)"
439:  echo "FINAL_STABILITY RC_BEFORE=$rc_before RC_AFTER=$rc_after HEALTH_AFTER=$health_after LAPI_AFTER=${lapi_after:-NA} CAPI_AFTER=${capi_after:-NA} FATAL_AFTER=$fatal_after ENV_BAD_AFTER=${env_after:-NONE}"
441:  test "$rc_before" = "$rc_after" && test "$health_after" = "200" && test "${lapi_after:-NA}" = "0" && test "${capi_after:-NA}" = "0" && test "$fatal_after" = "0" && test -z "$env_after"
KNOWN_SCRIPT=/root/771r_netbird_public_vps_fixed_then_capi.sh SHA256=dc8119b6815d60e08f442e77faba6ce6e9899c4120d78490886e222b8510efa7 EXECUTABLE=false
8:PROOF="/root/evidence/771R_NETBIRD_PUBLIC_VPS_FIXED_THEN_CAPI_${TS}_PROOF.txt"
10:EDGE_REMOTE="/tmp/771r_edge_netbird_egress_capi_${TS}.sh"
11:EDGE_LOCAL="/root/771r_edge_netbird_egress_capi_${TS}.sh"
26:  timeout 20 ssh -n \
31:    "echo SSH_OK; echo USER=\$(id -un); echo HOSTNAME=\$(hostname); command -v netbird >/dev/null 2>&1 && netbird status 2>&1 || echo NETBIRD_CLI_MISSING; curl -4 -sk --connect-timeout 8 --max-time 20 -o /tmp/771r_capi.body -w 'DIRECT_CAPI_HTTP=%{http_code}\n' https://api.crowdsec.net/v3/watchers/login || true" \
51:EGRESS_DIR=/etc/homelab-crowdsec-capi-netbird-egress
53:HEALTH_FILE="$HEALTH_DIR/crowdsec-capi.txt"
73:    echo "CHECK=crowdsec-capi"
79:force_no_capi_stable() {
85:      DISABLE_ONLINE_API: "true"
86:      ARGS: "-no-capi"
109:wait_lapi() {
112:  echo "WAIT_LAPI=$label"
115:    health="$(curl -sk --connect-timeout 3 --max-time 6 -o /tmp/771r_health.html -w '%{http_code}' http://[PRIVATE_IP]:8088/health || true)"
117:    rc="$(printf '%s\n' "$out" | awk -F= '/^LAPI_RC=/{print $2}' | tail -1)"
118:    fatal="$(docker logs --since 30s crowdsec 2>&1 | grep -Eic 'fatal|unable to run local API|failed to get docker info|lookup socket-proxy|server misbehaving|mapping value is not allowed' || true)"
119:    echo "LAPI_TRY=$n HEALTH=$health LAPI_RC=${rc:-NA} FATAL_COUNT_30S=$fatal"
193:    raise SystemExit("api.server block not found")
197:    "      credentials_path: /etc/crowdsec/online_api_credentials.yaml",
236:  grep -nE 'DISABLE_ONLINE_API|ARGS|GODEBUG|HTTP_PROXY|HTTPS_PROXY|NO_PROXY|socket-proxy|published:|target:' /tmp/771r_compose.yml || true
237:  ! grep -qE 'DISABLE_ONLINE_API|ARGS:.*no-capi|-no-capi' /tmp/771r_compose.yml
251:    timeout 12 ssh -n \
256:      "echo SSH_OK; hostname; curl -4 -sk --connect-timeout 8 --max-time 20 -o /tmp/771r_capi.body -w 'DIRECT_CAPI_HTTP=%{http_code}\n' https://api.crowdsec.net/v3/watchers/login || true" \
268:    if ssh -n -fN -M -S "$ctl" \
278:      code="$(curl -sk --proxy "socks5h://[PRIVATE_IP]:${port}" --connect-timeout 12 --max-time 45 -o /tmp/771r_capi_proxy.body -w '%{http_code}' https://api.crowdsec.net/v3/watchers/login || true)"
279:      trace="$(curl -sk --proxy "socks5h://[PRIVATE_IP]:${port}" --connect-timeout 12 --max-time 45 https://www.cloudflare.com/cdn-cgi/trace 2>/dev/null | grep -E 'ip=|colo=' | sed -n '1,5p' || true)"
280:      echo "SOCKS_CAPI_HTTP=$code"
284:      ssh -S "$ctl" -O exit "$user@$ip" >/dev/null 2>&1 || true
317:  cat >/etc/systemd/system/homelab-crowdsec-capi-netbird-egress.service <<'EOF'
319:Description=Homelab CrowdSec CAPI NetBird VPS SOCKS egress
326:EnvironmentFile=/etc/homelab-crowdsec-capi-netbird-egress/current.env
327:ExecStart=/bin/sh -lc 'exec /usr/bin/ssh -N -D "${SOCKS_BIND}:${SOCKS_PORT}" -o BatchMode=yes -o ExitOnForwardFailure=yes -o ServerAliveInterval=30 -o ServerAliveCountMax=3 -o StrictHostKeyChecking=accept-new "${SSH_USER}@${SSH_HOST}"'
328:Restart=always
329:RestartSec=5
335:  cat >/usr/local/sbin/homelab-crowdsec-capi-egress-switch <<'EOF'
339:base=/etc/homelab-crowdsec-capi-netbird-egress
347:systemctl restart homelab-crowdsec-capi-netbird-egress.service
348:systemctl restart privoxy 2>/dev/null || true
350:systemctl --no-pager --full status homelab-crowdsec-capi-netbird-egress.service | sed -n '1,30p'
352:  chmod 755 /usr/local/sbin/homelab-crowdsec-capi-egress-switch
355:  systemctl enable --now homelab-crowdsec-capi-netbird-egress.service
356:  systemctl restart homelab-crowdsec-capi-netbird-egress.service
358:  systemctl is-active homelab-crowdsec-capi-netbird-egress.service || true
372:    if "HOMELAB_771" in line and "CROWDSEC_CAPI" in line and "BEGIN" in line:
374:    if "HOMELAB_771" in line and "CROWDSEC_CAPI" in line and "END" in line:
384:out.append("# HOMELAB_771R_CROWDSEC_CAPI_NETBIRD_BEGIN")
387:out.append("# HOMELAB_771R_CROWDSEC_CAPI_NETBIRD_END")
392:  systemctl restart privoxy
397:  code="$(curl -sk --proxy "http://${b}:${HTTP_PROXY_PORT}" --connect-timeout 12 --max-time 45 -o /tmp/771r_http_proxy_capi.body -w '%{http_code}' https://api.crowdsec.net/v3/watchers/login || true)"
398:  echo "HTTP_PROXY_CAPI_HTTP=$code"
402:register_capi() {
403:  local b proxy_url reg_out reg_rc ready n health lapi_rc capi_out capi_rc fatal envbad rc_before rc_after health_after lapi_after capi_after fatal_after env_after
405:  proxy_url="http://${b}:${HTTP_PROXY_PORT}"
406:  echo "REGISTER_CAPI proxy=$proxy_url"
408:  force_no_capi_stable
409:  wait_lapi "BEFORE_CAPI_REGISTER" || return 10
413:  if test -f config/online_api_credentials.yaml; then
414:    mkdir -p /opt/stacks/crowdsec/manual-backups/771r-old-online-creds-"$TS"
415:    mv config/online_api_credentials.yaml /opt/stacks/crowdsec/manual-backups/771r-old-online-creds-"$TS"/online_api_credentials.yaml.before-register
420:  wait_lapi "REGISTER_MODE" || return 13
425:    if cscli capi register --help 2>&1 | grep -q -- "-y"; then
426:      timeout 240 cscli capi register -y >/tmp/771r_register.out 2>&1
428:      timeout 240 sh -c "yes | cscli capi register" >/tmp/771r_register.out 2>&1
441:  if ! test -f config/online_api_credentials.yaml; then
445:  stat -c 'ONLINE_CREDS path=%n mode=%a owner=%U group=%G size=%s' config/online_api_credentials.yaml || true
446:  awk -F: '/^[A-Za-z0-9_ -]+:/ {gsub(/^[ \t]+|[ \t]+$/, "", $1); print $1 ": REDACTED"}' config/online_api_credentials.yaml | sed -n '1,40p'
448:  grep -Eq '^[[:space:]]*login:' config/online_api_credentials.yaml || return 22
455:  echo "VALIDATE_CAPI"
459:    health="$(curl -sk --connect-timeout 3 --max-time 6 -o /tmp/771r_health2.html -w '%{http_code}' http://[PRIVATE_IP]:8088/health || true)"
460:    lapi_rc="$(docker exec crowdsec sh -lc 'cscli lapi status >/tmp/771r_lapi2.out 2>&1; echo LAPI_RC=$?' 2>/dev/null | awk -F= '/^LAPI_RC=/{print $2}' | tail -1 || true)"
462:    capi_rc="$(printf '%s\n' "$capi_out" | awk -F= '/^CAPI_RC=/{print $2}' | tail -1)"
463:    fatal="$(docker logs --since 60s crowdsec 2>&1 | grep -Eic 'fatal|TLS handshake timeout|unable to run local API|failed to get docker info|lookup socket-proxy|server misbehaving|mapping value is not allowed|missing credentials field|open /etc/crowdsec/online_api_credentials.yaml|proxyconnect tcp' || true)"
464:    envbad="$(docker inspect crowdsec --format '{{range .Config.Env}}{{println .}}{{end}}' 2>/dev/null | grep -E 'DISABLE_ONLINE_API|ARGS=.*no-capi|-no-capi' || true)"
465:    echo "VALIDATE_TRY=$n HEALTH=$health LAPI_RC=${lapi_rc:-NA} CAPI_RC=${capi_rc:-NA} FATAL=$fatal ENV_BAD=${envbad:-NONE}"
466:    printf '%s\n' "$capi_out"
467:    if test "$health" = "200" && test "${lapi_rc:-NA}" = "0" && test "${capi_rc:-NA}" = "0" && test "$fatal" = "0" && test -z "$envbad"; then
474:  rc_before="$(docker inspect crowdsec --format '{{.RestartCount}}' 2>/dev/null || echo NA)"
476:  rc_after="$(docker inspect crowdsec --format '{{.RestartCount}}' 2>/dev/null || echo NA)"
477:  health_after="$(curl -sk --connect-timeout 3 --max-time 6 -o /tmp/771r_health_after.html -w '%{http_code}' http://[PRIVATE_IP]:8088/health || true)"
478:  lapi_after="$(docker exec crowdsec sh -lc 'cscli lapi status >/tmp/771r_lapi_after.out 2>&1; echo LAPI_RC=$?' 2>/dev/null | awk -F= '/^LAPI_RC=/{print $2}' | tail -1 || true)"
KNOWN_SCRIPT=/root/771s_edge_capi_netbird_20260702T170251Z.sh SHA256=c4783c14a3a132616af5db6a065270ccd39a7690f9fd38d0ef27fe5de6bd07e5 EXECUTABLE=true
9:EGRESS_DIR=/etc/homelab-crowdsec-capi-netbird-egress
11:HEALTH_FILE="$HEALTH_DIR/crowdsec-capi.txt"
30:    echo "CHECK=crowdsec-capi"
36:force_no_capi_stable() {
42:      DISABLE_ONLINE_API: "true"
43:      ARGS: "-no-capi"
65:wait_lapi() {
67:  echo "WAIT_LAPI=$label"
70:    health="$(curl -sk --connect-timeout 3 --max-time 6 -o /tmp/771s_health.html -w '%{http_code}' http://[PRIVATE_IP]:8088/health || true)"
72:    rc="$(printf '%s\n' "$out" | awk -F= '/^LAPI_RC=/{print $2}' | tail -1)"
73:    fatal="$(docker logs --since 30s crowdsec 2>&1 | grep -Eic 'fatal|unable to run local API|failed to get docker info|lookup socket-proxy|server misbehaving|mapping value is not allowed' || true)"
74:    echo "LAPI_TRY=$n HEALTH=$health LAPI_RC=${rc:-NA} FATAL_COUNT_30S=$fatal"
149:    raise SystemExit("api.server block not found")
153:    "      credentials_path: /etc/crowdsec/online_api_credentials.yaml",
191:  grep -nE 'DISABLE_ONLINE_API|ARGS|GODEBUG|HTTP_PROXY|HTTPS_PROXY|NO_PROXY|socket-proxy|published:|target:' /tmp/771s_compose.yml || true
192:  ! grep -qE 'DISABLE_ONLINE_API|ARGS:.*no-capi|-no-capi' /tmp/771s_compose.yml
204:    timeout 12 ssh -n \
209:      "echo SSH_OK; hostname; curl -4 -sk --connect-timeout 8 --max-time 20 -o /tmp/771s_capi.body -w 'DIRECT_CAPI_HTTP=%{http_code}\n' https://api.crowdsec.net/v3/watchers/login || true" \
221:    if ssh -n -fN -M -S "$ctl" \
231:      code="$(curl -sk --proxy "socks5h://[PRIVATE_IP]:${port}" --connect-timeout 12 --max-time 45 -o /tmp/771s_capi_proxy.body -w '%{http_code}' https://api.crowdsec.net/v3/watchers/login || true)"
232:      trace="$(curl -sk --proxy "socks5h://[PRIVATE_IP]:${port}" --connect-timeout 12 --max-time 45 https://www.cloudflare.com/cdn-cgi/trace 2>/dev/null | grep -E 'ip=|colo=' | sed -n '1,5p' || true)"
233:      echo "SOCKS_CAPI_HTTP=$code"
237:      ssh -S "$ctl" -O exit "$user@$ip" >/dev/null 2>&1 || true
269:  cat >/etc/systemd/system/homelab-crowdsec-capi-netbird-egress.service <<'EOF'
271:Description=Homelab CrowdSec CAPI NetBird VPS SOCKS egress
278:EnvironmentFile=/etc/homelab-crowdsec-capi-netbird-egress/current.env
279:ExecStart=/bin/sh -lc 'exec /usr/bin/ssh -N -D "${SOCKS_BIND}:${SOCKS_PORT}" -o BatchMode=yes -o ExitOnForwardFailure=yes -o ServerAliveInterval=30 -o ServerAliveCountMax=3 -o StrictHostKeyChecking=accept-new "${SSH_USER}@${SSH_HOST}"'
280:Restart=always
281:RestartSec=5
287:  cat >/usr/local/sbin/homelab-crowdsec-capi-egress-switch <<'EOF'
291:base=/etc/homelab-crowdsec-capi-netbird-egress
299:systemctl restart homelab-crowdsec-capi-netbird-egress.service
300:systemctl restart privoxy 2>/dev/null || true
302:systemctl --no-pager --full status homelab-crowdsec-capi-netbird-egress.service | sed -n '1,30p'
304:  chmod 755 /usr/local/sbin/homelab-crowdsec-capi-egress-switch
307:  systemctl enable --now homelab-crowdsec-capi-netbird-egress.service
308:  systemctl restart homelab-crowdsec-capi-netbird-egress.service
310:  systemctl is-active homelab-crowdsec-capi-netbird-egress.service || true
325:    if "HOMELAB_771" in line and "CROWDSEC_CAPI" in line and "BEGIN" in line:
328:    if "HOMELAB_771" in line and "CROWDSEC_CAPI" in line and "END" in line:
339:out.append("# HOMELAB_771S_CROWDSEC_CAPI_NETBIRD_BEGIN")
342:out.append("# HOMELAB_771S_CROWDSEC_CAPI_NETBIRD_END")
347:  systemctl restart privoxy
352:  code="$(curl -sk --proxy "http://${b}:${HTTP_PROXY_PORT}" --connect-timeout 12 --max-time 45 -o /tmp/771s_http_proxy_capi.body -w '%{http_code}' https://api.crowdsec.net/v3/watchers/login || true)"
353:  echo "HTTP_PROXY_CAPI_HTTP=$code"
357:register_capi() {
359:  proxy_url="http://${b}:${HTTP_PROXY_PORT}"
360:  echo "REGISTER_CAPI proxy=$proxy_url"
362:  force_no_capi_stable
363:  wait_lapi "BEFORE_CAPI_REGISTER" || return 10
367:  if test -f config/online_api_credentials.yaml; then
368:    mkdir -p /opt/stacks/crowdsec/manual-backups/771s-old-online-creds-"$TS"
369:    mv config/online_api_credentials.yaml /opt/stacks/crowdsec/manual-backups/771s-old-online-creds-"$TS"/online_api_credentials.yaml.before-register
374:  wait_lapi "REGISTER_MODE" || return 13
379:    if cscli capi register --help 2>&1 | grep -q -- "-y"; then
380:      timeout 240 cscli capi register -y >/tmp/771s_register.out 2>&1
382:      timeout 240 sh -c "yes | cscli capi register" >/tmp/771s_register.out 2>&1
395:  if ! test -f config/online_api_credentials.yaml; then
399:  stat -c 'ONLINE_CREDS path=%n mode=%a owner=%U group=%G size=%s' config/online_api_credentials.yaml || true
400:  awk -F: '/^[A-Za-z0-9_ -]+:/ {gsub(/^[ \t]+|[ \t]+$/, "", $1); print $1 ": REDACTED"}' config/online_api_credentials.yaml | sed -n '1,40p'
402:  grep -Eq '^[[:space:]]*login:' config/online_api_credentials.yaml || return 22
409:  echo "VALIDATE_CAPI"
413:    health="$(curl -sk --connect-timeout 3 --max-time 6 -o /tmp/771s_health2.html -w '%{http_code}' http://[PRIVATE_IP]:8088/health || true)"
414:    lapi_rc="$(docker exec crowdsec sh -lc 'cscli lapi status >/tmp/771s_lapi2.out 2>&1; echo LAPI_RC=$?' 2>/dev/null | awk -F= '/^LAPI_RC=/{print $2}' | tail -1 || true)"
416:    capi_rc="$(printf '%s\n' "$capi_out" | awk -F= '/^CAPI_RC=/{print $2}' | tail -1)"
417:    fatal="$(docker logs --since 60s crowdsec 2>&1 | grep -Eic 'fatal|TLS handshake timeout|unable to run local API|failed to get docker info|lookup socket-proxy|server misbehaving|mapping value is not allowed|missing credentials field|open /etc/crowdsec/online_api_credentials.yaml|proxyconnect tcp' || true)"
418:    envbad="$(docker inspect crowdsec --format '{{range .Config.Env}}{{println .}}{{end}}' 2>/dev/null | grep -E 'DISABLE_ONLINE_API|ARGS=.*no-capi|-no-capi' || true)"
419:    echo "VALIDATE_TRY=$n HEALTH=$health LAPI_RC=${lapi_rc:-NA} CAPI_RC=${capi_rc:-NA} FATAL=$fatal ENV_BAD=${envbad:-NONE}"
420:    printf '%s\n' "$capi_out"
421:    if test "$health" = "200" && test "${lapi_rc:-NA}" = "0" && test "${capi_rc:-NA}" = "0" && test "$fatal" = "0" && test -z "$envbad"; then
428:  rc_before="$(docker inspect crowdsec --format '{{.RestartCount}}' 2>/dev/null || echo NA)"
430:  rc_after="$(docker inspect crowdsec --format '{{.RestartCount}}' 2>/dev/null || echo NA)"
431:  health_after="$(curl -sk --connect-timeout 3 --max-time 6 -o /tmp/771s_health_after.html -w '%{http_code}' http://[PRIVATE_IP]:8088/health || true)"
432:  lapi_after="$(docker exec crowdsec sh -lc 'cscli lapi status >/tmp/771s_lapi_after.out 2>&1; echo LAPI_RC=$?' 2>/dev/null | awk -F= '/^LAPI_RC=/{print $2}' | tail -1 || true)"
433:  capi_after="$(docker exec crowdsec sh -lc 'cscli capi status >/tmp/771s_capi_after.out 2>&1; echo CAPI_RC=$?' 2>/dev/null | awk -F= '/^CAPI_RC=/{print $2}' | tail -1 || true)"
434:  fatal_after="$(docker logs --since 240s crowdsec 2>&1 | grep -Eic 'fatal|TLS handshake timeout|unable to run local API|failed to get docker info|lookup socket-proxy|server misbehaving|mapping value is not allowed|missing credentials field|open /etc/crowdsec/online_api_credentials.yaml|proxyconnect tcp' || true)"
435:  env_after="$(docker inspect crowdsec --format '{{range .Config.Env}}{{println .}}{{end}}' 2>/dev/null | grep -E 'DISABLE_ONLINE_API|ARGS=.*no-capi|-no-capi' || true)"
437:  echo "FINAL_STABILITY RC_BEFORE=$rc_before RC_AFTER=$rc_after HEALTH_AFTER=$health_after LAPI_AFTER=${lapi_after:-NA} CAPI_AFTER=${capi_after:-NA} FATAL_AFTER=$fatal_after ENV_BAD_AFTER=${env_after:-NONE}"
439:  test "$rc_before" = "$rc_after" && test "$health_after" = "200" && test "${lapi_after:-NA}" = "0" && test "${capi_after:-NA}" = "0" && test "$fatal_after" = "0" && test -z "$env_after"
443:echo "STEP=771S_EDGE_NETBIRD_EGRESS_CAPI"
KNOWN_SCRIPT=/root/771s_vps_identity_repair_netbird_capi.sh SHA256=16121a810320b1517291830ba128baf6c68e7b3e6f78786481dedb78a1f061b9 EXECUTABLE=false
8:PROOF="/root/evidence/771S_VPS_IDENTITY_REPAIR_NETBIRD_CAPI_${TS}_PROOF.txt"
13:EDGE_REMOTE="/tmp/771s_edge_capi_netbird_${TS}.sh"
14:EDGE_LOCAL="/root/771s_edge_capi_netbird_${TS}.sh"
31:EGRESS_DIR=/etc/homelab-crowdsec-capi-netbird-egress
33:HEALTH_FILE="$HEALTH_DIR/crowdsec-capi.txt"
52:    echo "CHECK=crowdsec-capi"
58:force_no_capi_stable() {
64:      DISABLE_ONLINE_API: "true"
65:      ARGS: "-no-capi"
87:wait_lapi() {
89:  echo "WAIT_LAPI=$label"
92:    health="$(curl -sk --connect-timeout 3 --max-time 6 -o /tmp/771s_health.html -w '%{http_code}' http://[PRIVATE_IP]:8088/health || true)"
94:    rc="$(printf '%s\n' "$out" | awk -F= '/^LAPI_RC=/{print $2}' | tail -1)"
95:    fatal="$(docker logs --since 30s crowdsec 2>&1 | grep -Eic 'fatal|unable to run local API|failed to get docker info|lookup socket-proxy|server misbehaving|mapping value is not allowed' || true)"
96:    echo "LAPI_TRY=$n HEALTH=$health LAPI_RC=${rc:-NA} FATAL_COUNT_30S=$fatal"
171:    raise SystemExit("api.server block not found")
175:    "      credentials_path: /etc/crowdsec/online_api_credentials.yaml",
213:  grep -nE 'DISABLE_ONLINE_API|ARGS|GODEBUG|HTTP_PROXY|HTTPS_PROXY|NO_PROXY|socket-proxy|published:|target:' /tmp/771s_compose.yml || true
214:  ! grep -qE 'DISABLE_ONLINE_API|ARGS:.*no-capi|-no-capi' /tmp/771s_compose.yml
226:    timeout 12 ssh -n \
231:      "echo SSH_OK; hostname; curl -4 -sk --connect-timeout 8 --max-time 20 -o /tmp/771s_capi.body -w 'DIRECT_CAPI_HTTP=%{http_code}\n' https://api.crowdsec.net/v3/watchers/login || true" \
243:    if ssh -n -fN -M -S "$ctl" \
253:      code="$(curl -sk --proxy "socks5h://[PRIVATE_IP]:${port}" --connect-timeout 12 --max-time 45 -o /tmp/771s_capi_proxy.body -w '%{http_code}' https://api.crowdsec.net/v3/watchers/login || true)"
254:      trace="$(curl -sk --proxy "socks5h://[PRIVATE_IP]:${port}" --connect-timeout 12 --max-time 45 https://www.cloudflare.com/cdn-cgi/trace 2>/dev/null | grep -E 'ip=|colo=' | sed -n '1,5p' || true)"
255:      echo "SOCKS_CAPI_HTTP=$code"
259:      ssh -S "$ctl" -O exit "$user@$ip" >/dev/null 2>&1 || true
291:  cat >/etc/systemd/system/homelab-crowdsec-capi-netbird-egress.service <<'EOF'
293:Description=Homelab CrowdSec CAPI NetBird VPS SOCKS egress
300:EnvironmentFile=/etc/homelab-crowdsec-capi-netbird-egress/current.env
301:ExecStart=/bin/sh -lc 'exec /usr/bin/ssh -N -D "${SOCKS_BIND}:${SOCKS_PORT}" -o BatchMode=yes -o ExitOnForwardFailure=yes -o ServerAliveInterval=30 -o ServerAliveCountMax=3 -o StrictHostKeyChecking=accept-new "${SSH_USER}@${SSH_HOST}"'
302:Restart=always
303:RestartSec=5
309:  cat >/usr/local/sbin/homelab-crowdsec-capi-egress-switch <<'EOF'
313:base=/etc/homelab-crowdsec-capi-netbird-egress
321:systemctl restart homelab-crowdsec-capi-netbird-egress.service
322:systemctl restart privoxy 2>/dev/null || true
324:systemctl --no-pager --full status homelab-crowdsec-capi-netbird-egress.service | sed -n '1,30p'
326:  chmod 755 /usr/local/sbin/homelab-crowdsec-capi-egress-switch
329:  systemctl enable --now homelab-crowdsec-capi-netbird-egress.service
330:  systemctl restart homelab-crowdsec-capi-netbird-egress.service
332:  systemctl is-active homelab-crowdsec-capi-netbird-egress.service || true
347:    if "HOMELAB_771" in line and "CROWDSEC_CAPI" in line and "BEGIN" in line:
350:    if "HOMELAB_771" in line and "CROWDSEC_CAPI" in line and "END" in line:
361:out.append("# HOMELAB_771S_CROWDSEC_CAPI_NETBIRD_BEGIN")
364:out.append("# HOMELAB_771S_CROWDSEC_CAPI_NETBIRD_END")
369:  systemctl restart privoxy
374:  code="$(curl -sk --proxy "http://${b}:${HTTP_PROXY_PORT}" --connect-timeout 12 --max-time 45 -o /tmp/771s_http_proxy_capi.body -w '%{http_code}' https://api.crowdsec.net/v3/watchers/login || true)"
375:  echo "HTTP_PROXY_CAPI_HTTP=$code"
379:register_capi() {
381:  proxy_url="http://${b}:${HTTP_PROXY_PORT}"
382:  echo "REGISTER_CAPI proxy=$proxy_url"
384:  force_no_capi_stable
385:  wait_lapi "BEFORE_CAPI_REGISTER" || return 10
389:  if test -f config/online_api_credentials.yaml; then
390:    mkdir -p /opt/stacks/crowdsec/manual-backups/771s-old-online-creds-"$TS"
391:    mv config/online_api_credentials.yaml /opt/stacks/crowdsec/manual-backups/771s-old-online-creds-"$TS"/online_api_credentials.yaml.before-register
396:  wait_lapi "REGISTER_MODE" || return 13
401:    if cscli capi register --help 2>&1 | grep -q -- "-y"; then
402:      timeout 240 cscli capi register -y >/tmp/771s_register.out 2>&1
404:      timeout 240 sh -c "yes | cscli capi register" >/tmp/771s_register.out 2>&1
417:  if ! test -f config/online_api_credentials.yaml; then
421:  stat -c 'ONLINE_CREDS path=%n mode=%a owner=%U group=%G size=%s' config/online_api_credentials.yaml || true
422:  awk -F: '/^[A-Za-z0-9_ -]+:/ {gsub(/^[ \t]+|[ \t]+$/, "", $1); print $1 ": REDACTED"}' config/online_api_credentials.yaml | sed -n '1,40p'
424:  grep -Eq '^[[:space:]]*login:' config/online_api_credentials.yaml || return 22
431:  echo "VALIDATE_CAPI"
435:    health="$(curl -sk --connect-timeout 3 --max-time 6 -o /tmp/771s_health2.html -w '%{http_code}' http://[PRIVATE_IP]:8088/health || true)"
436:    lapi_rc="$(docker exec crowdsec sh -lc 'cscli lapi status >/tmp/771s_lapi2.out 2>&1; echo LAPI_RC=$?' 2>/dev/null | awk -F= '/^LAPI_RC=/{print $2}' | tail -1 || true)"
438:    capi_rc="$(printf '%s\n' "$capi_out" | awk -F= '/^CAPI_RC=/{print $2}' | tail -1)"
439:    fatal="$(docker logs --since 60s crowdsec 2>&1 | grep -Eic 'fatal|TLS handshake timeout|unable to run local API|failed to get docker info|lookup socket-proxy|server misbehaving|mapping value is not allowed|missing credentials field|open /etc/crowdsec/online_api_credentials.yaml|proxyconnect tcp' || true)"
440:    envbad="$(docker inspect crowdsec --format '{{range .Config.Env}}{{println .}}{{end}}' 2>/dev/null | grep -E 'DISABLE_ONLINE_API|ARGS=.*no-capi|-no-capi' || true)"
441:    echo "VALIDATE_TRY=$n HEALTH=$health LAPI_RC=${lapi_rc:-NA} CAPI_RC=${capi_rc:-NA} FATAL=$fatal ENV_BAD=${envbad:-NONE}"
442:    printf '%s\n' "$capi_out"
443:    if test "$health" = "200" && test "${lapi_rc:-NA}" = "0" && test "${capi_rc:-NA}" = "0" && test "$fatal" = "0" && test -z "$envbad"; then
450:  rc_before="$(docker inspect crowdsec --format '{{.RestartCount}}' 2>/dev/null || echo NA)"
452:  rc_after="$(docker inspect crowdsec --format '{{.RestartCount}}' 2>/dev/null || echo NA)"
453:  health_after="$(curl -sk --connect-timeout 3 --max-time 6 -o /tmp/771s_health_after.html -w '%{http_code}' http://[PRIVATE_IP]:8088/health || true)"
454:  lapi_after="$(docker exec crowdsec sh -lc 'cscli lapi status >/tmp/771s_lapi_after.out 2>&1; echo LAPI_RC=$?' 2>/dev/null | awk -F= '/^LAPI_RC=/{print $2}' | tail -1 || true)"
455:  capi_after="$(docker exec crowdsec sh -lc 'cscli capi status >/tmp/771s_capi_after.out 2>&1; echo CAPI_RC=$?' 2>/dev/null | awk -F= '/^CAPI_RC=/{print $2}' | tail -1 || true)"
456:  fatal_after="$(docker logs --since 240s crowdsec 2>&1 | grep -Eic 'fatal|TLS handshake timeout|unable to run local API|failed to get docker info|lookup socket-proxy|server misbehaving|mapping value is not allowed|missing credentials field|open /etc/crowdsec/online_api_credentials.yaml|proxyconnect tcp' || true)"
457:  env_after="$(docker inspect crowdsec --format '{{range .Config.Env}}{{println .}}{{end}}' 2>/dev/null | grep -E 'DISABLE_ONLINE_API|ARGS=.*no-capi|-no-capi' || true)"
KNOWN_SCRIPT=/root/771t_temp_hostkey_netbird_identity_then_capi.sh SHA256=0c3d628b23b67849d52112322ab2e1ee3779012c10578a0b8cece0d8ddf639da EXECUTABLE=false
8:PROOF="/root/evidence/771T_TEMP_HOSTKEY_NETBIRD_IDENTITY_THEN_CAPI_${TS}_PROOF.txt"
11:EDGE_SCRIPT_LOCAL="/root/771t_edge_capi_${TS}.sh"
12:EDGE_SCRIPT_REMOTE="/tmp/771t_edge_capi_${TS}.sh"
31:EGRESS_DIR=/etc/homelab-crowdsec-capi-netbird-egress
33:HEALTH_FILE="$HEALTH_DIR/crowdsec-capi.txt"
50:    echo "CHECK=crowdsec-capi"
56:force_no_capi_stable() {
62:      DISABLE_ONLINE_API: "true"
63:      ARGS: "-no-capi"
85:wait_lapi() {
87:  echo "WAIT_LAPI=$label"
90:    health="$(curl -sk --connect-timeout 3 --max-time 6 -o /tmp/771t_health.html -w '%{http_code}' http://[PRIVATE_IP]:8088/health || true)"
92:    rc="$(printf '%s\n' "$out" | awk -F= '/^LAPI_RC=/{print $2}' | tail -1)"
93:    fatal="$(docker logs --since 30s crowdsec 2>&1 | grep -Eic 'fatal|unable to run local API|failed to get docker info|lookup socket-proxy|server misbehaving|mapping value is not allowed' || true)"
94:    echo "LAPI_TRY=$n HEALTH=$health LAPI_RC=${rc:-NA} FATAL_COUNT_30S=$fatal"
166:    raise SystemExit("api.server block not found")
169:    "      credentials_path: /etc/crowdsec/online_api_credentials.yaml",
207:  grep -nE 'DISABLE_ONLINE_API|ARGS|GODEBUG|HTTP_PROXY|HTTPS_PROXY|NO_PROXY|socket-proxy|published:|target:' /tmp/771t_compose.yml || true
208:  ! grep -qE 'DISABLE_ONLINE_API|ARGS:.*no-capi|-no-capi' /tmp/771t_compose.yml
217:  timeout 15 ssh -n -o BatchMode=yes -o ConnectTimeout=8 -o StrictHostKeyChecking=accept-new "$TARGET_USER@$TARGET_NB" \
218:    "echo SSH_OK; hostname; curl -4 -sk --connect-timeout 8 --max-time 20 -o /tmp/771t_capi_direct.body -w 'DIRECT_CAPI_HTTP=%{http_code}\n' https://api.crowdsec.net/v3/watchers/login || true" >"$out" 2>&1
236:  cat >/etc/systemd/system/homelab-crowdsec-capi-netbird-egress.service <<'EOF'
238:Description=Homelab CrowdSec CAPI NetBird VPS SOCKS egress
245:EnvironmentFile=/etc/homelab-crowdsec-capi-netbird-egress/current.env
246:ExecStart=/bin/sh -lc 'exec /usr/bin/ssh -N -D "${SOCKS_BIND}:${SOCKS_PORT}" -o BatchMode=yes -o ExitOnForwardFailure=yes -o ServerAliveInterval=30 -o ServerAliveCountMax=3 -o StrictHostKeyChecking=accept-new "${SSH_USER}@${SSH_HOST}"'
247:Restart=always
248:RestartSec=5
254:  cat >/usr/local/sbin/homelab-crowdsec-capi-egress-switch <<'EOF'
258:base=/etc/homelab-crowdsec-capi-netbird-egress
266:systemctl restart homelab-crowdsec-capi-netbird-egress.service
267:systemctl restart privoxy 2>/dev/null || true
269:systemctl --no-pager --full status homelab-crowdsec-capi-netbird-egress.service | sed -n '1,30p'
271:  chmod 755 /usr/local/sbin/homelab-crowdsec-capi-egress-switch
274:  systemctl enable --now homelab-crowdsec-capi-netbird-egress.service
275:  systemctl restart homelab-crowdsec-capi-netbird-egress.service
277:  systemctl is-active homelab-crowdsec-capi-netbird-egress.service || true
293:    if "HOMELAB_771" in line and "CROWDSEC_CAPI" in line and "BEGIN" in line:
296:    if "HOMELAB_771" in line and "CROWDSEC_CAPI" in line and "END" in line:
307:out.append("# HOMELAB_771T_CROWDSEC_CAPI_NETBIRD_BEGIN")
310:out.append("# HOMELAB_771T_CROWDSEC_CAPI_NETBIRD_END")
315:  systemctl restart privoxy
320:  code="$(curl -sk --proxy "http://${b}:${HTTP_PROXY_PORT}" --connect-timeout 12 --max-time 45 -o /tmp/771t_http_proxy_capi.body -w '%{http_code}' https://api.crowdsec.net/v3/watchers/login || true)"
321:  trace="$(curl -sk --proxy "http://${b}:${HTTP_PROXY_PORT}" --connect-timeout 12 --max-time 45 https://www.cloudflare.com/cdn-cgi/trace 2>/dev/null | grep -E 'ip=|colo=' | sed -n '1,6p' || true)"
322:  echo "HTTP_PROXY_CAPI_HTTP=$code"
329:register_capi() {
331:  proxy_url="http://${b}:${HTTP_PROXY_PORT}"
332:  echo "REGISTER_CAPI proxy=$proxy_url"
334:  force_no_capi_stable
335:  wait_lapi "BEFORE_CAPI_REGISTER" || return 10
339:  if test -f config/online_api_credentials.yaml; then
340:    mkdir -p /opt/stacks/crowdsec/manual-backups/771t-old-online-creds-"$TS"
341:    mv config/online_api_credentials.yaml /opt/stacks/crowdsec/manual-backups/771t-old-online-creds-"$TS"/online_api_credentials.yaml.before-register
346:  wait_lapi "REGISTER_MODE" || return 13
351:    if cscli capi register --help 2>&1 | grep -q -- "-y"; then
352:      timeout 240 cscli capi register -y >/tmp/771t_register.out 2>&1
354:      timeout 240 sh -c "yes | cscli capi register" >/tmp/771t_register.out 2>&1
367:  if ! test -f config/online_api_credentials.yaml; then
371:  stat -c 'ONLINE_CREDS path=%n mode=%a owner=%U group=%G size=%s' config/online_api_credentials.yaml || true
372:  awk -F: '/^[A-Za-z0-9_ -]+:/ {gsub(/^[ \t]+|[ \t]+$/, "", $1); print $1 ": REDACTED"}' config/online_api_credentials.yaml | sed -n '1,40p'
374:  grep -Eq '^[[:space:]]*login:' config/online_api_credentials.yaml || return 22
381:  echo "VALIDATE_CAPI"
385:    health="$(curl -sk --connect-timeout 3 --max-time 6 -o /tmp/771t_health2.html -w '%{http_code}' http://[PRIVATE_IP]:8088/health || true)"
386:    lapi_rc="$(docker exec crowdsec sh -lc 'cscli lapi status >/tmp/771t_lapi2.out 2>&1; echo LAPI_RC=$?' 2>/dev/null | awk -F= '/^LAPI_RC=/{print $2}' | tail -1 || true)"
388:    capi_rc="$(printf '%s\n' "$capi_out" | awk -F= '/^CAPI_RC=/{print $2}' | tail -1)"
389:    fatal="$(docker logs --since 60s crowdsec 2>&1 | grep -Eic 'fatal|TLS handshake timeout|unable to run local API|failed to get docker info|lookup socket-proxy|server misbehaving|mapping value is not allowed|missing credentials field|open /etc/crowdsec/online_api_credentials.yaml|proxyconnect tcp' || true)"
390:    envbad="$(docker inspect crowdsec --format '{{range .Config.Env}}{{println .}}{{end}}' 2>/dev/null | grep -E 'DISABLE_ONLINE_API|ARGS=.*no-capi|-no-capi' || true)"
391:    echo "VALIDATE_TRY=$n HEALTH=$health LAPI_RC=${lapi_rc:-NA} CAPI_RC=${capi_rc:-NA} FATAL=$fatal ENV_BAD=${envbad:-NONE}"
392:    printf '%s\n' "$capi_out"
393:    if test "$health" = "200" && test "${lapi_rc:-NA}" = "0" && test "${capi_rc:-NA}" = "0" && test "$fatal" = "0" && test -z "$envbad"; then
400:  rc_before="$(docker inspect crowdsec --format '{{.RestartCount}}' 2>/dev/null || echo NA)"
402:  rc_after="$(docker inspect crowdsec --format '{{.RestartCount}}' 2>/dev/null || echo NA)"
403:  health_after="$(curl -sk --connect-timeout 3 --max-time 6 -o /tmp/771t_health_after.html -w '%{http_code}' http://[PRIVATE_IP]:8088/health || true)"
404:  lapi_after="$(docker exec crowdsec sh -lc 'cscli lapi status >/tmp/771t_lapi_after.out 2>&1; echo LAPI_RC=$?' 2>/dev/null | awk -F= '/^LAPI_RC=/{print $2}' | tail -1 || true)"
405:  capi_after="$(docker exec crowdsec sh -lc 'cscli capi status >/tmp/771t_capi_after.out 2>&1; echo CAPI_RC=$?' 2>/dev/null | awk -F= '/^CAPI_RC=/{print $2}' | tail -1 || true)"
406:  fatal_after="$(docker logs --since 240s crowdsec 2>&1 | grep -Eic 'fatal|TLS handshake timeout|unable to run local API|failed to get docker info|lookup socket-proxy|server misbehaving|mapping value is not allowed|missing credentials field|open /etc/crowdsec/online_api_credentials.yaml|proxyconnect tcp' || true)"
407:  env_after="$(docker inspect crowdsec --format '{{range .Config.Env}}{{println .}}{{end}}' 2>/dev/null | grep -E 'DISABLE_ONLINE_API|ARGS=.*no-capi|-no-capi' || true)"
409:  echo "FINAL_STABILITY RC_BEFORE=$rc_before RC_AFTER=$rc_after HEALTH_AFTER=$health_after LAPI_AFTER=${lapi_after:-NA} CAPI_AFTER=${capi_after:-NA} FATAL_AFTER=$fatal_after ENV_BAD_AFTER=${env_after:-NONE}"
411:  test "$rc_before" = "$rc_after" && test "$health_after" = "200" && test "${lapi_after:-NA}" = "0" && test "${capi_after:-NA}" = "0" && test "$fatal_after" = "0" && test -z "$env_after"
415:echo "STEP=771T_EDGE_CAPI_VIA_VERIFIED_NETBIRD_PEER"
418:systemctl restart netbird 2>/dev/null || true
KNOWN_SCRIPT=/root/771u_find_key_fix_netbird_egress_capi.sh SHA256=6b6511ec3d614793e3542777ccfcb5e8c5f09cff77ee2d57624b3ac980787bcb EXECUTABLE=false
8:PROOF="/root/evidence/771U_FIND_KEY_FIX_NETBIRD_EGRESS_CAPI_${TS}_PROOF.txt"
11:EDGE_REMOTE="/tmp/771u_edge_register_capi_${TS}.sh"
12:EDGE_LOCAL="/root/771u_edge_register_capi_${TS}.sh"
31:EGRESS_DIR=/etc/homelab-crowdsec-capi-netbird-egress
33:HEALTH_FILE="$HEALTH_DIR/crowdsec-capi.txt"
52:    echo "CHECK=crowdsec-capi"
58:force_no_capi_stable() {
64:      DISABLE_ONLINE_API: "true"
65:      ARGS: "-no-capi"
87:wait_lapi() {
89:  echo "WAIT_LAPI=$label"
92:    health="$(curl -sk --connect-timeout 3 --max-time 6 -o /tmp/771u_health.html -w '%{http_code}' http://[PRIVATE_IP]:8088/health || true)"
94:    rc="$(printf '%s\n' "$out" | awk -F= '/^LAPI_RC=/{print $2}' | tail -1)"
95:    fatal="$(docker logs --since 30s crowdsec 2>&1 | grep -Eic 'fatal|unable to run local API|failed to get docker info|lookup socket-proxy|server misbehaving|mapping value is not allowed' || true)"
96:    echo "LAPI_TRY=$n HEALTH=$health LAPI_RC=${rc:-NA} FATAL_COUNT_30S=$fatal"
167:    raise SystemExit("api.server block not found")
170:    "      credentials_path: /etc/crowdsec/online_api_credentials.yaml",
207:  grep -nE 'DISABLE_ONLINE_API|ARGS|GODEBUG|HTTP_PROXY|HTTPS_PROXY|NO_PROXY|socket-proxy|published:|target:' /tmp/771u_compose.yml || true
208:  ! grep -qE 'DISABLE_ONLINE_API|ARGS:.*no-capi|-no-capi' /tmp/771u_compose.yml
213:    ssh-keygen -q -t ed25519 -N "" -C "homelab-crowdsec-capi-netbird-egress-edge" -f "$SSH_KEY"
227:  timeout 15 ssh -n \
234:    "echo SSH_OK; hostname; curl -4 -sk --connect-timeout 8 --max-time 20 -o /tmp/771u_capi_direct.body -w 'DIRECT_CAPI_HTTP=%{http_code}\n' https://api.crowdsec.net/v3/watchers/login || true" >"$out" 2>&1
253:  cat >/etc/systemd/system/homelab-crowdsec-capi-netbird-egress.service <<'EOF'
255:Description=Homelab CrowdSec CAPI NetBird VPS SOCKS egress
262:EnvironmentFile=/etc/homelab-crowdsec-capi-netbird-egress/current.env
263:ExecStart=/bin/sh -lc 'exec /usr/bin/ssh -N -i "${SSH_KEY}" -D "${SOCKS_BIND}:${SOCKS_PORT}" -o IdentitiesOnly=yes -o BatchMode=yes -o ExitOnForwardFailure=yes -o ServerAliveInterval=30 -o ServerAliveCountMax=3 -o StrictHostKeyChecking=accept-new "${SSH_USER}@${SSH_HOST}"'
264:Restart=always
265:RestartSec=5
271:  cat >/usr/local/sbin/homelab-crowdsec-capi-egress-switch <<'EOF'
275:base=/etc/homelab-crowdsec-capi-netbird-egress
283:systemctl restart homelab-crowdsec-capi-netbird-egress.service
284:systemctl restart privoxy 2>/dev/null || true
286:systemctl --no-pager --full status homelab-crowdsec-capi-netbird-egress.service | sed -n '1,30p'
288:  chmod 755 /usr/local/sbin/homelab-crowdsec-capi-egress-switch
291:  systemctl enable --now homelab-crowdsec-capi-netbird-egress.service
292:  systemctl restart homelab-crowdsec-capi-netbird-egress.service
294:  systemctl is-active homelab-crowdsec-capi-netbird-egress.service || true
310:    if "HOMELAB_771" in line and "CROWDSEC_CAPI" in line and "BEGIN" in line:
313:    if "HOMELAB_771" in line and "CROWDSEC_CAPI" in line and "END" in line:
324:out.append("# HOMELAB_771U_CROWDSEC_CAPI_NETBIRD_BEGIN")
327:out.append("# HOMELAB_771U_CROWDSEC_CAPI_NETBIRD_END")
332:  systemctl restart privoxy
337:  code="$(curl -sk --proxy "http://${b}:${HTTP_PROXY_PORT}" --connect-timeout 12 --max-time 45 -o /tmp/771u_http_proxy_capi.body -w '%{http_code}' https://api.crowdsec.net/v3/watchers/login || true)"
338:  trace="$(curl -sk --proxy "http://${b}:${HTTP_PROXY_PORT}" --connect-timeout 12 --max-time 45 https://www.cloudflare.com/cdn-cgi/trace 2>/dev/null | grep -E 'ip=|colo=' | sed -n '1,6p' || true)"
339:  echo "HTTP_PROXY_CAPI_HTTP=$code"
346:register_capi() {
348:  proxy_url="http://${b}:${HTTP_PROXY_PORT}"
349:  echo "REGISTER_CAPI proxy=$proxy_url"
351:  force_no_capi_stable
352:  wait_lapi "BEFORE_CAPI_REGISTER" || return 10
356:  if test -f config/online_api_credentials.yaml; then
357:    mkdir -p /opt/stacks/crowdsec/manual-backups/771u-old-online-creds-"$TS"
358:    mv config/online_api_credentials.yaml /opt/stacks/crowdsec/manual-backups/771u-old-online-creds-"$TS"/online_api_credentials.yaml.before-register
363:  wait_lapi "REGISTER_MODE" || return 13
368:    if cscli capi register --help 2>&1 | grep -q -- "-y"; then
369:      timeout 240 cscli capi register -y >/tmp/771u_register.out 2>&1
371:      timeout 240 sh -c "yes | cscli capi register" >/tmp/771u_register.out 2>&1
384:  if ! test -f config/online_api_credentials.yaml; then
388:  stat -c 'ONLINE_CREDS path=%n mode=%a owner=%U group=%G size=%s' config/online_api_credentials.yaml || true
389:  awk -F: '/^[A-Za-z0-9_ -]+:/ {gsub(/^[ \t]+|[ \t]+$/, "", $1); print $1 ": REDACTED"}' config/online_api_credentials.yaml | sed -n '1,40p'
391:  grep -Eq '^[[:space:]]*login:' config/online_api_credentials.yaml || return 22
398:  echo "VALIDATE_CAPI"
402:    health="$(curl -sk --connect-timeout 3 --max-time 6 -o /tmp/771u_health2.html -w '%{http_code}' http://[PRIVATE_IP]:8088/health || true)"
403:    lapi_rc="$(docker exec crowdsec sh -lc 'cscli lapi status >/tmp/771u_lapi2.out 2>&1; echo LAPI_RC=$?' 2>/dev/null | awk -F= '/^LAPI_RC=/{print $2}' | tail -1 || true)"
405:    capi_rc="$(printf '%s\n' "$capi_out" | awk -F= '/^CAPI_RC=/{print $2}' | tail -1)"
406:    fatal="$(docker logs --since 60s crowdsec 2>&1 | grep -Eic 'fatal|TLS handshake timeout|unable to run local API|failed to get docker info|lookup socket-proxy|server misbehaving|mapping value is not allowed|missing credentials field|open /etc/crowdsec/online_api_credentials.yaml|proxyconnect tcp' || true)"
407:    envbad="$(docker inspect crowdsec --format '{{range .Config.Env}}{{println .}}{{end}}' 2>/dev/null | grep -E 'DISABLE_ONLINE_API|ARGS=.*no-capi|-no-capi' || true)"
408:    echo "VALIDATE_TRY=$n HEALTH=$health LAPI_RC=${lapi_rc:-NA} CAPI_RC=${capi_rc:-NA} FATAL=$fatal ENV_BAD=${envbad:-NONE}"
409:    printf '%s\n' "$capi_out"
410:    if test "$health" = "200" && test "${lapi_rc:-NA}" = "0" && test "${capi_rc:-NA}" = "0" && test "$fatal" = "0" && test -z "$envbad"; then
417:  rc_before="$(docker inspect crowdsec --format '{{.RestartCount}}' 2>/dev/null || echo NA)"
419:  rc_after="$(docker inspect crowdsec --format '{{.RestartCount}}' 2>/dev/null || echo NA)"
420:  health_after="$(curl -sk --connect-timeout 3 --max-time 6 -o /tmp/771u_health_after.html -w '%{http_code}' http://[PRIVATE_IP]:8088/health || true)"
421:  lapi_after="$(docker exec crowdsec sh -lc 'cscli lapi status >/tmp/771u_lapi_after.out 2>&1; echo LAPI_RC=$?' 2>/dev/null | awk -F= '/^LAPI_RC=/{print $2}' | tail -1 || true)"
422:  capi_after="$(docker exec crowdsec sh -lc 'cscli capi status >/tmp/771u_capi_after.out 2>&1; echo CAPI_RC=$?' 2>/dev/null | awk -F= '/^CAPI_RC=/{print $2}' | tail -1 || true)"
423:  fatal_after="$(docker logs --since 240s crowdsec 2>&1 | grep -Eic 'fatal|TLS handshake timeout|unable to run local API|failed to get docker info|lookup socket-proxy|server misbehaving|mapping value is not allowed|missing credentials field|open /etc/crowdsec/online_api_credentials.yaml|proxyconnect tcp' || true)"
424:  env_after="$(docker inspect crowdsec --format '{{range .Config.Env}}{{println .}}{{end}}' 2>/dev/null | grep -E 'DISABLE_ONLINE_API|ARGS=.*no-capi|-no-capi' || true)"
426:  echo "FINAL_STABILITY RC_BEFORE=$rc_before RC_AFTER=$rc_after HEALTH_AFTER=$health_after LAPI_AFTER=${lapi_after:-NA} CAPI_AFTER=${capi_after:-NA} FATAL_AFTER=$fatal_after ENV_BAD_AFTER=${env_after:-NONE}"
428:  test "$rc_before" = "$rc_after" && test "$health_after" = "200" && test "${lapi_after:-NA}" = "0" && test "${capi_after:-NA}" = "0" && test "$fatal_after" = "0" && test -z "$env_after"
432:echo "STEP=771U_EDGE_EGRESS_CAPI"
KNOWN_SCRIPT=/root/771v_deep_key_backup_netbird_capi.sh SHA256=92191ce6124981ee0468cc8f95c749c47bca5fc61f9aecaeedeef91cdd434170 EXECUTABLE=false
8:PROOF="/root/evidence/771V_DEEP_KEY_BACKUP_NETBIRD_CAPI_${TS}_PROOF.txt"
11:EDGE_LOCAL="/root/771v_edge_netbird_capi_${TS}.sh"
12:EDGE_REMOTE="/tmp/771v_edge_netbird_capi_${TS}.sh"
31:EGRESS_DIR=/etc/homelab-crowdsec-capi-netbird-egress
33:HEALTH_FILE="$HEALTH_DIR/crowdsec-capi.txt"
52:    echo "CHECK=crowdsec-capi"
58:force_no_capi_stable() {
64:      DISABLE_ONLINE_API: "true"
65:      ARGS: "-no-capi"
87:wait_lapi() {
89:  echo "WAIT_LAPI=$label"
92:    health="$(curl -sk --connect-timeout 3 --max-time 6 -o /tmp/771v_health.html -w '%{http_code}' http://[PRIVATE_IP]:8088/health || true)"
94:    rc="$(printf '%s\n' "$out" | awk -F= '/^LAPI_RC=/{print $2}' | tail -1)"
95:    fatal="$(docker logs --since 30s crowdsec 2>&1 | grep -Eic 'fatal|unable to run local API|failed to get docker info|lookup socket-proxy|server misbehaving|mapping value is not allowed' || true)"
96:    echo "LAPI_TRY=$n HEALTH=$health LAPI_RC=${rc:-NA} FATAL_COUNT_30S=$fatal"
168:    raise SystemExit("api.server block not found")
172:    "      credentials_path: /etc/crowdsec/online_api_credentials.yaml",
210:  grep -nE 'DISABLE_ONLINE_API|ARGS|GODEBUG|HTTP_PROXY|HTTPS_PROXY|NO_PROXY|socket-proxy|published:|target:' /tmp/771v_compose.yml || true
211:  ! grep -qE 'DISABLE_ONLINE_API|ARGS:.*no-capi|-no-capi' /tmp/771v_compose.yml
216:    ssh-keygen -q -t ed25519 -N "" -C "homelab-crowdsec-capi-netbird-egress-edge" -f "$SSH_KEY"
230:  timeout 15 ssh -n \
237:    "echo SSH_OK; hostname; curl -4 -sk --connect-timeout 8 --max-time 20 -o /tmp/771v_capi_direct.body -w 'DIRECT_CAPI_HTTP=%{http_code}\n' https://api.crowdsec.net/v3/watchers/login || true" >"$out" 2>&1
256:  cat >/etc/systemd/system/homelab-crowdsec-capi-netbird-egress.service <<'EOF'
258:Description=Homelab CrowdSec CAPI NetBird VPS SOCKS egress
265:EnvironmentFile=/etc/homelab-crowdsec-capi-netbird-egress/current.env
266:ExecStart=/bin/sh -lc 'exec /usr/bin/ssh -N -i "${SSH_KEY}" -D "${SOCKS_BIND}:${SOCKS_PORT}" -o IdentitiesOnly=yes -o BatchMode=yes -o ExitOnForwardFailure=yes -o ServerAliveInterval=30 -o ServerAliveCountMax=3 -o StrictHostKeyChecking=accept-new "${SSH_USER}@${SSH_HOST}"'
267:Restart=always
268:RestartSec=5
274:  cat >/usr/local/sbin/homelab-crowdsec-capi-egress-switch <<'EOF'
278:base=/etc/homelab-crowdsec-capi-netbird-egress
286:systemctl restart homelab-crowdsec-capi-netbird-egress.service
287:systemctl restart privoxy 2>/dev/null || true
289:systemctl --no-pager --full status homelab-crowdsec-capi-netbird-egress.service | sed -n '1,30p'
291:  chmod 755 /usr/local/sbin/homelab-crowdsec-capi-egress-switch
294:  systemctl enable --now homelab-crowdsec-capi-netbird-egress.service
295:  systemctl restart homelab-crowdsec-capi-netbird-egress.service
297:  systemctl is-active homelab-crowdsec-capi-netbird-egress.service || true
313:    if "HOMELAB_771" in line and "CROWDSEC_CAPI" in line and "BEGIN" in line:
316:    if "HOMELAB_771" in line and "CROWDSEC_CAPI" in line and "END" in line:
327:out.append("# HOMELAB_771V_CROWDSEC_CAPI_NETBIRD_BEGIN")
330:out.append("# HOMELAB_771V_CROWDSEC_CAPI_NETBIRD_END")
335:  systemctl restart privoxy
340:  code="$(curl -sk --proxy "http://${b}:${HTTP_PROXY_PORT}" --connect-timeout 12 --max-time 45 -o /tmp/771v_http_proxy_capi.body -w '%{http_code}' https://api.crowdsec.net/v3/watchers/login || true)"
341:  trace="$(curl -sk --proxy "http://${b}:${HTTP_PROXY_PORT}" --connect-timeout 12 --max-time 45 https://www.cloudflare.com/cdn-cgi/trace 2>/dev/null | grep -E 'ip=|colo=' | sed -n '1,6p' || true)"
342:  echo "HTTP_PROXY_CAPI_HTTP=$code"
349:register_capi() {
351:  proxy_url="http://${b}:${HTTP_PROXY_PORT}"
352:  echo "REGISTER_CAPI proxy=$proxy_url"
354:  force_no_capi_stable
355:  wait_lapi "BEFORE_CAPI_REGISTER" || return 10
359:  if test -f config/online_api_credentials.yaml; then
360:    mkdir -p /opt/stacks/crowdsec/manual-backups/771v-old-online-creds-"$TS"
361:    mv config/online_api_credentials.yaml /opt/stacks/crowdsec/manual-backups/771v-old-online-creds-"$TS"/online_api_credentials.yaml.before-register
366:  wait_lapi "REGISTER_MODE" || return 13
371:    if cscli capi register --help 2>&1 | grep -q -- "-y"; then
372:      timeout 240 cscli capi register -y >/tmp/771v_register.out 2>&1
374:      timeout 240 sh -c "yes | cscli capi register" >/tmp/771v_register.out 2>&1
387:  if ! test -f config/online_api_credentials.yaml; then
391:  stat -c 'ONLINE_CREDS path=%n mode=%a owner=%U group=%G size=%s' config/online_api_credentials.yaml || true
392:  awk -F: '/^[A-Za-z0-9_ -]+:/ {gsub(/^[ \t]+|[ \t]+$/, "", $1); print $1 ": REDACTED"}' config/online_api_credentials.yaml | sed -n '1,40p'
394:  grep -Eq '^[[:space:]]*login:' config/online_api_credentials.yaml || return 22
401:  echo "VALIDATE_CAPI"
405:    health="$(curl -sk --connect-timeout 3 --max-time 6 -o /tmp/771v_health2.html -w '%{http_code}' http://[PRIVATE_IP]:8088/health || true)"
406:    lapi_rc="$(docker exec crowdsec sh -lc 'cscli lapi status >/tmp/771v_lapi2.out 2>&1; echo LAPI_RC=$?' 2>/dev/null | awk -F= '/^LAPI_RC=/{print $2}' | tail -1 || true)"
408:    capi_rc="$(printf '%s\n' "$capi_out" | awk -F= '/^CAPI_RC=/{print $2}' | tail -1)"
409:    fatal="$(docker logs --since 60s crowdsec 2>&1 | grep -Eic 'fatal|TLS handshake timeout|unable to run local API|failed to get docker info|lookup socket-proxy|server misbehaving|mapping value is not allowed|missing credentials field|open /etc/crowdsec/online_api_credentials.yaml|proxyconnect tcp' || true)"
410:    envbad="$(docker inspect crowdsec --format '{{range .Config.Env}}{{println .}}{{end}}' 2>/dev/null | grep -E 'DISABLE_ONLINE_API|ARGS=.*no-capi|-no-capi' || true)"
411:    echo "VALIDATE_TRY=$n HEALTH=$health LAPI_RC=${lapi_rc:-NA} CAPI_RC=${capi_rc:-NA} FATAL=$fatal ENV_BAD=${envbad:-NONE}"
412:    printf '%s\n' "$capi_out"
413:    if test "$health" = "200" && test "${lapi_rc:-NA}" = "0" && test "${capi_rc:-NA}" = "0" && test "$fatal" = "0" && test -z "$envbad"; then
420:  rc_before="$(docker inspect crowdsec --format '{{.RestartCount}}' 2>/dev/null || echo NA)"
422:  rc_after="$(docker inspect crowdsec --format '{{.RestartCount}}' 2>/dev/null || echo NA)"
423:  health_after="$(curl -sk --connect-timeout 3 --max-time 6 -o /tmp/771v_health_after.html -w '%{http_code}' http://[PRIVATE_IP]:8088/health || true)"
424:  lapi_after="$(docker exec crowdsec sh -lc 'cscli lapi status >/tmp/771v_lapi_after.out 2>&1; echo LAPI_RC=$?' 2>/dev/null | awk -F= '/^LAPI_RC=/{print $2}' | tail -1 || true)"
425:  capi_after="$(docker exec crowdsec sh -lc 'cscli capi status >/tmp/771v_capi_after.out 2>&1; echo CAPI_RC=$?' 2>/dev/null | awk -F= '/^CAPI_RC=/{print $2}' | tail -1 || true)"
426:  fatal_after="$(docker logs --since 240s crowdsec 2>&1 | grep -Eic 'fatal|TLS handshake timeout|unable to run local API|failed to get docker info|lookup socket-proxy|server misbehaving|mapping value is not allowed|missing credentials field|open /etc/crowdsec/online_api_credentials.yaml|proxyconnect tcp' || true)"
427:  env_after="$(docker inspect crowdsec --format '{{range .Config.Env}}{{println .}}{{end}}' 2>/dev/null | grep -E 'DISABLE_ONLINE_API|ARGS=.*no-capi|-no-capi' || true)"
429:  echo "FINAL_STABILITY RC_BEFORE=$rc_before RC_AFTER=$rc_after HEALTH_AFTER=$health_after LAPI_AFTER=${lapi_after:-NA} CAPI_AFTER=${capi_after:-NA} FATAL_AFTER=$fatal_after ENV_BAD_AFTER=${env_after:-NONE}"
431:  test "$rc_before" = "$rc_after" && test "$health_after" = "200" && test "${lapi_after:-NA}" = "0" && test "${capi_after:-NA}" = "0" && test "$fatal_after" = "0" && test -z "$env_after"
435:echo "STEP=771V_EDGE_NETBIRD_EGRESS_CAPI"
KNOWN_SCRIPT=/root/771z_after_manual_netbird_egress_capi.sh SHA256=f198ed621fd726ed6f15c4a0dd49fad307befd01e7a58ebbda1ddc379f5b49ee EXECUTABLE=false
8:PROOF="/root/evidence/771Z_AFTER_MANUAL_NETBIRD_EGRESS_CAPI_${TS}_PROOF.txt"
14:  echo "STEP=771Z_AFTER_MANUAL_NETBIRD_EGRESS_CAPI"
17:  echo "RULE=VERIFY_RELAY_MAIL_EGRESS_AND_REGISTER_CROWDSEC_CAPI"
21:  ssh debian@$EDGE "sudo bash -s" <<'EDGE'
27:HEALTH=/var/lib/homelab-health/crowdsec-capi.txt
38:    echo "CHECK=crowdsec-capi"
44:wait_lapi() {
46:  echo "WAIT_LAPI=$label"
49:    health="$(curl -sk --connect-timeout 3 --max-time 6 -o /tmp/771z_health.html -w '%{http_code}' http://[PRIVATE_IP]:8088/health || true)"
51:    rc="$(printf '%s\n' "$out" | awk -F= '/^LAPI_RC=/{print $2}' | tail -1)"
52:    echo "LAPI_TRY=$n HEALTH=$health LAPI_RC=${rc:-NA}"
59:force_no_capi() {
65:      DISABLE_ONLINE_API: "true"
66:      ARGS: "-no-capi"
87:enable_capi_compose() {
112:  grep -nE 'DISABLE_ONLINE_API|ARGS|GODEBUG|socket-proxy|published:|target:' /tmp/771z_compose.yml || true
113:  ! grep -qE 'DISABLE_ONLINE_API|ARGS:.*no-capi|-no-capi' /tmp/771z_compose.yml
180:    raise SystemExit("api.server block not found")
183:    "      credentials_path: /etc/crowdsec/online_api_credentials.yaml",
194:echo "NETBIRD_RESTART"
195:systemctl restart netbird 2>/dev/null || true
199:netbird status 2>&1 | redact || true
202:netbird status --json >/tmp/771z_nb.json 2>/tmp/771z_nb.err || true
229:echo "CAPI_DIRECT_TEST_AFTER_MANUAL_NETBIRD"
230:capi_code="$(curl -4 -sk --http1.1 --connect-timeout 12 --max-time 45 -o /tmp/771z_capi.body -w '%{http_code}' https://api.crowdsec.net/v3/watchers/login || true)"
231:trace="$(curl -4 -sk --connect-timeout 12 --max-time 30 https://www.cloudflare.com/cdn-cgi/trace 2>/dev/null | grep -E 'ip=|colo=' | sed -n '1,6p' || true)"
232:echo "CAPI_DIRECT_HTTP=$capi_code"
237:if test "$capi_code" = "000"; then
238:  force_no_capi
239:  wait_lapi "CAPI_ROUTE_NOT_READY_SAFE" || true
240:  write_health "REVIEW_MANUAL_NETBIRD_EGRESS_NOT_READY" "After manual NetBird setup, edge still cannot reach api.crowdsec.net; CrowdSec remains LAPI-only no-capi"
241:  echo "EDGE_STATUS=REVIEW_MANUAL_NETBIRD_EGRESS_NOT_READY_CAPI_NOT_DONE"
246:echo "CAPI_ROUTE_READY_REGISTER_NOW"
248:mkdir -p "manual-backups/771z-$TS"
249:test -f config/config.yaml && cp -a config/config.yaml "manual-backups/771z-$TS/config.yaml.before" || true
250:test -f config/user.yaml && cp -a config/user.yaml "manual-backups/771z-$TS/user.yaml.before" || true
251:test -f config/online_api_credentials.yaml && mv config/online_api_credentials.yaml "manual-backups/771z-$TS/online_api_credentials.yaml.before" || true
254:enable_capi_compose || {
255:  force_no_capi
256:  wait_lapi "COMPOSE_FAIL_SAFE" || true
257:  write_health "REVIEW_CAPI_COMPOSE_ENABLE_FAILED" "Direct CAPI route works, but compose CAPI enable failed"
262:wait_lapi "REGISTER_MODE" || exit 73
266:  if cscli capi register --help 2>&1 | grep -q -- "-y"; then
267:    timeout 240 cscli capi register -y >/tmp/771z_register.out 2>&1
269:    timeout 240 sh -c "yes | cscli capi register" >/tmp/771z_register.out 2>&1
281:if test "${reg_rc:-NA}" != "0" || ! test -f config/online_api_credentials.yaml; then
282:  force_no_capi
283:  wait_lapi "REGISTER_FAIL_SAFE" || true
284:  write_health "REVIEW_CAPI_ROUTE_READY_BUT_REGISTER_FAILED" "Direct CAPI route works, but cscli capi register failed; restored no-capi"
285:  echo "EDGE_STATUS=REVIEW_CAPI_REGISTER_FAILED_NOT_DONE"
290:stat -c 'ONLINE_CREDS path=%n mode=%a owner=%U group=%G size=%s' config/online_api_credentials.yaml || true
291:awk -F: '/^[A-Za-z0-9_ -]+:/ {gsub(/^[ \t]+|[ \t]+$/, "", $1); print $1 ": REDACTED"}' config/online_api_credentials.yaml | sed -n '1,40p'
294:enable_capi_compose || exit 75
300:  health="$(curl -sk --connect-timeout 3 --max-time 6 -o /tmp/771z_health2.html -w '%{http_code}' http://[PRIVATE_IP]:8088/health || true)"
301:  lapi_rc="$(docker exec crowdsec sh -lc 'cscli lapi status >/tmp/771z_lapi2.out 2>&1; echo LAPI_RC=$?' 2>/dev/null | awk -F= '/^LAPI_RC=/{print $2}' | tail -1 || true)"
303:  capi_rc="$(printf '%s\n' "$capi_out" | awk -F= '/^CAPI_RC=/{print $2}' | tail -1)"
304:  fatal="$(docker logs --since 60s crowdsec 2>&1 | grep -Eic 'fatal|TLS handshake timeout|unable to run local API|failed to get docker info|lookup socket-proxy|server misbehaving|mapping value is not allowed|missing credentials field|open /etc/crowdsec/online_api_credentials.yaml' || true)"
305:  envbad="$(docker inspect crowdsec --format '{{range .Config.Env}}{{println .}}{{end}}' 2>/dev/null | grep -E 'DISABLE_ONLINE_API|ARGS=.*no-capi|-no-capi' || true)"
306:  echo "VALIDATE_TRY=$n HEALTH=$health LAPI_RC=${lapi_rc:-NA} CAPI_RC=${capi_rc:-NA} FATAL=$fatal ENV_BAD=${envbad:-NONE}"
307:  printf '%s\n' "$capi_out"
308:  if test "$health" = "200" && test "${lapi_rc:-NA}" = "0" && test "${capi_rc:-NA}" = "0" && test "$fatal" = "0" && test -z "$envbad"; then
315:  write_health "OK_CAPI_REGISTERED_ENABLED_STABLE_MANUAL_NETBIRD_EGRESS" "CrowdSec CAPI registered and stable after manual NetBird egress via relay/mail"
316:  echo "EDGE_STATUS=OK_CROWDSEC_CAPI_100_PERCENT_REGISTERED_ENABLED_STABLE"
321:force_no_capi
322:wait_lapi "VALIDATION_FAIL_SAFE" || true
323:write_health "REVIEW_CAPI_REGISTERED_BUT_NOT_STABLE_RESTORED_NO_CAPI" "CAPI registration happened but stability validation failed; restored no-capi"
324:echo "EDGE_STATUS=REVIEW_CAPI_NOT_STABLE_RESTORED_NO_CAPI"
331:    code=$(curl -sk --connect-timeout 8 --max-time 20 --resolve "$h:443:$EDGE" -o "/tmp/771z_$h.html" -w "%{http_code}" "https://$h/" || true)
337:  echo STATUS=OK_771Z_AFTER_MANUAL_NETBIRD_EGRESS_CAPI_DONE
KNOWN_771_SAFE_STATIC_END=1
POLICY_DOCS_BEGIN=1
POLICY_DOC=/root/_2/workers2-cr0108-final-of79_umj/repo/kb/private/archive/2026-08-19/docs/22_MOLDOVA_HEALTHCHECK_GOTIFY_2026-08-18.md SHA256=fe0f5ca63837626583d150e8c4b9ce9c795832ae4f59af25369a00fa7825fdb5
1:# MOLDOVA HEALTHCHECK V3 / GOTIFY NOTIFIER — CURRENT RECORD
9:NetBird:
14:Old checker referenced retired Mailcow/old NetBird IP and caused false failures.
16:Current:
17:`/usr/local/sbin/pvepro-relay-healthcheck`
27:- new NetBird TCP 80/443
37:`PASS_RELAY_HEALTHCHECK_OK`
40:enabled/active.
48:Old USA observer had been converted to Gotify-only before retirement.
50:Moldova direct public DNS for `gotify.gram1.ru` is not relied upon.
78:`/etc/systemd/system/pvepro-relay-healthcheck.service.d/20-gotify-notifier.conf`
86:- timer active
89:Rollback backup:
92:Old USA observer then:
93:- backup created
95:- service inactive
96:- 80-second freeze proved no further health-file updates
98:- old NetBird server still stopped
99:- old host NetBird client still connected
100:- Moldova peer reachable
102:Old observer backup:
103:`/root/retired-homelab-dr-observer-20260818T221046Z`
POLICY_DOC=/root/_2/workers2-cr0108-final-of79_umj/repo/kb/private/archive/2026-08-19/docs/20_NETBIRD_USA_MIGRATION_2026-08-18.md SHA256=12fe079849346352315aac76fae82d00cbd17f88a3553270ca2c5f2749840552
1:# NETBIRD USA MIGRATION — FINAL CURRENT RECORD
5:Old USA mail/NetBird VPS:
7:- secondary NetBird IPv4 `[PRIVATE_IP]`
10:Old NetBird server stack stopped after successful migration.
11:Host-level NetBird client left running for rollback/peer observation.
33:NetBird:
36:Compose bind changed only from old NetBird secondary public IP to new `[PRIVATE_IP]`.
56:- Moldova synthetic check passes
59:Important health discovery:
60:- `/api/health` 404 on exact deployed version
61:- `:9000/health` 503 in combined relay/server mode
62:- first rollback was triggered by incorrectly assuming this endpoint must be healthy
65:Backups on new server include migration/cutover snapshots such as:
66:`/root/netbird-cutover-20260818T145807Z`
69:- upgrade NetBird
POLICY_DOC=/root/_2/workers2-cr0108-final-of79_umj/repo/kb/private/archive/2026-08-19/docs/15_CRITICAL_KEEP_RETIRE_DECISIONS.md SHA256=ad3ea70345063e8a13608a83acb4d6a1118533eb6acab22929e0bf1ac20c06af
1:# CRITICAL KEEP / RETIRE DECISIONS
3:This is a convenience matrix distilled from the historical handbook plus current state. A RETIRE label is not authorization to delete without fresh proof.
11:| VM9130 edge-cold-standby | KEEP UNTIL DR PROOF | do not delete before timed VM130 restore |
12:| VM150 Snikket | KEEP/CLOSED | do not reopen destructive rebuild without new defect |
16:| VM180 cluster-admin | historical future RETIRE candidate | only after dependency/backup/monitoring cleanup |
18:| CT200 skladchik-mod | historical future RETIRE candidate | preserve required data/monitoring first |
19:| public edge01 | KEEP/CRITICAL | current git-read V3 and public edge duties |
20:| Moldova relay | KEEP | independent relay/external health |
21:| USA mail/NetBird | KEEP | infra mail/monitoring/no-PII |
24:| pve01 18788 | KEEP NOW | reader-v3, usage proof before retirement |
27:| Cloud.ru prepared bucket | KEEP PREPARED | real backup workload not yet active |
POLICY_DOC=/root/_2/workers2-cr0108-final-of79_umj/FINAL_HANDOFF/repo/kb/private/archive/2026-08-19/docs/22_MOLDOVA_HEALTHCHECK_GOTIFY_2026-08-18.md SHA256=fe0f5ca63837626583d150e8c4b9ce9c795832ae4f59af25369a00fa7825fdb5
1:# MOLDOVA HEALTHCHECK V3 / GOTIFY NOTIFIER — CURRENT RECORD
9:NetBird:
14:Old checker referenced retired Mailcow/old NetBird IP and caused false failures.
16:Current:
17:`/usr/local/sbin/pvepro-relay-healthcheck`
27:- new NetBird TCP 80/443
37:`PASS_RELAY_HEALTHCHECK_OK`
40:enabled/active.
48:Old USA observer had been converted to Gotify-only before retirement.
50:Moldova direct public DNS for `gotify.gram1.ru` is not relied upon.
78:`/etc/systemd/system/pvepro-relay-healthcheck.service.d/20-gotify-notifier.conf`
86:- timer active
89:Rollback backup:
92:Old USA observer then:
93:- backup created
95:- service inactive
96:- 80-second freeze proved no further health-file updates
98:- old NetBird server still stopped
99:- old host NetBird client still connected
100:- Moldova peer reachable
102:Old observer backup:
103:`/root/retired-homelab-dr-observer-20260818T221046Z`
POLICY_DOC=/root/_2/workers2-cr0108-final-of79_umj/FINAL_HANDOFF/repo/kb/private/archive/2026-08-19/docs/20_NETBIRD_USA_MIGRATION_2026-08-18.md SHA256=12fe079849346352315aac76fae82d00cbd17f88a3553270ca2c5f2749840552
1:# NETBIRD USA MIGRATION — FINAL CURRENT RECORD
5:Old USA mail/NetBird VPS:
7:- secondary NetBird IPv4 `[PRIVATE_IP]`
10:Old NetBird server stack stopped after successful migration.
11:Host-level NetBird client left running for rollback/peer observation.
33:NetBird:
36:Compose bind changed only from old NetBird secondary public IP to new `[PRIVATE_IP]`.
56:- Moldova synthetic check passes
59:Important health discovery:
60:- `/api/health` 404 on exact deployed version
61:- `:9000/health` 503 in combined relay/server mode
62:- first rollback was triggered by incorrectly assuming this endpoint must be healthy
65:Backups on new server include migration/cutover snapshots such as:
66:`/root/netbird-cutover-20260818T145807Z`
69:- upgrade NetBird
POLICY_DOC=/root/_2/workers2-cr0108-final-of79_umj/FINAL_HANDOFF/repo/kb/private/archive/2026-08-19/docs/15_CRITICAL_KEEP_RETIRE_DECISIONS.md SHA256=ad3ea70345063e8a13608a83acb4d6a1118533eb6acab22929e0bf1ac20c06af
1:# CRITICAL KEEP / RETIRE DECISIONS
3:This is a convenience matrix distilled from the historical handbook plus current state. A RETIRE label is not authorization to delete without fresh proof.
11:| VM9130 edge-cold-standby | KEEP UNTIL DR PROOF | do not delete before timed VM130 restore |
12:| VM150 Snikket | KEEP/CLOSED | do not reopen destructive rebuild without new defect |
16:| VM180 cluster-admin | historical future RETIRE candidate | only after dependency/backup/monitoring cleanup |
18:| CT200 skladchik-mod | historical future RETIRE candidate | preserve required data/monitoring first |
19:| public edge01 | KEEP/CRITICAL | current git-read V3 and public edge duties |
20:| Moldova relay | KEEP | independent relay/external health |
21:| USA mail/NetBird | KEEP | infra mail/monitoring/no-PII |
24:| pve01 18788 | KEEP NOW | reader-v3, usage proof before retirement |
27:| Cloud.ru prepared bucket | KEEP PREPARED | real backup workload not yet active |
POLICY_DOCS_END=1
CONTROL_UNIT_REFERENCES_BEGIN=1
CONTROL_UNIT_REFERENCES_END=1
DECISION=PASS_BACKUP_1123_NO_EXTERNAL_PROVIDER_CONTROL_PATH_PROVEN
NEXT_GATE=RETIRE_US_NETBIRD_TARGET_FROM_ACTIVE_BACKUPV2_POLICY_THEN_COMBINED_REPAIR
TASK_RESULT=PASS_HOMELAB_BACKUP_MOLDOVA_CONTROL_RCA
CHANGES_MADE_BY_1123=false
PRODUCT_MUTATION_BY_1123=false
VM_MUTATION_BY_1123=false
CLOUD_MUTATION_BY_1123=false
HOMELAB_RESULT_CONTRACT={"version":1,"command_id":"SUPPORT-260922-HOMELAB-BACKUP-MOLDOVA-CONTROL-RCA-1123R1","status":"OK","changes_made":false,"rollback_started":false,"rollback_restored":null}
WORKERS2_BACKUP_MOLDOVA_CONTROL_RCA_END=1

OUTPUT_END
CHAT_OUTPUT_END
