# PowerShell counterpart to validate-config.sh # Run this in a PowerShell session; it will perform the same checks. param( [string]$BaselineFile = "docker-compose.lock.yml" ) function Assert-Error($msg) { Write-Error $msg exit 1 } if (Get-Command docker -ErrorAction SilentlyContinue) { Write-Host "[validate-config] generating normalized compose manifest" docker compose config | Set-Content -Path generated.yml -Encoding utf8 if (Test-Path $BaselineFile) { Write-Host "[validate-config] comparing against baseline $BaselineFile" $diff = Compare-Object -ReferenceObject (Get-Content $BaselineFile) -DifferenceObject (Get-Content generated.yml) -SyncWindow 0 if ($diff) { Write-Host "[validate-config] configuration drift detected!" Assert-Error "Please review and, if the change is intentional, update $BaselineFile." } Write-Host "[validate-config] docker-compose.yml matches baseline" } else { Write-Host "[validate-config] baseline file not found, creating $BaselineFile" Copy-Item generated.yml $BaselineFile Write-Host "[validate-config] please commit $BaselineFile to the repository" } } else { Write-Host "[validate-config] docker binary not found; skipping compose validation" } # CoreDNS check if (Get-Command coredns -ErrorAction SilentlyContinue) { Write-Host "[validate-config] checking PopuraDNS/Corefile with local coredns" coredns -conf PopuraDNS/Corefile -dns.port=0 $canCheckCorefile = $true } elseif (Get-Command docker -ErrorAction SilentlyContinue) { Write-Host "[validate-config] checking PopuraDNS/Corefile with container" docker run --rm -v "${PWD}/PopuraDNS/Corefile:/etc/coredns/Corefile:ro" ` coredns/coredns:latest -conf /etc/coredns/Corefile -dns.port=0 $canCheckCorefile = $true } else { Write-Host "[validate-config] cannot check Corefile syntax (no coredns or docker)" $canCheckCorefile = $false } # ensure onion and i2p zones are present in Corefile if ($canCheckCorefile) { foreach ($zone in @('onion.:53','i2p.:53','eth.:53','bit.:53','alt.:53','loki.:53','zil.:53','web3.:53','exit.:53','onion4.:53','onion6.:53')) { if (-not (Select-String -Path PopuraDNS/Corefile -Pattern $zone -Quiet)) { Assert-Error "[validate-config] error: Corefile missing $zone block" } } } # verify i2pd DNS server is enabled in its config if (Select-String -Path 'i2pd_yggdrasil_docker/src/i2pd.conf' -Pattern '\[dns\]' -Quiet) { $dnsSection = Select-String -Path 'i2pd_yggdrasil_docker/src/i2pd.conf' -Pattern 'enabled' -Context 0,1 | Where-Object { $_.Line -match 'true' } if (-not $dnsSection) { Write-Host "[validate-config] warning: i2pd DNS section present but not enabled" } } else { Write-Host "[validate-config] warning: i2pd.conf missing [dns] section" } # tor config should contain DNSPort if (-not (Select-String -Path 'tor_yggdrasil_docker/torrc' -Pattern '^DNSPort' -Quiet)) { Write-Host "[validate-config] warning: torrc does not specify DNSPort; onion DNS will not work" } # optional live DNS smoke queries (requires dig) if (Get-Command dig -ErrorAction SilentlyContinue) { Write-Host "[validate-config] performing live DNS query for .onion via CoreDNS" $res = dig @10.5.0.4 -p 53 facebookcorewwwi.onion +short if ($LASTEXITCODE -ne 0) { Assert-Error "[validate-config] onion query failed" } Write-Host "[validate-config] performing live DNS query for .i2p via CoreDNS" $res = dig @10.5.0.4 -p 53 stats.i2p +short if ($LASTEXITCODE -ne 0) { Assert-Error "[validate-config] i2p query failed" } } # ensure referenced secrets exist foreach ($s in @("./secrets/tz.txt", "./secrets/YGGDRASIL_GENERATE_KEYS.txt")) { if (-not (Test-Path $s)) { Assert-Error "[validate-config] error: secret file $s is missing" } } # check for :latest tags if (Select-String -Path docker-compose.yml -Pattern 'image: .*:latest' -Quiet) { Write-Host "[validate-config] warning: some services use the ':latest' image tag;" ` "pin to a specific version before deploying to production." } # warn if no healthchecks defined if (-not (Select-String -Path docker-compose.yml -Pattern 'healthcheck:' -Quiet)) { Write-Host "[validate-config] warning: no healthcheck definitions found in docker-compose.yml" } Write-Host "[validate-config] warning: some services use the ':latest' image tag;" ` "pin to a specific version before deploying to production." } # verify restart policies exist if (-not (Select-String -Path docker-compose.yml -Pattern 'restart:' -Quiet)) { Write-Host "[validate-config] warning: some services lack a restart policy." } # detect duplicate host ports $ports = Select-String -Path docker-compose.yml -Pattern ':[0-9]+:' -AllMatches | ForEach-Object { $_.Matches } | ForEach-Object { $_.Value.Trim(':') } | Sort-Object $dups = $ports | Group-Object | Where-Object { $_.Count -gt 1 } | Select-Object -ExpandProperty Name if ($dups) { Write-Host "[validate-config] warning: duplicate host port mappings detected: $($dups -join ' ')" } # unbound configuration syntax check if (Get-Command unbound-checkconf -ErrorAction SilentlyContinue) { Write-Host "[validate-config] checking unbound configuration locally" unbound-checkconf -c unbound/unbound.conf } elseif (Get-Command docker -ErrorAction SilentlyContinue) { Write-Host "[validate-config] checking unbound configuration in container" docker run --rm -v "${PWD}/unbound/unbound.conf:/etc/unbound/unbound.conf:ro" ` mvance/unbound:latest unbound-checkconf -c /etc/unbound/unbound.conf } else { Write-Host "[validate-config] cannot check unbound config (no unbound-checkconf or docker)" } # basic 3proxy config sanity foreach ($cfg in @('3proxy/first-instanse.cfg','3proxy/second-instanse.cfg')) { if (-not (Test-Path $cfg)) { Assert-Error "[validate-config] error: missing 3proxy config $cfg" } if (-not (Select-String -Path $cfg -Pattern 'socks|proxy' -Quiet)) { Write-Host "[validate-config] warning: $cfg does not contain socks/proxy directives" } } # simple sanity checks if (Select-String -Path docker-compose.yml -Pattern 'container_name: darkproxy' -Quiet) { Write-Host "[validate-config] warning: 'container_name: darkproxy' appears in compose; this may" ` "conflict with network or project name." } if (Select-String -Path docker-compose.yml -Pattern 'PIHOLE_DNS_' -Quiet) { if (Select-String -Path docker-compose.yml -Pattern 'PIHOLE_DNS_:' -Quiet) { Write-Host "[validate-config] warning: PIHOLE_DNS_ variable ends with underscore;" ` "consider using PIHOLE_DNS_1, PIHOLE_DNS_2 etc." } } Write-Host "[validate-config] all validations passed"