Compare commits
7
Commits
be5d47cb9c
..
v1.1.4
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
93492e88fb | ||
|
|
7da37cdb34 | ||
|
|
f34d1533c3 | ||
|
|
220d6dff2c | ||
|
|
81ab3b2280 | ||
|
|
d5d40a1697 | ||
|
|
3756a0058d |
@@ -7,6 +7,43 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## [1.1.4] - 2026-09-02
|
||||||
|
|
||||||
|
### Added
|
||||||
|
- Element-calling: fix Nix string interpolation of LAN_CIDR echo
|
||||||
|
- Docs/hub: update Element Calling port guidance to the new port set
|
||||||
|
- Element-calling: fix Wi-Fi calls and tighten media/TURN ports
|
||||||
|
- Flake: pin LiveKit to 1.13.6 for rtc.advertise_internal_ip support
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
- Updated nixpkgs
|
||||||
|
- Updated sovran-bitcon
|
||||||
|
- Dedupe NWC tooling — use Sovran_Bitcoin's sovran-nwc
|
||||||
|
- Update sovran-bitcoin flake input
|
||||||
|
- Extract bitcoin stack into Sovran_Bitcoin flake input
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- Set lnurl domainFile for Hub-managed Lightning Address domain
|
||||||
|
- Correct disablewallet casing
|
||||||
|
- Fixed typo
|
||||||
|
[1.1.4]: https://git.sovransystems.com/Sovran_Systems/Sovran_SystemsOS/releases/tag/v1.1.4
|
||||||
|
|
||||||
|
|
||||||
|
## [Unreleased]
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
- Element Calling: pin LiveKit to 1.13.6 and advertise the LAN interface
|
||||||
|
(rtc.advertise_internal_ip) so Wi-Fi callers get a local ICE candidate and
|
||||||
|
calls no longer depend on router NAT hairpin
|
||||||
|
- Element Calling: use a single UDP media mux (7882); move the TURN relay to
|
||||||
|
40000-40099 and remove the unreachable 5349 TURN/TLS listener
|
||||||
|
- Hub: update Element Calling router-port guidance to the new port set
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- Element Calling: TURN relay could not deliver media to the SFU on routers
|
||||||
|
without NAT loopback (turn.allow_restricted_peer_cidrs now permits the LAN
|
||||||
|
subnet derived from the primary interface)
|
||||||
|
|
||||||
## [1.1.3] - 2026-08-27
|
## [1.1.3] - 2026-08-27
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|||||||
@@ -21,9 +21,9 @@ Lightning infrastructure, private cloud, and communications platform when you
|
|||||||
are ready.
|
are ready.
|
||||||
|
|
||||||
[Visit the Website](https://sovransystems.com) ·
|
[Visit the Website](https://sovransystems.com) ·
|
||||||
[Download the ISO](https://downloads.sovransystems.com/Sovran_SystemsOS-1.1.3.iso) ·
|
[Download the ISO](https://downloads.sovransystems.com/Sovran_SystemsOS-1.1.4.iso) ·
|
||||||
[Try it safely in a VM](#try-it-first-in-a-virtual-machine) ·
|
[Try it safely in a VM](#try-it-first-in-a-virtual-machine) ·
|
||||||
[Verify the Download](https://downloads.sovransystems.com/Sovran_SystemsOS-1.1.3.iso.sha256) ·
|
[Verify the Download](https://downloads.sovransystems.com/Sovran_SystemsOS-1.1.4.iso.sha256) ·
|
||||||
[Build from Source](#build-from-source)
|
[Build from Source](#build-from-source)
|
||||||
|
|
||||||
<img src="assets/desktop-screenshot.webp" alt="Sovran_SystemsOS private Bitcoin desktop" width="800" />
|
<img src="assets/desktop-screenshot.webp" alt="Sovran_SystemsOS private Bitcoin desktop" width="800" />
|
||||||
@@ -345,8 +345,8 @@ with an imaging application such as [Balena Etcher](https://etcher.balena.io).
|
|||||||
|
|
||||||
### 1. Download the ISO and checksum
|
### 1. Download the ISO and checksum
|
||||||
|
|
||||||
- [Download Sovran_SystemsOS-1.1.3.iso](https://downloads.sovransystems.com/Sovran_SystemsOS-1.1.3.iso)
|
- [Download Sovran_SystemsOS-1.1.4.iso](https://downloads.sovransystems.com/Sovran_SystemsOS-1.1.4.iso)
|
||||||
- [Download Sovran_SystemsOS-1.1.3.iso.sha256](https://downloads.sovransystems.com/Sovran_SystemsOS-1.1.3.iso.sha256)
|
- [Download Sovran_SystemsOS-1.1.4.iso.sha256](https://downloads.sovransystems.com/Sovran_SystemsOS-1.1.4.iso.sha256)
|
||||||
|
|
||||||
The download may take some time. Do not rename or modify the ISO before
|
The download may take some time. Do not rename or modify the ISO before
|
||||||
verifying it, and keep both files in the same folder.
|
verifying it, and keep both files in the same folder.
|
||||||
@@ -364,16 +364,16 @@ checksum exactly.
|
|||||||
Open a terminal in the download folder and run:
|
Open a terminal in the download folder and run:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
sha256sum --check Sovran_SystemsOS-1.1.3.iso.sha256
|
sha256sum --check Sovran_SystemsOS-1.1.4.iso.sha256
|
||||||
```
|
```
|
||||||
|
|
||||||
A successful comparison reports:
|
A successful comparison reports:
|
||||||
|
|
||||||
```text
|
```text
|
||||||
Sovran_SystemsOS-1.1.3.iso: OK
|
Sovran_SystemsOS-1.1.4.iso: OK
|
||||||
```
|
```
|
||||||
|
|
||||||
You can also run `sha256sum Sovran_SystemsOS-1.1.3.iso` and compare the output
|
You can also run `sha256sum Sovran_SystemsOS-1.1.4.iso` and compare the output
|
||||||
against the checksum file manually.
|
against the checksum file manually.
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
@@ -384,11 +384,11 @@ against the checksum file manually.
|
|||||||
Open Terminal in the download folder and run:
|
Open Terminal in the download folder and run:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
shasum -a 256 Sovran_SystemsOS-1.1.3.iso
|
shasum -a 256 Sovran_SystemsOS-1.1.4.iso
|
||||||
```
|
```
|
||||||
|
|
||||||
Compare the value shown in Terminal with the value inside
|
Compare the value shown in Terminal with the value inside
|
||||||
`Sovran_SystemsOS-1.1.3.iso.sha256`.
|
`Sovran_SystemsOS-1.1.4.iso.sha256`.
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
@@ -398,7 +398,7 @@ Compare the value shown in Terminal with the value inside
|
|||||||
Open PowerShell in the download folder and run:
|
Open PowerShell in the download folder and run:
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
Get-FileHash .\Sovran_SystemsOS-1.1.3.iso -Algorithm SHA256
|
Get-FileHash .\Sovran_SystemsOS-1.1.4.iso -Algorithm SHA256
|
||||||
```
|
```
|
||||||
|
|
||||||
Compare the value under `Hash` with the published checksum.
|
Compare the value under `Hash` with the published checksum.
|
||||||
@@ -413,7 +413,7 @@ match exactly.
|
|||||||
|
|
||||||
1. Download and install [Balena Etcher](https://etcher.balena.io), then
|
1. Download and install [Balena Etcher](https://etcher.balena.io), then
|
||||||
connect the USB drive.
|
connect the USB drive.
|
||||||
2. Choose **Flash from file** and select `Sovran_SystemsOS-1.1.3.iso`.
|
2. Choose **Flash from file** and select `Sovran_SystemsOS-1.1.4.iso`.
|
||||||
3. Choose **Select target**, select the USB drive, and review your selection
|
3. Choose **Select target**, select the USB drive, and review your selection
|
||||||
carefully.
|
carefully.
|
||||||
4. Choose **Flash** and wait for the writing and verification process to
|
4. Choose **Flash** and wait for the writing and verification process to
|
||||||
@@ -856,7 +856,7 @@ primary location for collaboration. Please read our
|
|||||||
## Privacy. Sovereignty. Bitcoin.
|
## Privacy. Sovereignty. Bitcoin.
|
||||||
|
|
||||||
[Visit Sovran Systems](https://sovransystems.com) ·
|
[Visit Sovran Systems](https://sovransystems.com) ·
|
||||||
[Download Sovran_SystemsOS](https://downloads.sovransystems.com/Sovran_SystemsOS-1.1.3.iso) ·
|
[Download Sovran_SystemsOS](https://downloads.sovransystems.com/Sovran_SystemsOS-1.1.4.iso) ·
|
||||||
[View the License](LICENSE)
|
[View the License](LICENSE)
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -291,11 +291,10 @@ FEATURE_REGISTRY = [
|
|||||||
"port_requirements": [
|
"port_requirements": [
|
||||||
{"port": "80", "protocol": "TCP", "description": "HTTP (redirect to HTTPS)"},
|
{"port": "80", "protocol": "TCP", "description": "HTTP (redirect to HTTPS)"},
|
||||||
{"port": "443", "protocol": "TCP", "description": "HTTPS (domain)"},
|
{"port": "443", "protocol": "TCP", "description": "HTTPS (domain)"},
|
||||||
{"port": "7881", "protocol": "TCP", "description": "LiveKit WebRTC signalling"},
|
{"port": "7881", "protocol": "TCP", "description": "WebRTC media (TCP fallback)"},
|
||||||
{"port": "7882", "protocol": "UDP", "description": "LiveKit media (UDP mux)"},
|
{"port": "7882", "protocol": "UDP", "description": "WebRTC media (UDP)"},
|
||||||
{"port": "5349", "protocol": "TCP", "description": "TURN over TLS"},
|
{"port": "3478", "protocol": "UDP", "description": "TURN relay + STUN"},
|
||||||
{"port": "3478", "protocol": "UDP", "description": "TURN (STUN/relay)"},
|
{"port": "40000-40099", "protocol": "UDP", "description": "TURN relay (WebRTC media)"},
|
||||||
{"port": "30000-40000", "protocol": "TCP/UDP", "description": "TURN relay (WebRTC)"},
|
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -395,11 +394,10 @@ 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_ELEMENT_CALLING = [
|
_PORTS_ELEMENT_CALLING = [
|
||||||
{"port": "7881", "protocol": "TCP", "description": "LiveKit WebRTC signalling"},
|
{"port": "7881", "protocol": "TCP", "description": "WebRTC media (TCP fallback)"},
|
||||||
{"port": "7882", "protocol": "UDP", "description": "LiveKit media (UDP mux)"},
|
{"port": "7882", "protocol": "UDP", "description": "WebRTC media (UDP)"},
|
||||||
{"port": "5349", "protocol": "TCP", "description": "TURN over TLS"},
|
{"port": "3478", "protocol": "UDP", "description": "TURN relay + STUN"},
|
||||||
{"port": "3478", "protocol": "UDP", "description": "TURN (STUN/relay)"},
|
{"port": "40000-40099", "protocol": "UDP", "description": "TURN relay (WebRTC media)"},
|
||||||
{"port": "30000-40000", "protocol": "TCP/UDP", "description": "TURN relay (WebRTC)"},
|
|
||||||
]
|
]
|
||||||
|
|
||||||
# Units whose port requirements exist purely so the user can forward them in
|
# Units whose port requirements exist purely so the user can forward them in
|
||||||
@@ -1114,7 +1112,7 @@ def _get_firewall_allowed_ports() -> dict[str, set[int]]:
|
|||||||
)
|
)
|
||||||
if proc.returncode == 0:
|
if proc.returncode == 0:
|
||||||
for line in proc.stdout.splitlines():
|
for line in proc.stdout.splitlines():
|
||||||
# e.g. ACCEPT tcp -- ... dpt:443 or dpts:7882:7894
|
# e.g. ACCEPT tcp -- ... dpt:443 or dpts:40000:40099
|
||||||
m = re.search(r'(tcp|udp).*dpts?:(\d+)(?::(\d+))?', line)
|
m = re.search(r'(tcp|udp).*dpts?:(\d+)(?::(\d+))?', line)
|
||||||
if m:
|
if m:
|
||||||
proto_match = m.group(1)
|
proto_match = m.group(1)
|
||||||
@@ -1172,7 +1170,7 @@ def _resolve_all_addresses_cached(domain: str) -> list[str]:
|
|||||||
|
|
||||||
|
|
||||||
def _port_range_to_ints(port_str: str) -> list[int]:
|
def _port_range_to_ints(port_str: str) -> list[int]:
|
||||||
"""Convert a port string like ``"443"``, ``"30000-40000"`` to a list of ints."""
|
"""Convert a port string like ``"443"``, ``"40000-40099"`` to a list of ints."""
|
||||||
port_str = port_str.strip()
|
port_str = port_str.strip()
|
||||||
if re.match(r'^\d+$', port_str):
|
if re.match(r'^\d+$', port_str):
|
||||||
return [int(port_str)]
|
return [int(port_str)]
|
||||||
|
|||||||
@@ -88,7 +88,7 @@ function renderPortForwardGuideHtml(ports, opts) {
|
|||||||
'<ul class="port-req-steps">' +
|
'<ul class="port-req-steps">' +
|
||||||
'<li>Set the <strong>internal (private) port</strong> and the <strong>external (public) port</strong> to the <strong>same number</strong>.</li>' +
|
'<li>Set the <strong>internal (private) port</strong> and the <strong>external (public) port</strong> to the <strong>same number</strong>.</li>' +
|
||||||
'<li>Match the <strong>protocol</strong> exactly — a rule set to TCP will not pass UDP traffic. Where the table says <strong>TCP + UDP</strong>, create both rules (or pick “Both”/“TCP/UDP” if your router offers it).</li>' +
|
'<li>Match the <strong>protocol</strong> exactly — a rule set to TCP will not pass UDP traffic. Where the table says <strong>TCP + UDP</strong>, create both rules (or pick “Both”/“TCP/UDP” if your router offers it).</li>' +
|
||||||
'<li>For a range such as <strong>30000-40000</strong>, use your router’s port-range fields — start 30000, end 40000 — rather than one rule per port.</li>' +
|
'<li>For a range such as <strong>40000-40099</strong>, use your router’s port-range fields — start 40000, end 40099 — rather than one rule per port.</li>' +
|
||||||
'</ul>' +
|
'</ul>' +
|
||||||
'<table class="' + tableClass + '">' +
|
'<table class="' + tableClass + '">' +
|
||||||
'<thead><tr><th>Port(s)</th><th>Protocol</th><th>Used for</th></tr></thead>' +
|
'<thead><tr><th>Port(s)</th><th>Protocol</th><th>Used for</th></tr></thead>' +
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
"albyhub.service": "1.24.0",
|
"albyhub.service": "1.24.0",
|
||||||
"mempool.service": "3.2.1",
|
"mempool.service": "3.2.1",
|
||||||
"matrix-synapse.service": "1.115.0",
|
"matrix-synapse.service": "1.115.0",
|
||||||
"livekit.service": "1.5.2",
|
"livekit.service": "1.13.6",
|
||||||
"vaultwarden.service": "1.32.0",
|
"vaultwarden.service": "1.32.0",
|
||||||
"haven-relay.service": "0.1.0"
|
"haven-relay.service": "0.1.0"
|
||||||
}
|
}
|
||||||
|
|||||||
Generated
+27
-27
@@ -5,11 +5,11 @@
|
|||||||
"nixpkgs": "nixpkgs"
|
"nixpkgs": "nixpkgs"
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1787839684,
|
"lastModified": 1787862680,
|
||||||
"narHash": "sha256-xTafqsVs2/zyGsaCel41QT5Lpbs/rG56Kp+YsmLXL8I=",
|
"narHash": "sha256-mv+W62cI1Bjtkz9k8N8M7+7VSauv0/WmBrDYjcy5sE0=",
|
||||||
"owner": "emmanuelrosa",
|
"owner": "emmanuelrosa",
|
||||||
"repo": "btc-clients-nix",
|
"repo": "btc-clients-nix",
|
||||||
"rev": "ef81159876930802ef9861aa5c039cec6886a30f",
|
"rev": "f00585b12e751ac738392e2cccfbe305d077e2d4",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@@ -26,11 +26,11 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1785627969,
|
"lastModified": 1787559586,
|
||||||
"narHash": "sha256-4dtXQk/NMePegK/nWp5NSeuZKLATItOq61lpEvmXqGw=",
|
"narHash": "sha256-onL0VLf9vPllmT0H/OlURIU5r5t5WIEl7t4tVNKT0Nw=",
|
||||||
"owner": "hercules-ci",
|
"owner": "hercules-ci",
|
||||||
"repo": "flake-parts",
|
"repo": "flake-parts",
|
||||||
"rev": "427bf4bd9435fdf21321c8cc628c24efc14c0f7a",
|
"rev": "9d0d87172c374f89da73c1cfe6d81ae62feac1f1",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@@ -56,11 +56,11 @@
|
|||||||
},
|
},
|
||||||
"nixpkgs-stable": {
|
"nixpkgs-stable": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1787753485,
|
"lastModified": 1788297115,
|
||||||
"narHash": "sha256-BZWCi9ZRJiARTuKTbbtvFTj7t1TK4G3UEckT3HyNfRg=",
|
"narHash": "sha256-Z+vUNbfd2FIKkWOTkcT7RYlh3oFCnig/d2eXD1SWf2E=",
|
||||||
"owner": "nixos",
|
"owner": "nixos",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "062346a6d85bc4b49dfaa61c986e9c5be21217d1",
|
"rev": "a3116115851d68b8952a2a4221cc25a84e56b532",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@@ -72,11 +72,11 @@
|
|||||||
},
|
},
|
||||||
"nixpkgs-stable_2": {
|
"nixpkgs-stable_2": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1787753485,
|
"lastModified": 1788297115,
|
||||||
"narHash": "sha256-BZWCi9ZRJiARTuKTbbtvFTj7t1TK4G3UEckT3HyNfRg=",
|
"narHash": "sha256-Z+vUNbfd2FIKkWOTkcT7RYlh3oFCnig/d2eXD1SWf2E=",
|
||||||
"owner": "nixos",
|
"owner": "nixos",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "062346a6d85bc4b49dfaa61c986e9c5be21217d1",
|
"rev": "a3116115851d68b8952a2a4221cc25a84e56b532",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@@ -88,11 +88,11 @@
|
|||||||
},
|
},
|
||||||
"nixpkgs_2": {
|
"nixpkgs_2": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1787498568,
|
"lastModified": 1788179007,
|
||||||
"narHash": "sha256-9i/VTdusq/+NM/tz+J1Re+ojkMB8MBf0QshnYfzHz30=",
|
"narHash": "sha256-hn1oU2rue2SYK8dAr8+WNZWtbsz1S2W5mnHlSEuh3bo=",
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "56c02bc00adcf003215cc4bd996d6efaf4cff188",
|
"rev": "34ab99075ac4f7e40cf037eef32cb1c360bb85e9",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@@ -104,11 +104,11 @@
|
|||||||
},
|
},
|
||||||
"nixpkgs_3": {
|
"nixpkgs_3": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1787364730,
|
"lastModified": 1787631388,
|
||||||
"narHash": "sha256-NcYt9QJfpJiF1lAyN8BDPB4EeScbPU+EwQqPiBElrpU=",
|
"narHash": "sha256-vMiXptXarfSdJb1Gkc+FYVOAibuBRj7qxGa8z68q1Uw=",
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "a831408e6378bc02ebf8cc09b52c96ca86f6bab4",
|
"rev": "ac6b2166e7a9375683b8e98f860f273222337b16",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@@ -120,11 +120,11 @@
|
|||||||
},
|
},
|
||||||
"nixpkgs_4": {
|
"nixpkgs_4": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1787736819,
|
"lastModified": 1788179007,
|
||||||
"narHash": "sha256-cV5xEJJK3BvhU8rEd4mC9UsmDi5qscv/kzGPhBRC5WA=",
|
"narHash": "sha256-hn1oU2rue2SYK8dAr8+WNZWtbsz1S2W5mnHlSEuh3bo=",
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "9fbb54b33e91ee4ca368e35a78e0613c720600b3",
|
"rev": "34ab99075ac4f7e40cf037eef32cb1c360bb85e9",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@@ -141,11 +141,11 @@
|
|||||||
"systems": "systems"
|
"systems": "systems"
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1787691219,
|
"lastModified": 1788190018,
|
||||||
"narHash": "sha256-CjeJTOjrluiDuL0W/YBFkSBOQjBYmdKwj7hWAJ4PIh0=",
|
"narHash": "sha256-59BAfH0txPAZrPBF4QJqwvUWppD+ICrcjA1LZAmPnrQ=",
|
||||||
"owner": "nix-community",
|
"owner": "nix-community",
|
||||||
"repo": "nixvim",
|
"repo": "nixvim",
|
||||||
"rev": "ebec1ae277a50b16e7d6682edd009ef585d68261",
|
"rev": "41844750e55f17b1385d5b09ca7ade5f11f49506",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@@ -169,11 +169,11 @@
|
|||||||
"nixpkgs-stable": "nixpkgs-stable_2"
|
"nixpkgs-stable": "nixpkgs-stable_2"
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1788225336,
|
"lastModified": 1788378694,
|
||||||
"narHash": "sha256-ixw/ChkLWWrLOzoiSa9n1g2g5KDIVkedC6eYFCba+gA=",
|
"narHash": "sha256-s2yvGC1IHrQq2jP4KSbV2TA9Gh1T/YkcS+9neS/WcVI=",
|
||||||
"owner": "naturallaw777",
|
"owner": "naturallaw777",
|
||||||
"repo": "Sovran_Bitcoin",
|
"repo": "Sovran_Bitcoin",
|
||||||
"rev": "37caecaa3f3666231c8ec82a9a9a0df53fa40910",
|
"rev": "b4678fcc712da9dd01c167f62275192183490085",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
|||||||
@@ -19,6 +19,24 @@
|
|||||||
system = prev.stdenv.hostPlatform.system;
|
system = prev.stdenv.hostPlatform.system;
|
||||||
config.allowUnfree = true;
|
config.allowUnfree = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
# Pin LiveKit to 1.13.6: element-calling.nix sets
|
||||||
|
# rtc.advertise_internal_ip, which gives LAN callers a host candidate
|
||||||
|
# so calls work on Wi-Fi without the router needing NAT-hairpin. That
|
||||||
|
# flag is only honoured when node_ip is set manually from LiveKit
|
||||||
|
# v1.13.6 (mediatransportutil f234b53); nixpkgs-unstable currently
|
||||||
|
# ships 1.13.5. Remove this override once nixpkgs-unstable reaches
|
||||||
|
# >= 1.13.6.
|
||||||
|
livekit = prev.livekit.overrideAttrs (old: {
|
||||||
|
version = "1.13.6";
|
||||||
|
src = prev.fetchFromGitHub {
|
||||||
|
owner = "livekit";
|
||||||
|
repo = "livekit";
|
||||||
|
rev = "v1.13.6";
|
||||||
|
hash = "sha256-sUAx6ooeEUUqot5xuZv7xiQa3DdRFVULteTwYgFUzCI=";
|
||||||
|
};
|
||||||
|
vendorHash = "sha256-nOGSmoNuQQm/sIVI1HojsiS4GkbhA68uYMQ6X7d4a5Q=";
|
||||||
|
});
|
||||||
};
|
};
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -185,6 +185,14 @@ EOF
|
|||||||
fi
|
fi
|
||||||
echo "Detected primary network interface: $IFACE"
|
echo "Detected primary network interface: $IFACE"
|
||||||
|
|
||||||
|
# Derive the LAN subnet this box sits on so the embedded TURN relay
|
||||||
|
# is allowed to hand media to LiveKit's LAN host candidate (see the
|
||||||
|
# allow_restricted_peer_cidrs block below). Computed from the primary
|
||||||
|
# interface's own address, so it always matches the subnet the LAN
|
||||||
|
# clients (phones on Wi-Fi) actually live on.
|
||||||
|
LAN_CIDR=$(ip -4 -o addr show dev "$IFACE" | awk '{print $4}' | grep -vE '^(127\.|169\.254\.)' | head -n1 | python3 -c 'import sys, ipaddress; s = sys.stdin.read().strip(); print(str(ipaddress.ip_network(s, strict=False)) if s else "")' 2>/dev/null)
|
||||||
|
if [ -n "$LAN_CIDR" ]; then echo "Derived LAN CIDR for TURN relay: $LAN_CIDR"; else echo "Derived LAN CIDR for TURN relay: <none>"; fi
|
||||||
|
|
||||||
# Generate the full LiveKit config the daemon will load. turn.domain and
|
# Generate the full LiveKit config the daemon will load. turn.domain and
|
||||||
# rtc.interfaces.includes are only known at runtime, so they are
|
# rtc.interfaces.includes are only known at runtime, so they are
|
||||||
# substituted here. The cert/key paths point at the LoadCredential-staged
|
# substituted here. The cert/key paths point at the LoadCredential-staged
|
||||||
@@ -229,10 +237,9 @@ port: 7880
|
|||||||
rtc:
|
rtc:
|
||||||
use_external_ip: false
|
use_external_ip: false
|
||||||
node_ip: $PUBLIC_IP
|
node_ip: $PUBLIC_IP
|
||||||
|
advertise_internal_ip: true
|
||||||
tcp_port: 7881
|
tcp_port: 7881
|
||||||
udp_port: 7882
|
udp_port: 7882
|
||||||
port_range_start: 30000
|
|
||||||
port_range_end: 40000
|
|
||||||
interfaces:
|
interfaces:
|
||||||
includes:
|
includes:
|
||||||
- $IFACE
|
- $IFACE
|
||||||
@@ -244,10 +251,9 @@ port: 7880
|
|||||||
rtc:
|
rtc:
|
||||||
use_external_ip: true
|
use_external_ip: true
|
||||||
skip_external_ip_validation: true
|
skip_external_ip_validation: true
|
||||||
|
advertise_internal_ip: true
|
||||||
tcp_port: 7881
|
tcp_port: 7881
|
||||||
udp_port: 7882
|
udp_port: 7882
|
||||||
port_range_start: 30000
|
|
||||||
port_range_end: 40000
|
|
||||||
interfaces:
|
interfaces:
|
||||||
includes:
|
includes:
|
||||||
- $IFACE
|
- $IFACE
|
||||||
@@ -264,16 +270,37 @@ EOF
|
|||||||
# vhost (/livekit/jwt/sfu_webhook → 8073).
|
# vhost (/livekit/jwt/sfu_webhook → 8073).
|
||||||
LK_KEY=$(cut -d: -f1 < ${livekitKeyFile} | tr -d '[:space:]')
|
LK_KEY=$(cut -d: -f1 < ${livekitKeyFile} | tr -d '[:space:]')
|
||||||
|
|
||||||
|
# TURN/TLS is intentionally not configured (no tls_port): LiveKit
|
||||||
|
# advertises turns:<domain>:443 to clients regardless of tls_port, so
|
||||||
|
# a 5349 TURN/TLS listener would be unreachable and only adds attack
|
||||||
|
# surface. The staged cert/key stay for a future TURN/TLS-on-443
|
||||||
|
# (Caddy layer4 SNI) setup.
|
||||||
cat >> /run/livekit/livekit.yaml <<EOF
|
cat >> /run/livekit/livekit.yaml <<EOF
|
||||||
room:
|
room:
|
||||||
auto_create: false
|
auto_create: false
|
||||||
turn:
|
turn:
|
||||||
enabled: true
|
enabled: true
|
||||||
domain: $MATRIX
|
domain: $MATRIX
|
||||||
tls_port: 5349
|
|
||||||
udp_port: 3478
|
udp_port: 3478
|
||||||
|
relay_range_start: 40000
|
||||||
|
relay_range_end: 40099
|
||||||
cert_file: /run/credentials/livekit.service/turn-cert
|
cert_file: /run/credentials/livekit.service/turn-cert
|
||||||
key_file: /run/credentials/livekit.service/turn-key
|
key_file: /run/credentials/livekit.service/turn-key
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# By default the embedded TURN relay refuses to send media to
|
||||||
|
# private/loopback peers. That would force its final hop to the
|
||||||
|
# public/WAN IP (hairpin NAT) — exactly what breaks calls on routers
|
||||||
|
# without NAT loopback. Allow the LAN subnet so the relay can deliver
|
||||||
|
# directly to LiveKit's LAN host candidate instead.
|
||||||
|
if [ -n "$LAN_CIDR" ]; then
|
||||||
|
cat >> /run/livekit/livekit.yaml <<EOF
|
||||||
|
allow_restricted_peer_cidrs:
|
||||||
|
- $LAN_CIDR
|
||||||
|
EOF
|
||||||
|
fi
|
||||||
|
|
||||||
|
cat >> /run/livekit/livekit.yaml <<EOF
|
||||||
webhook:
|
webhook:
|
||||||
api_key: $LK_KEY
|
api_key: $LK_KEY
|
||||||
urls:
|
urls:
|
||||||
@@ -315,10 +342,14 @@ EOF
|
|||||||
"turn-key:/var/lib/livekit/turn.key"
|
"turn-key:/var/lib/livekit/turn.key"
|
||||||
];
|
];
|
||||||
|
|
||||||
networking.firewall.allowedTCPPorts = [ 5349 7881 ];
|
# 5349/TCP (TURN/TLS) is deliberately absent — see livekit-turn-setup. RTC
|
||||||
|
# media uses the single UDP mux (7882); the 30000-40000 range is gone so
|
||||||
|
# media is no longer spread across 10000 ports. The TURN relay allocation
|
||||||
|
# range (40000-40099) is kept separate from the media mux.
|
||||||
|
networking.firewall.allowedTCPPorts = [ 7881 ];
|
||||||
networking.firewall.allowedUDPPorts = [ 3478 7882 ];
|
networking.firewall.allowedUDPPorts = [ 3478 7882 ];
|
||||||
networking.firewall.allowedUDPPortRanges = [
|
networking.firewall.allowedUDPPortRanges = [
|
||||||
{ from = 30000; to = 40000; } # LiveKit internal TURN relay range
|
{ from = 40000; to = 40099; } # LiveKit embedded TURN relay allocation range
|
||||||
];
|
];
|
||||||
|
|
||||||
####### JWT SERVICE RUNTIME CONFIG #######
|
####### JWT SERVICE RUNTIME CONFIG #######
|
||||||
|
|||||||
Reference in New Issue
Block a user