Compare commits
24 Commits
dcad276c59
...
v1.0.1
| Author | SHA1 | Date | |
|---|---|---|---|
| 4e2264d5db | |||
| 82a6221880 | |||
| 6ec1faf3e6 | |||
| d3beee602d | |||
| 29960e9937 | |||
| 417456485a | |||
| 0945092dde | |||
| 6f12117521 | |||
| 8bf8814fa7 | |||
| d90b5b091b | |||
| 4275ac1d2f | |||
| 07b36d62d2 | |||
| 5fb8279d61 | |||
| 6eb63d3f85 | |||
| 2702854513 | |||
| 106537cc63 | |||
| dabb96e1b3 | |||
| 2b5a154b99 | |||
| e475b0f47d | |||
| 8f81f8f1e2 | |||
| cd753a7e28 | |||
| 7ac1985508 | |||
| 0ecf2eb651 | |||
| 18c7095aaf |
@@ -10,6 +10,14 @@
|
|||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div align="center">
|
||||||
|
|
||||||
|
<img src="assets/desktop-screenshot.png" alt="Sovran_SystemsOS desktop showing application dock and PRIVACY. SOVEREIGNTY. BITCOIN. tagline" width="800" />
|
||||||
|
|
||||||
|
*The Sovran_SystemsOS desktop — "Privacy. Sovereignty. Bitcoin."*
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Table of Contents
|
## Table of Contents
|
||||||
|
|||||||
@@ -281,9 +281,6 @@ FEATURE_SERVICE_MAP = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
# Port requirements for service tiles (keyed by unit name or icon)
|
# Port requirements for service tiles (keyed by unit name or icon)
|
||||||
_PORTS_MATRIX_FEDERATION = [
|
|
||||||
{"port": "8448", "protocol": "TCP", "description": "Matrix server-to-server federation"},
|
|
||||||
]
|
|
||||||
_PORTS_ELEMENT_CALLING = [
|
_PORTS_ELEMENT_CALLING = [
|
||||||
{"port": "7881", "protocol": "TCP", "description": "LiveKit WebRTC signalling"},
|
{"port": "7881", "protocol": "TCP", "description": "LiveKit WebRTC signalling"},
|
||||||
{"port": "7882", "protocol": "UDP", "description": "LiveKit media (UDP mux)"},
|
{"port": "7882", "protocol": "UDP", "description": "LiveKit media (UDP mux)"},
|
||||||
@@ -296,7 +293,7 @@ SERVICE_PORT_REQUIREMENTS: dict[str, list[dict]] = {
|
|||||||
# Infrastructure
|
# Infrastructure
|
||||||
"caddy.service": [],
|
"caddy.service": [],
|
||||||
# Communication
|
# Communication
|
||||||
"matrix-synapse.service": _PORTS_MATRIX_FEDERATION,
|
"matrix-synapse.service": [],
|
||||||
"livekit.service": _PORTS_ELEMENT_CALLING,
|
"livekit.service": _PORTS_ELEMENT_CALLING,
|
||||||
# Domain-based apps (80/443 handled by end-to-end domain reachability checks)
|
# Domain-based apps (80/443 handled by end-to-end domain reachability checks)
|
||||||
"btcpayserver.service": [],
|
"btcpayserver.service": [],
|
||||||
@@ -2256,6 +2253,13 @@ _btcd_version_cache: tuple[float, str | None] = (0.0, None)
|
|||||||
# Cache for ``bitcoin-cli getdeploymentinfo`` output (BIP-110 live status)
|
# Cache for ``bitcoin-cli getdeploymentinfo`` output (BIP-110 live status)
|
||||||
_btc_deployment_cache: tuple[float, dict | None] = (0.0, None)
|
_btc_deployment_cache: tuple[float, dict | None] = (0.0, None)
|
||||||
|
|
||||||
|
# Bitcoin Knots exposes BIP-110 as the `reduced_data` versionbits deployment
|
||||||
|
# (RDTS, bit 4) in getdeploymentinfo. See Knots src/deploymentinfo.cpp,
|
||||||
|
# src/kernel/chainparams.cpp, and doc/bips.md.
|
||||||
|
BIP110_DEPLOYMENT_NAMES = {"reduced_data", "rdts", "bip110", "uasf-bip110"}
|
||||||
|
BIP110_VERSIONBITS_BIT = 4
|
||||||
|
BIP110_SUBVERSION_MARKERS = {"bip110", "uasf-bip110", "reduced_data", "rdts"}
|
||||||
|
|
||||||
|
|
||||||
# ── Generic service version detection (NixOS store path) ─────────
|
# ── Generic service version detection (NixOS store path) ─────────
|
||||||
|
|
||||||
@@ -2414,35 +2418,61 @@ def _get_bip110_status() -> dict:
|
|||||||
|
|
||||||
Resolution order (authoritative → fallback → honest unknown):
|
Resolution order (authoritative → fallback → honest unknown):
|
||||||
|
|
||||||
1. ``getdeploymentinfo`` (authoritative) — scan the ``deployments`` dict for an
|
1. ``getdeploymentinfo`` (authoritative) — scan ``deployments`` for BIP-110.
|
||||||
entry whose key (case-insensitive) contains "bip110". The exact
|
Bitcoin Knots currently exposes BIP-110 as ``reduced_data`` (RDTS, bit 4;
|
||||||
deployment key name is **not** hard-coded because it may vary across Knots
|
see Knots deploymentinfo.cpp / chainparams.cpp / doc/bips.md), so matching
|
||||||
releases; detection is intentionally generic so that a name change degrades
|
first uses known deployment names, then falls back to versionbits bit 4.
|
||||||
to "unknown" rather than producing a false result.
|
|
||||||
|
|
||||||
2. Subversion fallback — if getdeploymentinfo is unavailable or yields no
|
2. Subversion fallback — if getdeploymentinfo is unavailable or yields no
|
||||||
recognisable BIP-110 entry, inspect the ``subversion`` field from
|
recognisable BIP-110 entry, inspect the ``subversion`` field from
|
||||||
``getnetworkinfo``. A case-insensitive match for "bip110" or "uasf-bip110"
|
``getnetworkinfo``. A case-insensitive match for known BIP-110 markers
|
||||||
in the subversion string is treated as "signaling".
|
(including "bip110", "uasf-bip110", "reduced_data", "rdts") is treated as
|
||||||
|
"signaling".
|
||||||
|
|
||||||
3. Unknown — if the node is entirely unreachable or neither source is
|
3. Unknown — if the node is entirely unreachable or neither source is
|
||||||
conclusive, return state="unknown", signaling=False, source="none".
|
conclusive, return state="unknown", signaling=False, source="none".
|
||||||
"""
|
"""
|
||||||
_unknown: dict = {"supported": False, "signaling": False, "state": "unknown", "source": "none"}
|
_unknown: dict = {"supported": False, "signaling": False, "state": "unknown", "source": "none"}
|
||||||
|
|
||||||
|
def _deployment_bit(entry: dict) -> int | None:
|
||||||
|
bip9 = entry.get("bip9", {}) or {}
|
||||||
|
bip8 = entry.get("bip8", {}) or {}
|
||||||
|
bit = bip9.get("bit")
|
||||||
|
if bit is None:
|
||||||
|
bit = bip8.get("bit")
|
||||||
|
if bit is None:
|
||||||
|
bit = entry.get("bit")
|
||||||
|
return bit
|
||||||
|
|
||||||
# ── 1. getdeploymentinfo (authoritative) ──────────────────────────
|
# ── 1. getdeploymentinfo (authoritative) ──────────────────────────
|
||||||
deploy_info = _get_bitcoin_deployment_info()
|
deploy_info = _get_bitcoin_deployment_info()
|
||||||
if deploy_info is not None:
|
if deploy_info is not None:
|
||||||
deployments = deploy_info.get("deployments", {})
|
deployments = deploy_info.get("deployments", {})
|
||||||
if isinstance(deployments, dict):
|
if isinstance(deployments, dict):
|
||||||
|
matched_entry: dict | None = None
|
||||||
|
|
||||||
|
# Primary match: known deployment names (case-insensitive exact match)
|
||||||
for key, entry in deployments.items():
|
for key, entry in deployments.items():
|
||||||
# Generic scan: match key that contains "bip110" (case-insensitive).
|
|
||||||
# Deliberately not matching bare "110" to avoid false positives on
|
|
||||||
# unrelated deployments whose names happen to include that digit sequence.
|
|
||||||
if "bip110" not in key.lower():
|
|
||||||
continue
|
|
||||||
if not isinstance(entry, dict):
|
if not isinstance(entry, dict):
|
||||||
continue
|
continue
|
||||||
|
key_lower = key.lower()
|
||||||
|
if key_lower not in BIP110_DEPLOYMENT_NAMES:
|
||||||
|
continue
|
||||||
|
matched_entry = entry
|
||||||
|
break
|
||||||
|
|
||||||
|
# Secondary match: versionbits bit (fallback only)
|
||||||
|
if matched_entry is None:
|
||||||
|
for _, entry in deployments.items():
|
||||||
|
if not isinstance(entry, dict):
|
||||||
|
continue
|
||||||
|
if _deployment_bit(entry) != BIP110_VERSIONBITS_BIT:
|
||||||
|
continue
|
||||||
|
matched_entry = entry
|
||||||
|
break
|
||||||
|
|
||||||
|
if matched_entry is not None:
|
||||||
|
entry = matched_entry
|
||||||
|
|
||||||
# bip9 / bip8 status field
|
# bip9 / bip8 status field
|
||||||
bip9 = entry.get("bip9", {}) or {}
|
bip9 = entry.get("bip9", {}) or {}
|
||||||
@@ -2460,9 +2490,16 @@ def _get_bip110_status() -> dict:
|
|||||||
if status == "locked_in":
|
if status == "locked_in":
|
||||||
return {"supported": True, "signaling": True, "state": "locked_in", "source": "getdeploymentinfo"}
|
return {"supported": True, "signaling": True, "state": "locked_in", "source": "getdeploymentinfo"}
|
||||||
if status in ("started", "defined"):
|
if status in ("started", "defined"):
|
||||||
# Check whether the node is currently signaling this period
|
# Check whether deployment is currently signaling in this period.
|
||||||
stats = bip9.get("statistics") or bip8.get("statistics") or {}
|
stats = bip9.get("statistics") or bip8.get("statistics") or {}
|
||||||
signaling = bool(stats.get("signaling", False))
|
# Some Knots outputs expose only ``count`` (not explicit signaling bool),
|
||||||
|
# so treat count>0 as a conservative signaling indicator for this period.
|
||||||
|
count = stats.get("count")
|
||||||
|
signaling = bool(
|
||||||
|
stats.get("signaling")
|
||||||
|
or stats.get("signalling")
|
||||||
|
or (isinstance(count, int) and count > 0)
|
||||||
|
)
|
||||||
if signaling:
|
if signaling:
|
||||||
return {"supported": True, "signaling": True, "state": "signaling", "source": "getdeploymentinfo"}
|
return {"supported": True, "signaling": True, "state": "signaling", "source": "getdeploymentinfo"}
|
||||||
return {"supported": True, "signaling": False, "state": "not_signaling", "source": "getdeploymentinfo"}
|
return {"supported": True, "signaling": False, "state": "not_signaling", "source": "getdeploymentinfo"}
|
||||||
@@ -2476,7 +2513,7 @@ def _get_bip110_status() -> dict:
|
|||||||
if net_info is not None:
|
if net_info is not None:
|
||||||
subversion = net_info.get("subversion", "") or ""
|
subversion = net_info.get("subversion", "") or ""
|
||||||
sv_lower = subversion.lower()
|
sv_lower = subversion.lower()
|
||||||
if "bip110" in sv_lower or "uasf-bip110" in sv_lower:
|
if any(marker in sv_lower for marker in BIP110_SUBVERSION_MARKERS):
|
||||||
return {"supported": True, "signaling": True, "state": "signaling", "source": "subversion"}
|
return {"supported": True, "signaling": True, "state": "signaling", "source": "subversion"}
|
||||||
# Node is reachable via RPC but no BIP-110 marker found anywhere
|
# Node is reachable via RPC but no BIP-110 marker found anywhere
|
||||||
return {"supported": False, "signaling": False, "state": "unsupported", "source": "subversion"}
|
return {"supported": False, "signaling": False, "state": "unsupported", "source": "subversion"}
|
||||||
@@ -2943,28 +2980,16 @@ async def api_service_detail(unit: str, icon: str | None = None):
|
|||||||
"status": ps,
|
"status": ps,
|
||||||
"description": p.get("description", ""),
|
"description": p.get("description", ""),
|
||||||
})
|
})
|
||||||
extra_ports = port_statuses if unit in ("matrix-synapse.service", "livekit.service") else []
|
extra_ports = port_statuses if unit == "livekit.service" else []
|
||||||
|
|
||||||
if needs_domain and unit in ("matrix-synapse.service", "livekit.service"):
|
if needs_domain and unit == "livekit.service":
|
||||||
if has_domain_issues:
|
if has_domain_issues:
|
||||||
domain_check_steps.append({
|
domain_check_steps.append({
|
||||||
"step": 4,
|
"step": 4,
|
||||||
"label": "Federation Port" if unit == "matrix-synapse.service" else "Additional Ports Required",
|
"label": "Additional Ports Required",
|
||||||
"status": "skipped",
|
"status": "skipped",
|
||||||
"detail": "Skipped until Steps 1-3 are complete",
|
"detail": "Skipped until Steps 1-3 are complete",
|
||||||
})
|
})
|
||||||
elif unit == "matrix-synapse.service":
|
|
||||||
if extra_ports:
|
|
||||||
matrix_open = extra_ports[0]["status"] != "closed"
|
|
||||||
domain_check_steps.append({
|
|
||||||
"step": 4,
|
|
||||||
"label": "Federation Port",
|
|
||||||
"status": "ok" if matrix_open else "error",
|
|
||||||
"detail": (
|
|
||||||
f"Matrix federation port 8448 (TCP) is {'open' if matrix_open else 'closed'}.\n"
|
|
||||||
f"Matrix federation requires port 8448 (TCP) forwarded to {internal_ip}"
|
|
||||||
),
|
|
||||||
})
|
|
||||||
else:
|
else:
|
||||||
extra_open = all(p["status"] != "closed" for p in extra_ports)
|
extra_open = all(p["status"] != "closed" for p in extra_ports)
|
||||||
domain_check_steps.append({
|
domain_check_steps.append({
|
||||||
|
|||||||
@@ -67,10 +67,10 @@ async function apiFetch(path, options) {
|
|||||||
// Keys match the "state" values returned by /api/bitcoin/bip110.
|
// Keys match the "state" values returned by /api/bitcoin/bip110.
|
||||||
|
|
||||||
var BIP110_BADGE_CONFIG = {
|
var BIP110_BADGE_CONFIG = {
|
||||||
active: { cls: 'tile-bip110-badge--active', label: 'BIP\u2011110: Active \u2713', title: 'BIP-110 is active on this node' },
|
active: { cls: 'tile-bip110-badge--active', label: 'Active', title: 'BIP-110 is active on this node' },
|
||||||
locked_in: { cls: 'tile-bip110-badge--locked_in', label: 'BIP\u2011110: Locked In', title: 'BIP-110 is locked in and will activate shortly' },
|
locked_in: { cls: 'tile-bip110-badge--locked_in', label: 'Locked In', title: 'BIP-110 is locked in and will activate shortly' },
|
||||||
signaling: { cls: 'tile-bip110-badge--signaling', label: 'BIP\u2011110: Signaling', title: 'Node is signaling readiness for BIP-110' },
|
signaling: { cls: 'tile-bip110-badge--signaling', label: 'Signaling', title: 'Node is signaling readiness for BIP-110' },
|
||||||
not_signaling: { cls: 'tile-bip110-badge--not_signaling',label: 'BIP\u2011110: Not Signaling', title: 'Node supports BIP-110 but is not signaling this period' },
|
not_signaling: { cls: 'tile-bip110-badge--not_signaling',label: 'Not Signaling', title: 'Node supports BIP-110 but is not signaling this period' },
|
||||||
unsupported: { cls: 'tile-bip110-badge--unsupported', label: 'BIP\u2011110: Not Supported', title: 'This node build does not include BIP-110' },
|
unsupported: { cls: 'tile-bip110-badge--unsupported', label: 'Not Supported', title: 'This node build does not include BIP-110' },
|
||||||
unknown: { cls: 'tile-bip110-badge--unknown', label: 'BIP\u2011110: \u2014', title: 'Status unavailable (node syncing or RPC not ready)' }
|
unknown: { cls: 'tile-bip110-badge--unknown', label: '\u2014', title: 'Status unavailable (node syncing or RPC not ready)' }
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -355,9 +355,9 @@ async function loadStep3() {
|
|||||||
+ '<strong>Before you continue:</strong>'
|
+ '<strong>Before you continue:</strong>'
|
||||||
+ '<ol style="margin:8px 0 0 16px; padding:0; line-height:1.7;">'
|
+ '<ol style="margin:8px 0 0 16px; padding:0; line-height:1.7;">'
|
||||||
+ '<li>Create an account at <a href="https://njal.la" target="_blank" style="color:var(--accent-color);">https://njal.la</a></li>'
|
+ '<li>Create an account at <a href="https://njal.la" target="_blank" style="color:var(--accent-color);">https://njal.la</a></li>'
|
||||||
+ '<li>Purchase a new domain on Njal.la, or create a subdomain from a domain you already own. Tip: Subdomains are free to create — you only need to purchase one domain, and you can add as many subdomains as you need at no extra cost.</li>'
|
+ '<li>Purchase a new domain on Njal.la, or create a subdomain from a domain you already own. Tip: Subdomains are free to create — you only need to purchase one domain, and you can add as many subdomains as you like.</li>'
|
||||||
+ '<li>In the Njal.la web interface, create a <strong>Dynamic</strong> record pointing to this machine\'s external IP address:<br>'
|
+ '<li>In the Njal.la web interface, create a <strong>Dynamic</strong> record pointing to this machine\'s external IP address:<br>'
|
||||||
+ '<span style="display:inline-block;margin-top:4px;padding:4px 12px;background:var(--card-color);border:1px solid var(--border-color);border-radius:6px;font-family:monospace;font-size:1.1em;font-weight:700;letter-spacing:0.03em;">' + escHtml(externalIp) + '</span></li>'
|
+ '<span style="display:inline-block;margin-top:4px;padding:4px 12px;background:var(--card-color);border:1px solid var(--border-color);border-radius:6px;font-family:monospace;font-size:1.1em;font-weight:700;">' + escHtml(externalIp) + '</span></li>'
|
||||||
+ '<li>Njal.la will give you a curl command like:<br>'
|
+ '<li>Njal.la will give you a curl command like:<br>'
|
||||||
+ '<code style="font-size:0.8em;">curl "https://njal.la/update/?h=sub.domain.com&k=abc123&auto"</code></li>'
|
+ '<code style="font-size:0.8em;">curl "https://njal.la/update/?h=sub.domain.com&k=abc123&auto"</code></li>'
|
||||||
+ '<li>Enter the subdomain and paste that curl command below for each service</li>'
|
+ '<li>Enter the subdomain and paste that curl command below for each service</li>'
|
||||||
@@ -370,7 +370,7 @@ async function loadStep3() {
|
|||||||
html += '<label class="onboarding-domain-label">' + escHtml(d.label) + '</label>';
|
html += '<label class="onboarding-domain-label">' + escHtml(d.label) + '</label>';
|
||||||
html += '<input class="onboarding-domain-input domain-field-input" type="text" id="domain-input-' + escHtml(d.name) + '" data-domain="' + escHtml(d.name) + '" placeholder="e.g. ' + escHtml(d.name) + '.yourdomain.com" value="' + escHtml(currentVal) + '" />';
|
html += '<input class="onboarding-domain-input domain-field-input" type="text" id="domain-input-' + escHtml(d.name) + '" data-domain="' + escHtml(d.name) + '" placeholder="e.g. ' + escHtml(d.name) + '.yourdomain.com" value="' + escHtml(currentVal) + '" />';
|
||||||
html += '<label class="onboarding-domain-label onboarding-domain-label--sub">Njal.la DDNS Curl Command</label>';
|
html += '<label class="onboarding-domain-label onboarding-domain-label--sub">Njal.la DDNS Curl Command</label>';
|
||||||
html += '<input class="onboarding-domain-input domain-field-input" type="text" id="ddns-input-' + escHtml(d.name) + '" data-ddns="' + escHtml(d.name) + '" placeholder="curl "https://njal.la/update/?h=' + escHtml(d.name) + '.yourdomain.com&k=abc123&auto"" />';
|
html += '<input class="onboarding-domain-input domain-field-input" type="text" id="ddns-input-' + escHtml(d.name) + '" data-ddns="' + escHtml(d.name) + '" placeholder="curl "https://njal.la/update/?h=...&k=...&auto"" />';
|
||||||
html += '<p class="onboarding-hint" style="margin-top:4px;">ℹ Paste the curl URL from your Njal.la dashboard\'s Dynamic record</p>';
|
html += '<p class="onboarding-hint" style="margin-top:4px;">ℹ Paste the curl URL from your Njal.la dashboard\'s Dynamic record</p>';
|
||||||
html += '<button type="button" class="btn btn-primary onboarding-domain-save-btn" data-save-domain="' + escHtml(d.name) + '" style="align-self:flex-start;margin-top:8px;font-size:0.82rem;padding:6px 16px;">Save</button>';
|
html += '<button type="button" class="btn btn-primary onboarding-domain-save-btn" data-save-domain="' + escHtml(d.name) + '" style="align-self:flex-start;margin-top:8px;font-size:0.82rem;padding:6px 16px;">Save</button>';
|
||||||
html += '<span class="onboarding-domain-save-status" id="domain-save-status-' + escHtml(d.name) + '" style="font-size:0.82rem;min-height:1.2em;"></span>';
|
html += '<span class="onboarding-domain-save-status" id="domain-save-status-' + escHtml(d.name) + '" style="font-size:0.82rem;min-height:1.2em;"></span>';
|
||||||
@@ -545,14 +545,13 @@ async function loadStep4() {
|
|||||||
html += '<tr><td class="port-req-port">80</td><td class="port-req-proto">TCP</td><td class="port-req-internal-ip">' + ip + '</td><td class="port-req-desc">HTTP</td></tr>';
|
html += '<tr><td class="port-req-port">80</td><td class="port-req-proto">TCP</td><td class="port-req-internal-ip">' + ip + '</td><td class="port-req-desc">HTTP</td></tr>';
|
||||||
html += '<tr><td class="port-req-port">443</td><td class="port-req-proto">TCP</td><td class="port-req-internal-ip">' + ip + '</td><td class="port-req-desc">HTTPS</td></tr>';
|
html += '<tr><td class="port-req-port">443</td><td class="port-req-proto">TCP</td><td class="port-req-internal-ip">' + ip + '</td><td class="port-req-desc">HTTPS</td></tr>';
|
||||||
html += '<tr><td class="port-req-port">22</td><td class="port-req-proto">TCP</td><td class="port-req-internal-ip">' + ip + '</td><td class="port-req-desc">SSH Remote Access</td></tr>';
|
html += '<tr><td class="port-req-port">22</td><td class="port-req-proto">TCP</td><td class="port-req-internal-ip">' + ip + '</td><td class="port-req-desc">SSH Remote Access</td></tr>';
|
||||||
html += '<tr><td class="port-req-port">8448</td><td class="port-req-proto">TCP</td><td class="port-req-internal-ip">' + ip + '</td><td class="port-req-desc">Matrix Federation</td></tr>';
|
|
||||||
html += '</tbody></table>';
|
html += '</tbody></table>';
|
||||||
html += '</div>';
|
html += '</div>';
|
||||||
|
|
||||||
// Optional ports table
|
// Optional ports table
|
||||||
html += '<div class="onboarding-port-section" style="margin-bottom:20px;">';
|
html += '<div class="onboarding-port-section" style="margin-bottom:20px;">';
|
||||||
html += '<div class="onboarding-port-section-title" style="font-weight:700;margin-bottom:4px;">Optional — Only needed if you enable Element Calling:</div>';
|
html += '<div class="onboarding-port-section-title" style="font-weight:700;margin-bottom:4px;">Optional — Only needed if you enable Element Calling:</div>';
|
||||||
html += '<div style="font-size:0.88em;margin-bottom:8px;color:var(--color-text-muted,#888);">These 5 additional port openings are required on top of the 4 required ports above.</div>';
|
html += '<div style="font-size:0.88em;margin-bottom:8px;color:var(--color-text-muted,#888);">These 5 additional port openings are required on top of the 3 required ports above.</div>';
|
||||||
html += '<table class="onboarding-port-table">';
|
html += '<table class="onboarding-port-table">';
|
||||||
html += '<thead><tr><th>Port</th><th>Protocol</th><th>Forward to</th><th>Purpose</th></tr></thead>';
|
html += '<thead><tr><th>Port</th><th>Protocol</th><th>Forward to</th><th>Purpose</th></tr></thead>';
|
||||||
html += '<tbody>';
|
html += '<tbody>';
|
||||||
@@ -560,14 +559,15 @@ async function loadStep4() {
|
|||||||
html += '<tr><td class="port-req-port">7882</td><td class="port-req-proto">UDP</td><td class="port-req-internal-ip">' + ip + '</td><td class="port-req-desc">LiveKit media (UDP mux)</td></tr>';
|
html += '<tr><td class="port-req-port">7882</td><td class="port-req-proto">UDP</td><td class="port-req-internal-ip">' + ip + '</td><td class="port-req-desc">LiveKit media (UDP mux)</td></tr>';
|
||||||
html += '<tr><td class="port-req-port">5349</td><td class="port-req-proto">TCP</td><td class="port-req-internal-ip">' + ip + '</td><td class="port-req-desc">TURN over TLS</td></tr>';
|
html += '<tr><td class="port-req-port">5349</td><td class="port-req-proto">TCP</td><td class="port-req-internal-ip">' + ip + '</td><td class="port-req-desc">TURN over TLS</td></tr>';
|
||||||
html += '<tr><td class="port-req-port">3478</td><td class="port-req-proto">UDP</td><td class="port-req-internal-ip">' + ip + '</td><td class="port-req-desc">TURN (STUN/relay)</td></tr>';
|
html += '<tr><td class="port-req-port">3478</td><td class="port-req-proto">UDP</td><td class="port-req-internal-ip">' + ip + '</td><td class="port-req-desc">TURN (STUN/relay)</td></tr>';
|
||||||
html += '<tr><td class="port-req-port">30000–40000</td><td class="port-req-proto">TCP/UDP</td><td class="port-req-internal-ip">' + ip + '</td><td class="port-req-desc">TURN relay (WebRTC)</td></tr>';
|
html += '<tr><td class="port-req-port">30000–40000</td><td class="port-req-proto">TCP & UDP</td><td class="port-req-internal-ip">' + ip + '</td><td class="port-req-desc">TURN relay (WebRTC)</td></tr>';
|
||||||
html += '</tbody></table>';
|
html += '</tbody></table>';
|
||||||
|
html += '<div style="font-size:0.85em;margin-top:6px;color:var(--color-text-muted,#888);">ℹ The <strong>30000–40000</strong> range is a single forwarding rule — just set its protocol to <strong>both TCP and UDP</strong> (often shown as "Both" or "TCP/UDP" on your router).</div>';
|
||||||
html += '</div>';
|
html += '</div>';
|
||||||
|
|
||||||
// Totals
|
// Totals
|
||||||
html += '<div class="onboarding-port-totals">';
|
html += '<div class="onboarding-port-totals">';
|
||||||
html += '<strong>Total port openings: 4</strong> (without Element Calling)<br>';
|
html += '<strong>Total port openings: 3</strong> (without Element Calling)<br>';
|
||||||
html += '<strong>Total port openings: 9</strong> (with Element Calling — 4 required + 5 optional)';
|
html += '<strong>Total port openings: 8</strong> (with Element Calling — 3 required + 5 optional)';
|
||||||
html += '</div>';
|
html += '</div>';
|
||||||
|
|
||||||
html += '<div class="onboarding-port-warn" style="margin-bottom:16px;">'
|
html += '<div class="onboarding-port-warn" style="margin-bottom:16px;">'
|
||||||
|
|||||||
@@ -0,0 +1,166 @@
|
|||||||
|
import unittest
|
||||||
|
from unittest.mock import patch
|
||||||
|
from pathlib import Path
|
||||||
|
import sys
|
||||||
|
import types
|
||||||
|
|
||||||
|
sys.path.insert(0, str(Path(__file__).resolve().parents[1]))
|
||||||
|
|
||||||
|
|
||||||
|
def _install_web_stubs():
|
||||||
|
if "fastapi" in sys.modules:
|
||||||
|
return
|
||||||
|
|
||||||
|
class _HTTPException(Exception):
|
||||||
|
def __init__(self, status_code=None, detail=None):
|
||||||
|
super().__init__(detail)
|
||||||
|
self.status_code = status_code
|
||||||
|
self.detail = detail
|
||||||
|
|
||||||
|
class _FastAPI:
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def mount(self, *args, **kwargs):
|
||||||
|
return None
|
||||||
|
|
||||||
|
def add_middleware(self, *args, **kwargs):
|
||||||
|
return None
|
||||||
|
|
||||||
|
def __getattr__(self, _name):
|
||||||
|
def _decorator_factory(*args, **kwargs):
|
||||||
|
def _decorator(func):
|
||||||
|
return func
|
||||||
|
|
||||||
|
return _decorator
|
||||||
|
|
||||||
|
return _decorator_factory
|
||||||
|
|
||||||
|
class _BaseModel:
|
||||||
|
pass
|
||||||
|
|
||||||
|
class _StaticFiles:
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
pass
|
||||||
|
|
||||||
|
class _Jinja2Templates:
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
pass
|
||||||
|
|
||||||
|
class _BaseHTTPMiddleware:
|
||||||
|
pass
|
||||||
|
|
||||||
|
fastapi_module = types.ModuleType("fastapi")
|
||||||
|
fastapi_module.FastAPI = _FastAPI
|
||||||
|
fastapi_module.HTTPException = _HTTPException
|
||||||
|
sys.modules["fastapi"] = fastapi_module
|
||||||
|
|
||||||
|
responses_module = types.ModuleType("fastapi.responses")
|
||||||
|
responses_module.HTMLResponse = object
|
||||||
|
responses_module.JSONResponse = object
|
||||||
|
responses_module.RedirectResponse = object
|
||||||
|
sys.modules["fastapi.responses"] = responses_module
|
||||||
|
|
||||||
|
staticfiles_module = types.ModuleType("fastapi.staticfiles")
|
||||||
|
staticfiles_module.StaticFiles = _StaticFiles
|
||||||
|
sys.modules["fastapi.staticfiles"] = staticfiles_module
|
||||||
|
|
||||||
|
templating_module = types.ModuleType("fastapi.templating")
|
||||||
|
templating_module.Jinja2Templates = _Jinja2Templates
|
||||||
|
sys.modules["fastapi.templating"] = templating_module
|
||||||
|
|
||||||
|
requests_module = types.ModuleType("fastapi.requests")
|
||||||
|
requests_module.Request = object
|
||||||
|
sys.modules["fastapi.requests"] = requests_module
|
||||||
|
|
||||||
|
pydantic_module = types.ModuleType("pydantic")
|
||||||
|
pydantic_module.BaseModel = _BaseModel
|
||||||
|
sys.modules["pydantic"] = pydantic_module
|
||||||
|
|
||||||
|
starlette_base_module = types.ModuleType("starlette.middleware.base")
|
||||||
|
starlette_base_module.BaseHTTPMiddleware = _BaseHTTPMiddleware
|
||||||
|
sys.modules["starlette.middleware.base"] = starlette_base_module
|
||||||
|
|
||||||
|
starlette_middleware_module = types.ModuleType("starlette.middleware")
|
||||||
|
starlette_middleware_module.base = starlette_base_module
|
||||||
|
sys.modules["starlette.middleware"] = starlette_middleware_module
|
||||||
|
|
||||||
|
starlette_module = types.ModuleType("starlette")
|
||||||
|
starlette_module.middleware = starlette_middleware_module
|
||||||
|
sys.modules["starlette"] = starlette_module
|
||||||
|
|
||||||
|
|
||||||
|
_install_web_stubs()
|
||||||
|
from sovran_systemsos_web import server
|
||||||
|
|
||||||
|
|
||||||
|
class Bip110StatusTests(unittest.TestCase):
|
||||||
|
def _status(self, deploy_info, net_info):
|
||||||
|
with patch.object(server, "_get_bitcoin_deployment_info", return_value=deploy_info), patch.object(
|
||||||
|
server, "_get_bitcoin_version_info", return_value=net_info
|
||||||
|
):
|
||||||
|
return server._get_bip110_status()
|
||||||
|
|
||||||
|
def test_started_reduced_data_reports_signaling(self):
|
||||||
|
deploy_info = {
|
||||||
|
"deployments": {
|
||||||
|
"reduced_data": {
|
||||||
|
"type": "bip9",
|
||||||
|
"active": False,
|
||||||
|
"bip9": {
|
||||||
|
"bit": 4,
|
||||||
|
"status": "started",
|
||||||
|
"statistics": {"elapsed": 833, "count": 4, "threshold": 1109},
|
||||||
|
"signalling": "--#--",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
result = self._status(deploy_info, {"subversion": "/Satoshi:29.0.0/"})
|
||||||
|
self.assertEqual(
|
||||||
|
result,
|
||||||
|
{"supported": True, "signaling": True, "state": "signaling", "source": "getdeploymentinfo"},
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_active_reduced_data_reports_active(self):
|
||||||
|
deploy_info = {
|
||||||
|
"deployments": {"reduced_data": {"active": True, "bip9": {"bit": 4, "status": "active"}}}
|
||||||
|
}
|
||||||
|
|
||||||
|
result = self._status(deploy_info, {"subversion": "/Satoshi:29.0.0/"})
|
||||||
|
self.assertEqual(result["state"], "active")
|
||||||
|
self.assertTrue(result["supported"])
|
||||||
|
self.assertTrue(result["signaling"])
|
||||||
|
self.assertEqual(result["source"], "getdeploymentinfo")
|
||||||
|
|
||||||
|
def test_locked_in_reduced_data_reports_locked_in(self):
|
||||||
|
deploy_info = {
|
||||||
|
"deployments": {"reduced_data": {"active": False, "bip9": {"bit": 4, "status": "locked_in"}}}
|
||||||
|
}
|
||||||
|
|
||||||
|
result = self._status(deploy_info, {"subversion": "/Satoshi:29.0.0/"})
|
||||||
|
self.assertEqual(result["state"], "locked_in")
|
||||||
|
self.assertTrue(result["supported"])
|
||||||
|
self.assertTrue(result["signaling"])
|
||||||
|
self.assertEqual(result["source"], "getdeploymentinfo")
|
||||||
|
|
||||||
|
def test_no_bip110_deployment_and_plain_subversion_reports_unsupported(self):
|
||||||
|
deploy_info = {
|
||||||
|
"deployments": {
|
||||||
|
"taproot": {"type": "bip9", "active": True, "bip9": {"bit": 2, "status": "active"}},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result = self._status(deploy_info, {"subversion": "/Satoshi:27.0.0/"})
|
||||||
|
self.assertEqual(
|
||||||
|
result,
|
||||||
|
{"supported": False, "signaling": False, "state": "unsupported", "source": "subversion"},
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_node_unreachable_reports_unknown(self):
|
||||||
|
result = self._status(None, None)
|
||||||
|
self.assertEqual(result, {"supported": False, "signaling": False, "state": "unknown", "source": "none"})
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
unittest.main()
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 442 KiB |
+2
-2
@@ -145,10 +145,10 @@
|
|||||||
ranger fastfetch gedit openssl pwgen
|
ranger fastfetch gedit openssl pwgen
|
||||||
aspell aspellDicts.en lm_sensors
|
aspell aspellDicts.en lm_sensors
|
||||||
hunspell hunspellDicts.en_US
|
hunspell hunspellDicts.en_US
|
||||||
synadm brave dua bitwarden-desktop
|
synadm brave dua
|
||||||
gparted pv unzip parted screen zenity
|
gparted pv unzip parted screen zenity
|
||||||
libargon2 gnome-terminal libreoffice-fresh
|
libargon2 gnome-terminal libreoffice-fresh
|
||||||
dig firefox element-desktop wp-cli axel
|
dig firefox wp-cli axel
|
||||||
lk-jwt-service livekit-libwebrtc livekit-cli livekit
|
lk-jwt-service livekit-libwebrtc livekit-cli livekit
|
||||||
matrix-synapse age
|
matrix-synapse age
|
||||||
];
|
];
|
||||||
|
|||||||
Generated
+29
-63
@@ -1,33 +1,15 @@
|
|||||||
{
|
{
|
||||||
"nodes": {
|
"nodes": {
|
||||||
"bip110": {
|
"btc-clients": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"nixpkgs": "nixpkgs"
|
"nixpkgs": "nixpkgs"
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1778967282,
|
"lastModified": 1781013869,
|
||||||
"narHash": "sha256-0g9RvVCD6zxY2vy54GhbB1OeeEZdKuxTr9r0whcpRjQ=",
|
"narHash": "sha256-XlEUtL+8M6kbPdmIh4sQQ7G02/1CwHQEk1RPvIMEWOs=",
|
||||||
"owner": "emmanuelrosa",
|
|
||||||
"repo": "bitcoin-knots-bip-110-nix",
|
|
||||||
"rev": "8d23ed98940d70e42ee870d719677a073a0a5920",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "emmanuelrosa",
|
|
||||||
"repo": "bitcoin-knots-bip-110-nix",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"btc-clients": {
|
|
||||||
"inputs": {
|
|
||||||
"nixpkgs": "nixpkgs_2"
|
|
||||||
},
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1779889285,
|
|
||||||
"narHash": "sha256-5QOMNn/rxJjsy9n2pAG5+AwUXOAPXSzcr62y1tGHXKA=",
|
|
||||||
"owner": "emmanuelrosa",
|
"owner": "emmanuelrosa",
|
||||||
"repo": "btc-clients-nix",
|
"repo": "btc-clients-nix",
|
||||||
"rev": "9a3dd86e11ea5fb17ace9043aa3d0d5ed359a3ca",
|
"rev": "9a6c78204dc8961840375b110bca595b1f6f084c",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@@ -105,7 +87,7 @@
|
|||||||
"inputs": {
|
"inputs": {
|
||||||
"extra-container": "extra-container",
|
"extra-container": "extra-container",
|
||||||
"flake-utils": "flake-utils",
|
"flake-utils": "flake-utils",
|
||||||
"nixpkgs": "nixpkgs_3",
|
"nixpkgs": "nixpkgs_2",
|
||||||
"nixpkgs-25_05": "nixpkgs-25_05",
|
"nixpkgs-25_05": "nixpkgs-25_05",
|
||||||
"nixpkgs-unstable": "nixpkgs-unstable"
|
"nixpkgs-unstable": "nixpkgs-unstable"
|
||||||
},
|
},
|
||||||
@@ -126,16 +108,15 @@
|
|||||||
},
|
},
|
||||||
"nixpkgs": {
|
"nixpkgs": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1777728799,
|
"lastModified": 1780218263,
|
||||||
"narHash": "sha256-z7jjYQqhkFKab92VQ3duB7QVO7f7Y62qTFrJYXO/lyo=",
|
"narHash": "sha256-T/f0pPDrH3Qc1VXyQXbK7yfHWRn90l3xwplc/nsxin4=",
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "4b2287113c2f9a2331c04899b2e2e5ab92dea9c5",
|
"rev": "7fc393d1b46fa000d48ff14e8b6a3c9985f03af0",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
"owner": "nixos",
|
"owner": "nixos",
|
||||||
"ref": "master",
|
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
@@ -158,16 +139,16 @@
|
|||||||
},
|
},
|
||||||
"nixpkgs-stable": {
|
"nixpkgs-stable": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1751274312,
|
"lastModified": 1780902259,
|
||||||
"narHash": "sha256-/bVBlRpECLVzjV19t5KMdMFWSwKLtb5RyXdjz3LJT+g=",
|
"narHash": "sha256-q8yYEC5f1mFlQO9RGna4LTc9QrcvWunX6FYp83munkQ=",
|
||||||
"owner": "nixos",
|
"owner": "nixos",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "50ab793786d9de88ee30ec4e4c24fb4236fc2674",
|
"rev": "bd0ff2d3eac24699c3664d5966b9ef36f388e2ca",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
"owner": "nixos",
|
"owner": "nixos",
|
||||||
"ref": "nixos-24.11",
|
"ref": "nixos-26.05",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
@@ -189,21 +170,6 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"nixpkgs_2": {
|
"nixpkgs_2": {
|
||||||
"locked": {
|
|
||||||
"lastModified": 1777728799,
|
|
||||||
"narHash": "sha256-z7jjYQqhkFKab92VQ3duB7QVO7f7Y62qTFrJYXO/lyo=",
|
|
||||||
"owner": "NixOS",
|
|
||||||
"repo": "nixpkgs",
|
|
||||||
"rev": "4b2287113c2f9a2331c04899b2e2e5ab92dea9c5",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "nixos",
|
|
||||||
"repo": "nixpkgs",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"nixpkgs_3": {
|
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1778737229,
|
"lastModified": 1778737229,
|
||||||
"narHash": "sha256-6xWoytx8jFW4PF1GjRm/i/53trbpKGfz6zjzQGBr4cI=",
|
"narHash": "sha256-6xWoytx8jFW4PF1GjRm/i/53trbpKGfz6zjzQGBr4cI=",
|
||||||
@@ -219,13 +185,13 @@
|
|||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"nixpkgs_4": {
|
"nixpkgs_3": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1779560665,
|
"lastModified": 1780749050,
|
||||||
"narHash": "sha256-tpyBcxPpcQb8ukyNF7DoCwfSY3VPsxHoYwj00Cayv5o=",
|
"narHash": "sha256-3av0pIjlOWQ6rDbNOmpUSvbNnJkGORQKKjb4LtCZsIY=",
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "64c08a7ca051951c8eae34e3e3cb1e202fe36786",
|
"rev": "a799d3e3886da994fa307f817a6bc705ae538eeb",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@@ -235,13 +201,13 @@
|
|||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"nixpkgs_5": {
|
"nixpkgs_4": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1779259093,
|
"lastModified": 1780336545,
|
||||||
"narHash": "sha256-7DKWmH23hL2eYdkxCKeqj2i+yljTKuU+3Nk1UPHOnxc=",
|
"narHash": "sha256-vhVhuXzFrIOfcssC/9hDHx7MHzDKjF3keHuREOQqQiQ=",
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "d99b013d5d1931ad77fe3912ed218170dec5d9a4",
|
"rev": "4df1b885d76a54e1aa1a318f8d16fd6005b6401f",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@@ -254,15 +220,15 @@
|
|||||||
"nixvim": {
|
"nixvim": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"flake-parts": "flake-parts",
|
"flake-parts": "flake-parts",
|
||||||
"nixpkgs": "nixpkgs_5",
|
"nixpkgs": "nixpkgs_4",
|
||||||
"systems": "systems_2"
|
"systems": "systems_2"
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1779816597,
|
"lastModified": 1780995253,
|
||||||
"narHash": "sha256-Kgod3gZlhSp6WozZ2pFaclXbWpjs6kQLAtldoxb85Lc=",
|
"narHash": "sha256-6Lsoyw2XPvY8YNMCtPnsyw0JVVtHsXP2xtrFJBBTAOQ=",
|
||||||
"owner": "nix-community",
|
"owner": "nix-community",
|
||||||
"repo": "nixvim",
|
"repo": "nixvim",
|
||||||
"rev": "297f9341476ba7f821a42d7a2805e206ef8c6ef8",
|
"rev": "43a7e6f82978ac975c3bba6728869b231e7a1ba0",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@@ -273,10 +239,9 @@
|
|||||||
},
|
},
|
||||||
"root": {
|
"root": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"bip110": "bip110",
|
|
||||||
"btc-clients": "btc-clients",
|
"btc-clients": "btc-clients",
|
||||||
"nix-bitcoin": "nix-bitcoin",
|
"nix-bitcoin": "nix-bitcoin",
|
||||||
"nixpkgs": "nixpkgs_4",
|
"nixpkgs": "nixpkgs_3",
|
||||||
"nixpkgs-stable": "nixpkgs-stable",
|
"nixpkgs-stable": "nixpkgs-stable",
|
||||||
"nixvim": "nixvim"
|
"nixvim": "nixvim"
|
||||||
}
|
}
|
||||||
@@ -298,15 +263,16 @@
|
|||||||
},
|
},
|
||||||
"systems_2": {
|
"systems_2": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1681028828,
|
"lastModified": 1774449309,
|
||||||
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
"narHash": "sha256-brhZ8DmuGtzkCYHJg4HEd602amKm89Y9ytsFZ5uWD1w=",
|
||||||
"owner": "nix-systems",
|
"owner": "nix-systems",
|
||||||
"repo": "default",
|
"repo": "default",
|
||||||
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
"rev": "c29398b59d2048c4ab79345812849c9bd15e9150",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
"owner": "nix-systems",
|
"owner": "nix-systems",
|
||||||
|
"ref": "future-26.11",
|
||||||
"repo": "default",
|
"repo": "default",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
nix-bitcoin.url = "github:fort-nix/nix-bitcoin/release";
|
nix-bitcoin.url = "github:fort-nix/nix-bitcoin/release";
|
||||||
nixvim.url = "github:nix-community/nixvim";
|
nixvim.url = "github:nix-community/nixvim";
|
||||||
btc-clients.url = "github:emmanuelrosa/btc-clients-nix";
|
btc-clients.url = "github:emmanuelrosa/btc-clients-nix";
|
||||||
nixpkgs-stable.url = "github:nixos/nixpkgs/nixos-24.11";
|
nixpkgs-stable.url = "github:nixos/nixpkgs/nixos-26.05";
|
||||||
};
|
};
|
||||||
|
|
||||||
outputs = { self, nixpkgs, nix-bitcoin, nixvim, btc-clients, nixpkgs-stable, ... }:
|
outputs = { self, nixpkgs, nix-bitcoin, nixvim, btc-clients, nixpkgs-stable, ... }:
|
||||||
|
|||||||
@@ -16,7 +16,6 @@ in
|
|||||||
{
|
{
|
||||||
imports = [
|
imports = [
|
||||||
"${modulesPath}/installer/cd-dvd/installation-cd-graphical-gnome.nix"
|
"${modulesPath}/installer/cd-dvd/installation-cd-graphical-gnome.nix"
|
||||||
./branding.nix
|
|
||||||
];
|
];
|
||||||
|
|
||||||
image.baseName = lib.mkForce "Sovran_SystemsOS";
|
image.baseName = lib.mkForce "Sovran_SystemsOS";
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ lib.mkIf config.sovran_systemsOS.services.bitcoin {
|
|||||||
|
|
||||||
services.bitcoind = {
|
services.bitcoind = {
|
||||||
enable = true;
|
enable = true;
|
||||||
package = config.nix-bitcoin.pkgs.bitcoind-knots;
|
package = pkgs.bitcoind-knots;
|
||||||
dataDir = "/run/media/Second_Drive/BTCEcoandBackup/Bitcoin_Node";
|
dataDir = "/run/media/Second_Drive/BTCEcoandBackup/Bitcoin_Node";
|
||||||
txindex = true;
|
txindex = true;
|
||||||
tor.proxy = true;
|
tor.proxy = true;
|
||||||
|
|||||||
@@ -94,10 +94,10 @@ EOF
|
|||||||
$MATRIX {
|
$MATRIX {
|
||||||
reverse_proxy /_matrix/* http://localhost:8008
|
reverse_proxy /_matrix/* http://localhost:8008
|
||||||
reverse_proxy /_synapse/client/* http://localhost:8008
|
reverse_proxy /_synapse/client/* http://localhost:8008
|
||||||
|
handle /.well-known/matrix/server {
|
||||||
|
header Content-Type application/json
|
||||||
|
respond \`{"m.server":"$MATRIX:443"}\` 200
|
||||||
}
|
}
|
||||||
|
|
||||||
$MATRIX:8448 {
|
|
||||||
reverse_proxy http://localhost:8008
|
|
||||||
}
|
}
|
||||||
EOF
|
EOF
|
||||||
fi
|
fi
|
||||||
|
|||||||
@@ -68,10 +68,7 @@ $MATRIX {
|
|||||||
header /.well-known/matrix/* Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS"
|
header /.well-known/matrix/* Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS"
|
||||||
header /.well-known/matrix/* Access-Control-Allow-Headers "X-Requested-With, Content-Type, Authorization"
|
header /.well-known/matrix/* Access-Control-Allow-Headers "X-Requested-With, Content-Type, Authorization"
|
||||||
respond /.well-known/matrix/client \`{ "m.homeserver": {"base_url": "https://$MATRIX" }, "org.matrix.msc4143.rtc_foci": [{ "type":"livekit", "livekit_service_url":"https://$ELEMENT_CALLING/livekit/jwt" }] }\`
|
respond /.well-known/matrix/client \`{ "m.homeserver": {"base_url": "https://$MATRIX" }, "org.matrix.msc4143.rtc_foci": [{ "type":"livekit", "livekit_service_url":"https://$ELEMENT_CALLING/livekit/jwt" }] }\`
|
||||||
}
|
respond /.well-known/matrix/server \`{"m.server":"$MATRIX:443"}\`
|
||||||
|
|
||||||
$MATRIX:8448 {
|
|
||||||
reverse_proxy http://localhost:8008
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$ELEMENT_CALLING {
|
$ELEMENT_CALLING {
|
||||||
|
|||||||
@@ -250,9 +250,6 @@ CREDS
|
|||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
networking.firewall.allowedTCPPorts = [ 8448 ];
|
|
||||||
networking.firewall.allowedUDPPorts = [ 8448 ];
|
|
||||||
|
|
||||||
sovran_systemsOS.domainRequirements = [
|
sovran_systemsOS.domainRequirements = [
|
||||||
{ name = "matrix"; label = "Matrix Synapse"; example = "matrix.yourdomain.com"; }
|
{ name = "matrix"; label = "Matrix Synapse"; example = "matrix.yourdomain.com"; }
|
||||||
];
|
];
|
||||||
|
|||||||
Reference in New Issue
Block a user