rtlinux 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- rtlinux-0.1.0/LICENSE +17 -0
- rtlinux-0.1.0/PKG-INFO +163 -0
- rtlinux-0.1.0/README.md +136 -0
- rtlinux-0.1.0/pyproject.toml +45 -0
- rtlinux-0.1.0/setup.cfg +4 -0
- rtlinux-0.1.0/src/rtlinux/__init__.py +317 -0
- rtlinux-0.1.0/src/rtlinux.egg-info/PKG-INFO +163 -0
- rtlinux-0.1.0/src/rtlinux.egg-info/SOURCES.txt +9 -0
- rtlinux-0.1.0/src/rtlinux.egg-info/dependency_links.txt +1 -0
- rtlinux-0.1.0/src/rtlinux.egg-info/entry_points.txt +5 -0
- rtlinux-0.1.0/src/rtlinux.egg-info/top_level.txt +1 -0
rtlinux-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
Apache License
|
|
2
|
+
Version 2.0, January 2004
|
|
3
|
+
http://www.apache.org/licenses/
|
|
4
|
+
|
|
5
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
you may not use this file except in compliance with the License.
|
|
7
|
+
You may obtain a copy of the License at
|
|
8
|
+
|
|
9
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
|
|
11
|
+
Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
See the License for the specific language governing permissions and
|
|
15
|
+
limitations under the License.
|
|
16
|
+
|
|
17
|
+
Copyright 2024-2026 MeshPOP
|
rtlinux-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: rtlinux
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: MeshPOP Runtime Linux — L0 node OS for AI infrastructure mesh
|
|
5
|
+
Author-email: MeshPOP <meshpop@proton.me>
|
|
6
|
+
License: Apache-2.0
|
|
7
|
+
Project-URL: Homepage, https://mpop.dev
|
|
8
|
+
Project-URL: Repository, https://github.com/meshpop/rtlinux
|
|
9
|
+
Project-URL: Documentation, https://mpop.dev/docs/
|
|
10
|
+
Project-URL: Issues, https://github.com/meshpop/rtlinux/issues
|
|
11
|
+
Keywords: meshpop,runtime,linux,buildroot,wireguard,mesh,infrastructure,ai,mcp,distributed,vssh,orchestration,node-os,l0
|
|
12
|
+
Classifier: Development Status :: 3 - Alpha
|
|
13
|
+
Classifier: Intended Audience :: System Administrators
|
|
14
|
+
Classifier: Intended Audience :: Developers
|
|
15
|
+
Classifier: License :: OSI Approved :: Apache Software License
|
|
16
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
17
|
+
Classifier: Operating System :: MacOS
|
|
18
|
+
Classifier: Programming Language :: Python :: 3
|
|
19
|
+
Classifier: Topic :: System :: Operating System
|
|
20
|
+
Classifier: Topic :: System :: Systems Administration
|
|
21
|
+
Classifier: Topic :: System :: Clustering
|
|
22
|
+
Classifier: Topic :: System :: Networking
|
|
23
|
+
Requires-Python: >=3.8
|
|
24
|
+
Description-Content-Type: text/markdown
|
|
25
|
+
License-File: LICENSE
|
|
26
|
+
Dynamic: license-file
|
|
27
|
+
|
|
28
|
+
# rtlinux — MeshPOP Runtime Linux
|
|
29
|
+
|
|
30
|
+
**Layer 0 of the MeshPOP stack.** A Buildroot-based minimal Linux distribution purpose-built for AI infrastructure mesh nodes.
|
|
31
|
+
|
|
32
|
+
```
|
|
33
|
+
L0 rtlinux — Runtime OS (kernel + musl + busybox + MeshPOP)
|
|
34
|
+
L1 Wire — WireGuard mesh VPN (pip install meshpop-wire)
|
|
35
|
+
L2 vssh — Secure remote execution (pip install vssh)
|
|
36
|
+
L3 mpop — Fleet orchestration (pip install meshpop)
|
|
37
|
+
L4 MeshDB — Distributed search (pip install meshpop-db)
|
|
38
|
+
L5 Vault — Secrets management (pip install sv-vault)
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## What It Does
|
|
42
|
+
|
|
43
|
+
Builds a minimal, network-hardened Linux OS with the full MeshPOP tool suite pre-installed. Boot a node → it auto-joins the Wire mesh → instantly manageable via `mpop exec`, `mpop deploy`, `mpop ask`.
|
|
44
|
+
|
|
45
|
+
**Like Talos Linux for Kubernetes, but for MeshPOP.**
|
|
46
|
+
|
|
47
|
+
## Install
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
pip install rtlinux
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Quick Start
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
# Build runtime image (Buildroot — from source, zero dependencies)
|
|
57
|
+
rtlinux build --method buildroot
|
|
58
|
+
|
|
59
|
+
# Deploy to a new node
|
|
60
|
+
rtlinux deploy g5 --image output/meshpoplinux-rootfs.tar.gz
|
|
61
|
+
|
|
62
|
+
# Verify all nodes
|
|
63
|
+
rtlinux verify --all
|
|
64
|
+
|
|
65
|
+
# Full CI/CD loop: build → deploy → verify → fix
|
|
66
|
+
rtlinux loop --nodes "g1 g2 g3 d1 d2"
|
|
67
|
+
|
|
68
|
+
# Fleet status
|
|
69
|
+
rtlinux status
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## Build Methods
|
|
73
|
+
|
|
74
|
+
| Method | Dependencies | Time | Output |
|
|
75
|
+
|--------|-------------|------|--------|
|
|
76
|
+
| **Buildroot** (recommended) | None — kernel+BusyBox+musl from source | 20-60 min | bzImage + rootfs.cpio |
|
|
77
|
+
| Alpine | Docker | ~2 min | rootfs.tar.gz |
|
|
78
|
+
| Scratch | Linux host or Docker | ~1 min | rootfs.tar.gz |
|
|
79
|
+
|
|
80
|
+
## MCP Server
|
|
81
|
+
|
|
82
|
+
rtlinux includes an MCP server for AI-driven node management:
|
|
83
|
+
|
|
84
|
+
```json
|
|
85
|
+
{
|
|
86
|
+
"mcpServers": {
|
|
87
|
+
"rtlinux": {
|
|
88
|
+
"command": "python3",
|
|
89
|
+
"args": ["-m", "rtlinux.mcp.rtlinux_mcp_server"]
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### MCP Tools
|
|
96
|
+
|
|
97
|
+
| Tool | Description |
|
|
98
|
+
|------|-------------|
|
|
99
|
+
| `rtlinux_build` | Build runtime image |
|
|
100
|
+
| `rtlinux_deploy` | Deploy to a node |
|
|
101
|
+
| `rtlinux_verify` | Health check (all 5 layers) |
|
|
102
|
+
| `rtlinux_fleet` | Fleet status overview |
|
|
103
|
+
| `rtlinux_fix` | Auto-fix degraded node |
|
|
104
|
+
| `rtlinux_cicd` | Full CI/CD loop |
|
|
105
|
+
|
|
106
|
+
## Python API
|
|
107
|
+
|
|
108
|
+
```python
|
|
109
|
+
import rtlinux
|
|
110
|
+
|
|
111
|
+
# Build
|
|
112
|
+
result = rtlinux.build(method="buildroot")
|
|
113
|
+
|
|
114
|
+
# Deploy
|
|
115
|
+
result = rtlinux.deploy("g5")
|
|
116
|
+
|
|
117
|
+
# Verify single node
|
|
118
|
+
health = rtlinux.verify("g1")
|
|
119
|
+
# → {"status": "healthy", "layers_ok": "5/5", ...}
|
|
120
|
+
|
|
121
|
+
# Verify fleet
|
|
122
|
+
fleet = rtlinux.verify_fleet(["g1", "g2", "d1", "d2"])
|
|
123
|
+
# → {"summary": "4/4 healthy", "fleet": {...}}
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
## Architecture
|
|
127
|
+
|
|
128
|
+
```
|
|
129
|
+
┌────────────────────────────────────────────────┐
|
|
130
|
+
│ rtlinux Node │
|
|
131
|
+
│ │
|
|
132
|
+
│ kernel (Buildroot-compiled) │
|
|
133
|
+
│ └─ WireGuard (mesh VPN, auto-peering) │
|
|
134
|
+
│ └─ vssh daemon (remote execution) │
|
|
135
|
+
│ └─ mpop agent (orchestration) │
|
|
136
|
+
│ └─ MeshDB indexer (file search) │
|
|
137
|
+
│ └─ minimal userspace (BusyBox + musl) │
|
|
138
|
+
│ │
|
|
139
|
+
│ No SSH. No package manager. No systemd. │
|
|
140
|
+
│ Just MeshPOP. │
|
|
141
|
+
└────────────────────────────────────────────────┘
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
## The MeshPOP Stack
|
|
145
|
+
|
|
146
|
+
| Layer | Package | PyPI |
|
|
147
|
+
|-------|---------|------|
|
|
148
|
+
| L0 | **rtlinux** | `pip install rtlinux` |
|
|
149
|
+
| L1 | Wire | `pip install meshpop-wire` |
|
|
150
|
+
| L2 | vssh | `pip install vssh` |
|
|
151
|
+
| L3 | mpop | `pip install meshpop` |
|
|
152
|
+
| L4 | MeshDB | `pip install meshpop-db` |
|
|
153
|
+
| L5 | Vault | `pip install sv-vault` |
|
|
154
|
+
|
|
155
|
+
## Links
|
|
156
|
+
|
|
157
|
+
- **Homepage**: [mpop.dev](https://mpop.dev)
|
|
158
|
+
- **GitHub**: [github.com/meshpop/rtlinux](https://github.com/meshpop/rtlinux)
|
|
159
|
+
- **All repos**: [github.com/meshpop](https://github.com/meshpop)
|
|
160
|
+
|
|
161
|
+
## License
|
|
162
|
+
|
|
163
|
+
Apache-2.0
|
rtlinux-0.1.0/README.md
ADDED
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
# rtlinux — MeshPOP Runtime Linux
|
|
2
|
+
|
|
3
|
+
**Layer 0 of the MeshPOP stack.** A Buildroot-based minimal Linux distribution purpose-built for AI infrastructure mesh nodes.
|
|
4
|
+
|
|
5
|
+
```
|
|
6
|
+
L0 rtlinux — Runtime OS (kernel + musl + busybox + MeshPOP)
|
|
7
|
+
L1 Wire — WireGuard mesh VPN (pip install meshpop-wire)
|
|
8
|
+
L2 vssh — Secure remote execution (pip install vssh)
|
|
9
|
+
L3 mpop — Fleet orchestration (pip install meshpop)
|
|
10
|
+
L4 MeshDB — Distributed search (pip install meshpop-db)
|
|
11
|
+
L5 Vault — Secrets management (pip install sv-vault)
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
## What It Does
|
|
15
|
+
|
|
16
|
+
Builds a minimal, network-hardened Linux OS with the full MeshPOP tool suite pre-installed. Boot a node → it auto-joins the Wire mesh → instantly manageable via `mpop exec`, `mpop deploy`, `mpop ask`.
|
|
17
|
+
|
|
18
|
+
**Like Talos Linux for Kubernetes, but for MeshPOP.**
|
|
19
|
+
|
|
20
|
+
## Install
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
pip install rtlinux
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Quick Start
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
# Build runtime image (Buildroot — from source, zero dependencies)
|
|
30
|
+
rtlinux build --method buildroot
|
|
31
|
+
|
|
32
|
+
# Deploy to a new node
|
|
33
|
+
rtlinux deploy g5 --image output/meshpoplinux-rootfs.tar.gz
|
|
34
|
+
|
|
35
|
+
# Verify all nodes
|
|
36
|
+
rtlinux verify --all
|
|
37
|
+
|
|
38
|
+
# Full CI/CD loop: build → deploy → verify → fix
|
|
39
|
+
rtlinux loop --nodes "g1 g2 g3 d1 d2"
|
|
40
|
+
|
|
41
|
+
# Fleet status
|
|
42
|
+
rtlinux status
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## Build Methods
|
|
46
|
+
|
|
47
|
+
| Method | Dependencies | Time | Output |
|
|
48
|
+
|--------|-------------|------|--------|
|
|
49
|
+
| **Buildroot** (recommended) | None — kernel+BusyBox+musl from source | 20-60 min | bzImage + rootfs.cpio |
|
|
50
|
+
| Alpine | Docker | ~2 min | rootfs.tar.gz |
|
|
51
|
+
| Scratch | Linux host or Docker | ~1 min | rootfs.tar.gz |
|
|
52
|
+
|
|
53
|
+
## MCP Server
|
|
54
|
+
|
|
55
|
+
rtlinux includes an MCP server for AI-driven node management:
|
|
56
|
+
|
|
57
|
+
```json
|
|
58
|
+
{
|
|
59
|
+
"mcpServers": {
|
|
60
|
+
"rtlinux": {
|
|
61
|
+
"command": "python3",
|
|
62
|
+
"args": ["-m", "rtlinux.mcp.rtlinux_mcp_server"]
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### MCP Tools
|
|
69
|
+
|
|
70
|
+
| Tool | Description |
|
|
71
|
+
|------|-------------|
|
|
72
|
+
| `rtlinux_build` | Build runtime image |
|
|
73
|
+
| `rtlinux_deploy` | Deploy to a node |
|
|
74
|
+
| `rtlinux_verify` | Health check (all 5 layers) |
|
|
75
|
+
| `rtlinux_fleet` | Fleet status overview |
|
|
76
|
+
| `rtlinux_fix` | Auto-fix degraded node |
|
|
77
|
+
| `rtlinux_cicd` | Full CI/CD loop |
|
|
78
|
+
|
|
79
|
+
## Python API
|
|
80
|
+
|
|
81
|
+
```python
|
|
82
|
+
import rtlinux
|
|
83
|
+
|
|
84
|
+
# Build
|
|
85
|
+
result = rtlinux.build(method="buildroot")
|
|
86
|
+
|
|
87
|
+
# Deploy
|
|
88
|
+
result = rtlinux.deploy("g5")
|
|
89
|
+
|
|
90
|
+
# Verify single node
|
|
91
|
+
health = rtlinux.verify("g1")
|
|
92
|
+
# → {"status": "healthy", "layers_ok": "5/5", ...}
|
|
93
|
+
|
|
94
|
+
# Verify fleet
|
|
95
|
+
fleet = rtlinux.verify_fleet(["g1", "g2", "d1", "d2"])
|
|
96
|
+
# → {"summary": "4/4 healthy", "fleet": {...}}
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
## Architecture
|
|
100
|
+
|
|
101
|
+
```
|
|
102
|
+
┌────────────────────────────────────────────────┐
|
|
103
|
+
│ rtlinux Node │
|
|
104
|
+
│ │
|
|
105
|
+
│ kernel (Buildroot-compiled) │
|
|
106
|
+
│ └─ WireGuard (mesh VPN, auto-peering) │
|
|
107
|
+
│ └─ vssh daemon (remote execution) │
|
|
108
|
+
│ └─ mpop agent (orchestration) │
|
|
109
|
+
│ └─ MeshDB indexer (file search) │
|
|
110
|
+
│ └─ minimal userspace (BusyBox + musl) │
|
|
111
|
+
│ │
|
|
112
|
+
│ No SSH. No package manager. No systemd. │
|
|
113
|
+
│ Just MeshPOP. │
|
|
114
|
+
└────────────────────────────────────────────────┘
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
## The MeshPOP Stack
|
|
118
|
+
|
|
119
|
+
| Layer | Package | PyPI |
|
|
120
|
+
|-------|---------|------|
|
|
121
|
+
| L0 | **rtlinux** | `pip install rtlinux` |
|
|
122
|
+
| L1 | Wire | `pip install meshpop-wire` |
|
|
123
|
+
| L2 | vssh | `pip install vssh` |
|
|
124
|
+
| L3 | mpop | `pip install meshpop` |
|
|
125
|
+
| L4 | MeshDB | `pip install meshpop-db` |
|
|
126
|
+
| L5 | Vault | `pip install sv-vault` |
|
|
127
|
+
|
|
128
|
+
## Links
|
|
129
|
+
|
|
130
|
+
- **Homepage**: [mpop.dev](https://mpop.dev)
|
|
131
|
+
- **GitHub**: [github.com/meshpop/rtlinux](https://github.com/meshpop/rtlinux)
|
|
132
|
+
- **All repos**: [github.com/meshpop](https://github.com/meshpop)
|
|
133
|
+
|
|
134
|
+
## License
|
|
135
|
+
|
|
136
|
+
Apache-2.0
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=68.0", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "rtlinux"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "MeshPOP Runtime Linux — L0 node OS for AI infrastructure mesh"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
license = {text = "Apache-2.0"}
|
|
11
|
+
requires-python = ">=3.8"
|
|
12
|
+
authors = [{name = "MeshPOP", email = "meshpop@proton.me"}]
|
|
13
|
+
keywords = [
|
|
14
|
+
"meshpop", "runtime", "linux", "buildroot", "wireguard",
|
|
15
|
+
"mesh", "infrastructure", "ai", "mcp", "distributed",
|
|
16
|
+
"vssh", "orchestration", "node-os", "l0"
|
|
17
|
+
]
|
|
18
|
+
classifiers = [
|
|
19
|
+
"Development Status :: 3 - Alpha",
|
|
20
|
+
"Intended Audience :: System Administrators",
|
|
21
|
+
"Intended Audience :: Developers",
|
|
22
|
+
"License :: OSI Approved :: Apache Software License",
|
|
23
|
+
"Operating System :: POSIX :: Linux",
|
|
24
|
+
"Operating System :: MacOS",
|
|
25
|
+
"Programming Language :: Python :: 3",
|
|
26
|
+
"Topic :: System :: Operating System",
|
|
27
|
+
"Topic :: System :: Systems Administration",
|
|
28
|
+
"Topic :: System :: Clustering",
|
|
29
|
+
"Topic :: System :: Networking",
|
|
30
|
+
]
|
|
31
|
+
|
|
32
|
+
[project.urls]
|
|
33
|
+
Homepage = "https://mpop.dev"
|
|
34
|
+
Repository = "https://github.com/meshpop/rtlinux"
|
|
35
|
+
Documentation = "https://mpop.dev/docs/"
|
|
36
|
+
Issues = "https://github.com/meshpop/rtlinux/issues"
|
|
37
|
+
|
|
38
|
+
[project.scripts]
|
|
39
|
+
rtlinux = "rtlinux:main"
|
|
40
|
+
|
|
41
|
+
[project.entry-points."meshpop.mcp"]
|
|
42
|
+
rtlinux = "rtlinux.mcp.rtlinux_mcp_server"
|
|
43
|
+
|
|
44
|
+
[tool.setuptools.packages.find]
|
|
45
|
+
where = ["src"]
|
rtlinux-0.1.0/setup.cfg
ADDED
|
@@ -0,0 +1,317 @@
|
|
|
1
|
+
"""
|
|
2
|
+
rtlinux — MeshPOP Runtime Linux (L0)
|
|
3
|
+
====================================
|
|
4
|
+
|
|
5
|
+
MeshPOP-native runtime OS for AI infrastructure nodes.
|
|
6
|
+
Buildroot-based minimal Linux: boot → wire connect → vssh listen → ready.
|
|
7
|
+
|
|
8
|
+
Layer 0 of the MeshPOP stack:
|
|
9
|
+
|
|
10
|
+
L0 rtlinux — Runtime OS (kernel + musl + busybox + MeshPOP)
|
|
11
|
+
L1 Wire — WireGuard mesh VPN
|
|
12
|
+
L2 vssh — Secure remote execution
|
|
13
|
+
L3 mpop — Fleet orchestration
|
|
14
|
+
L4 MeshDB — Distributed search
|
|
15
|
+
L5 Vault — Secrets management
|
|
16
|
+
|
|
17
|
+
Usage::
|
|
18
|
+
|
|
19
|
+
# Build runtime image
|
|
20
|
+
rtlinux build --method buildroot
|
|
21
|
+
|
|
22
|
+
# Deploy to new node
|
|
23
|
+
rtlinux deploy g5 --image meshpoplinux-rootfs.tar.gz
|
|
24
|
+
|
|
25
|
+
# Verify fleet health
|
|
26
|
+
rtlinux verify --all
|
|
27
|
+
|
|
28
|
+
# Full CI/CD loop
|
|
29
|
+
rtlinux loop --nodes "g1 g2 g3 d1 d2"
|
|
30
|
+
|
|
31
|
+
Install::
|
|
32
|
+
|
|
33
|
+
pip install rtlinux
|
|
34
|
+
|
|
35
|
+
Links:
|
|
36
|
+
- GitHub: https://github.com/meshpop/rtlinux
|
|
37
|
+
- Docs: https://mpop.dev
|
|
38
|
+
- PyPI: https://pypi.org/project/rtlinux/
|
|
39
|
+
"""
|
|
40
|
+
|
|
41
|
+
__version__ = "0.1.0"
|
|
42
|
+
__author__ = "MeshPOP"
|
|
43
|
+
__license__ = "Apache-2.0"
|
|
44
|
+
|
|
45
|
+
import os
|
|
46
|
+
import sys
|
|
47
|
+
import json
|
|
48
|
+
import base64
|
|
49
|
+
import subprocess
|
|
50
|
+
from pathlib import Path
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
# ── Config ──────────────────────────────────────────────────────────
|
|
54
|
+
RTLINUX_DIR = os.environ.get("RTLINUX_DIR", os.path.expanduser("~/meshpoplinux"))
|
|
55
|
+
BUILD_METHODS = ["buildroot", "alpine", "scratch"]
|
|
56
|
+
DEFAULT_METHOD = "buildroot"
|
|
57
|
+
|
|
58
|
+
MESHPOP_PACKAGES = ["meshpop", "vssh", "meshpop-wire", "meshpop-db", "sv-vault"]
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def _vssh_exec(node: str, cmd: str) -> str:
|
|
62
|
+
"""Execute command on remote node via vssh Python module."""
|
|
63
|
+
try:
|
|
64
|
+
import vssh
|
|
65
|
+
import io
|
|
66
|
+
old = sys.stdout
|
|
67
|
+
sys.stdout = buf = io.StringIO()
|
|
68
|
+
vssh.ssh(node, cmd)
|
|
69
|
+
sys.stdout = old
|
|
70
|
+
return buf.getvalue().strip()
|
|
71
|
+
except ImportError:
|
|
72
|
+
# Fallback to CLI
|
|
73
|
+
r = subprocess.run(
|
|
74
|
+
["vssh", "exec", node, cmd],
|
|
75
|
+
capture_output=True, text=True, timeout=30
|
|
76
|
+
)
|
|
77
|
+
return r.stdout.strip()
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
def _vssh_put(local_path: str, node: str, remote_path: str) -> bool:
|
|
81
|
+
"""Upload file to remote node via vssh."""
|
|
82
|
+
try:
|
|
83
|
+
import vssh
|
|
84
|
+
vssh.put(local_path, node, remote_path)
|
|
85
|
+
return True
|
|
86
|
+
except ImportError:
|
|
87
|
+
r = subprocess.run(
|
|
88
|
+
["vssh", "put", local_path, f"{node}:{remote_path}"],
|
|
89
|
+
capture_output=True, text=True, timeout=120
|
|
90
|
+
)
|
|
91
|
+
return r.returncode == 0
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
# ── Build ───────────────────────────────────────────────────────────
|
|
95
|
+
def build(method: str = DEFAULT_METHOD, output_dir: str = None) -> dict:
|
|
96
|
+
"""Build meshpoplinux runtime image.
|
|
97
|
+
|
|
98
|
+
Args:
|
|
99
|
+
method: Build method (buildroot, alpine, scratch)
|
|
100
|
+
output_dir: Output directory for artifacts
|
|
101
|
+
|
|
102
|
+
Returns:
|
|
103
|
+
dict with build results
|
|
104
|
+
"""
|
|
105
|
+
if method not in BUILD_METHODS:
|
|
106
|
+
return {"error": f"Unknown method: {method}. Use: {BUILD_METHODS}"}
|
|
107
|
+
|
|
108
|
+
output_dir = output_dir or os.path.join(RTLINUX_DIR, "output")
|
|
109
|
+
os.makedirs(output_dir, exist_ok=True)
|
|
110
|
+
|
|
111
|
+
scripts = {
|
|
112
|
+
"buildroot": "scripts/build-buildroot.sh",
|
|
113
|
+
"alpine": "scripts/build-docker.sh",
|
|
114
|
+
"scratch": "scripts/build-from-scratch.sh",
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
script = os.path.join(RTLINUX_DIR, scripts[method])
|
|
118
|
+
if not os.path.exists(script):
|
|
119
|
+
return {"error": f"Build script not found: {script}"}
|
|
120
|
+
|
|
121
|
+
r = subprocess.run(
|
|
122
|
+
["bash", script, output_dir],
|
|
123
|
+
capture_output=True, text=True, timeout=3600
|
|
124
|
+
)
|
|
125
|
+
|
|
126
|
+
rootfs = os.path.join(output_dir, "meshpoplinux-rootfs.tar.gz")
|
|
127
|
+
if os.path.exists(rootfs):
|
|
128
|
+
size = os.path.getsize(rootfs)
|
|
129
|
+
return {
|
|
130
|
+
"status": "ok",
|
|
131
|
+
"method": method,
|
|
132
|
+
"artifact": rootfs,
|
|
133
|
+
"size_bytes": size,
|
|
134
|
+
"size_human": f"{size / 1024 / 1024:.1f}MB",
|
|
135
|
+
}
|
|
136
|
+
return {"error": "Build failed — rootfs not produced", "output": r.stderr[-500:]}
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
# ── Deploy ──────────────────────────────────────────────────────────
|
|
140
|
+
def deploy(node: str, image: str = None, install_stack: bool = True) -> dict:
|
|
141
|
+
"""Deploy runtime image to a node.
|
|
142
|
+
|
|
143
|
+
Args:
|
|
144
|
+
node: Target node name (g1, d2, etc.)
|
|
145
|
+
image: Path to rootfs image (default: output/meshpoplinux-rootfs.tar.gz)
|
|
146
|
+
install_stack: Whether to install MeshPOP packages
|
|
147
|
+
|
|
148
|
+
Returns:
|
|
149
|
+
dict with deployment results
|
|
150
|
+
"""
|
|
151
|
+
image = image or os.path.join(RTLINUX_DIR, "output", "meshpoplinux-rootfs.tar.gz")
|
|
152
|
+
if not os.path.exists(image):
|
|
153
|
+
return {"error": f"Image not found: {image}. Run: rtlinux build"}
|
|
154
|
+
|
|
155
|
+
results = {"node": node, "steps": []}
|
|
156
|
+
|
|
157
|
+
# Upload
|
|
158
|
+
ok = _vssh_put(image, node, "/tmp/meshpoplinux-rootfs.tar.gz")
|
|
159
|
+
results["steps"].append({"upload": "ok" if ok else "failed"})
|
|
160
|
+
|
|
161
|
+
# Extract
|
|
162
|
+
out = _vssh_exec(node, "mkdir -p /opt/meshpoplinux && tar xzf /tmp/meshpoplinux-rootfs.tar.gz -C /opt/meshpoplinux 2>&1 | tail -3")
|
|
163
|
+
results["steps"].append({"extract": out or "ok"})
|
|
164
|
+
|
|
165
|
+
# Install MeshPOP stack
|
|
166
|
+
if install_stack:
|
|
167
|
+
for pkg in MESHPOP_PACKAGES:
|
|
168
|
+
out = _vssh_exec(node, f"pip3 install --break-system-packages --upgrade {pkg} 2>&1 | tail -1")
|
|
169
|
+
results["steps"].append({pkg: out})
|
|
170
|
+
|
|
171
|
+
# Cleanup
|
|
172
|
+
_vssh_exec(node, "rm -f /tmp/meshpoplinux-rootfs.tar.gz")
|
|
173
|
+
|
|
174
|
+
results["status"] = "ok"
|
|
175
|
+
return results
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
# ── Verify ──────────────────────────────────────────────────────────
|
|
179
|
+
def verify(node: str) -> dict:
|
|
180
|
+
"""Verify a node's health across all 5 MeshPOP layers.
|
|
181
|
+
|
|
182
|
+
Returns:
|
|
183
|
+
dict with check results per layer
|
|
184
|
+
"""
|
|
185
|
+
checks = {"node": node, "layers": {}}
|
|
186
|
+
|
|
187
|
+
# L0: Reachable?
|
|
188
|
+
ping = _vssh_exec(node, "echo pong")
|
|
189
|
+
checks["layers"]["L0_reachable"] = ping == "pong"
|
|
190
|
+
if not checks["layers"]["L0_reachable"]:
|
|
191
|
+
checks["status"] = "unreachable"
|
|
192
|
+
return checks
|
|
193
|
+
|
|
194
|
+
# System info
|
|
195
|
+
checks["hostname"] = _vssh_exec(node, "hostname")
|
|
196
|
+
checks["kernel"] = _vssh_exec(node, "uname -r")
|
|
197
|
+
checks["python"] = _vssh_exec(node, "python3 --version 2>&1")
|
|
198
|
+
|
|
199
|
+
# L1: Wire
|
|
200
|
+
wg = _vssh_exec(node, "ip -4 addr show wg0 2>/dev/null | grep -oP 'inet \\K[0-9./]+'")
|
|
201
|
+
checks["layers"]["L1_wire"] = bool(wg)
|
|
202
|
+
checks["wire_ip"] = wg
|
|
203
|
+
|
|
204
|
+
# L2: vssh
|
|
205
|
+
checks["layers"]["L2_vssh"] = True # Already reachable
|
|
206
|
+
|
|
207
|
+
# L3: mpop packages
|
|
208
|
+
pkg_ok = 0
|
|
209
|
+
for pkg in MESHPOP_PACKAGES:
|
|
210
|
+
ver = _vssh_exec(node, f"python3 -c \"import importlib.metadata; print(importlib.metadata.version('{pkg}'))\" 2>/dev/null")
|
|
211
|
+
checks[f"pkg_{pkg}"] = ver if ver else None
|
|
212
|
+
if ver:
|
|
213
|
+
pkg_ok += 1
|
|
214
|
+
checks["layers"]["L3_mpop"] = pkg_ok >= 3
|
|
215
|
+
|
|
216
|
+
# L4: MeshDB
|
|
217
|
+
mdb = _vssh_exec(node, "python3 -c 'import meshpop_db; print(\"ok\")' 2>&1")
|
|
218
|
+
checks["layers"]["L4_meshdb"] = "ok" in mdb
|
|
219
|
+
|
|
220
|
+
# L5: Vault
|
|
221
|
+
vlt = _vssh_exec(node, "python3 -c 'import sv_vault; print(\"ok\")' 2>&1")
|
|
222
|
+
checks["layers"]["L5_vault"] = "ok" in vlt
|
|
223
|
+
|
|
224
|
+
# Disk
|
|
225
|
+
disk = _vssh_exec(node, "df / | tail -1 | tr -s ' ' | cut -d' ' -f5 | tr -d '%'")
|
|
226
|
+
try:
|
|
227
|
+
checks["disk_pct"] = int(disk)
|
|
228
|
+
except:
|
|
229
|
+
checks["disk_pct"] = None
|
|
230
|
+
|
|
231
|
+
# Overall
|
|
232
|
+
layer_ok = sum(1 for v in checks["layers"].values() if v)
|
|
233
|
+
checks["status"] = "healthy" if layer_ok >= 4 else "degraded" if layer_ok >= 2 else "critical"
|
|
234
|
+
checks["layers_ok"] = f"{layer_ok}/{len(checks['layers'])}"
|
|
235
|
+
|
|
236
|
+
return checks
|
|
237
|
+
|
|
238
|
+
|
|
239
|
+
def verify_fleet(nodes: list) -> dict:
|
|
240
|
+
"""Verify all nodes in the fleet."""
|
|
241
|
+
results = {}
|
|
242
|
+
for node in nodes:
|
|
243
|
+
results[node] = verify(node)
|
|
244
|
+
|
|
245
|
+
healthy = sum(1 for r in results.values() if r.get("status") == "healthy")
|
|
246
|
+
return {
|
|
247
|
+
"fleet": results,
|
|
248
|
+
"summary": f"{healthy}/{len(nodes)} healthy",
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
|
|
252
|
+
# ── CLI ─────────────────────────────────────────────────────────────
|
|
253
|
+
def main():
|
|
254
|
+
"""CLI entry point."""
|
|
255
|
+
import argparse
|
|
256
|
+
|
|
257
|
+
parser = argparse.ArgumentParser(
|
|
258
|
+
prog="rtlinux",
|
|
259
|
+
description="MeshPOP Runtime Linux — L0 node OS management"
|
|
260
|
+
)
|
|
261
|
+
sub = parser.add_subparsers(dest="cmd")
|
|
262
|
+
|
|
263
|
+
# build
|
|
264
|
+
p_build = sub.add_parser("build", help="Build runtime image")
|
|
265
|
+
p_build.add_argument("--method", default=DEFAULT_METHOD, choices=BUILD_METHODS)
|
|
266
|
+
p_build.add_argument("--output", default=None)
|
|
267
|
+
|
|
268
|
+
# deploy
|
|
269
|
+
p_deploy = sub.add_parser("deploy", help="Deploy to a node")
|
|
270
|
+
p_deploy.add_argument("node", help="Target node (g1, d2, etc.)")
|
|
271
|
+
p_deploy.add_argument("--image", default=None)
|
|
272
|
+
p_deploy.add_argument("--no-stack", action="store_true")
|
|
273
|
+
|
|
274
|
+
# verify
|
|
275
|
+
p_verify = sub.add_parser("verify", help="Verify node health")
|
|
276
|
+
p_verify.add_argument("node", nargs="?", help="Node name")
|
|
277
|
+
p_verify.add_argument("--all", action="store_true")
|
|
278
|
+
p_verify.add_argument("--nodes", default="g1 g2 g3 d1 d2")
|
|
279
|
+
|
|
280
|
+
# status
|
|
281
|
+
sub.add_parser("status", help="Fleet status")
|
|
282
|
+
|
|
283
|
+
# version
|
|
284
|
+
sub.add_parser("version", help="Show version")
|
|
285
|
+
|
|
286
|
+
args = parser.parse_args()
|
|
287
|
+
|
|
288
|
+
if args.cmd == "build":
|
|
289
|
+
result = build(method=args.method, output_dir=args.output)
|
|
290
|
+
print(json.dumps(result, indent=2))
|
|
291
|
+
|
|
292
|
+
elif args.cmd == "deploy":
|
|
293
|
+
result = deploy(args.node, image=args.image, install_stack=not args.no_stack)
|
|
294
|
+
print(json.dumps(result, indent=2))
|
|
295
|
+
|
|
296
|
+
elif args.cmd == "verify":
|
|
297
|
+
if args.all or not args.node:
|
|
298
|
+
nodes = args.nodes.split()
|
|
299
|
+
result = verify_fleet(nodes)
|
|
300
|
+
else:
|
|
301
|
+
result = verify(args.node)
|
|
302
|
+
print(json.dumps(result, indent=2))
|
|
303
|
+
|
|
304
|
+
elif args.cmd == "status":
|
|
305
|
+
nodes = "g1 g2 g3 d1 d2".split()
|
|
306
|
+
result = verify_fleet(nodes)
|
|
307
|
+
print(json.dumps(result, indent=2))
|
|
308
|
+
|
|
309
|
+
elif args.cmd == "version":
|
|
310
|
+
print(f"rtlinux {__version__}")
|
|
311
|
+
|
|
312
|
+
else:
|
|
313
|
+
parser.print_help()
|
|
314
|
+
|
|
315
|
+
|
|
316
|
+
if __name__ == "__main__":
|
|
317
|
+
main()
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: rtlinux
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: MeshPOP Runtime Linux — L0 node OS for AI infrastructure mesh
|
|
5
|
+
Author-email: MeshPOP <meshpop@proton.me>
|
|
6
|
+
License: Apache-2.0
|
|
7
|
+
Project-URL: Homepage, https://mpop.dev
|
|
8
|
+
Project-URL: Repository, https://github.com/meshpop/rtlinux
|
|
9
|
+
Project-URL: Documentation, https://mpop.dev/docs/
|
|
10
|
+
Project-URL: Issues, https://github.com/meshpop/rtlinux/issues
|
|
11
|
+
Keywords: meshpop,runtime,linux,buildroot,wireguard,mesh,infrastructure,ai,mcp,distributed,vssh,orchestration,node-os,l0
|
|
12
|
+
Classifier: Development Status :: 3 - Alpha
|
|
13
|
+
Classifier: Intended Audience :: System Administrators
|
|
14
|
+
Classifier: Intended Audience :: Developers
|
|
15
|
+
Classifier: License :: OSI Approved :: Apache Software License
|
|
16
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
17
|
+
Classifier: Operating System :: MacOS
|
|
18
|
+
Classifier: Programming Language :: Python :: 3
|
|
19
|
+
Classifier: Topic :: System :: Operating System
|
|
20
|
+
Classifier: Topic :: System :: Systems Administration
|
|
21
|
+
Classifier: Topic :: System :: Clustering
|
|
22
|
+
Classifier: Topic :: System :: Networking
|
|
23
|
+
Requires-Python: >=3.8
|
|
24
|
+
Description-Content-Type: text/markdown
|
|
25
|
+
License-File: LICENSE
|
|
26
|
+
Dynamic: license-file
|
|
27
|
+
|
|
28
|
+
# rtlinux — MeshPOP Runtime Linux
|
|
29
|
+
|
|
30
|
+
**Layer 0 of the MeshPOP stack.** A Buildroot-based minimal Linux distribution purpose-built for AI infrastructure mesh nodes.
|
|
31
|
+
|
|
32
|
+
```
|
|
33
|
+
L0 rtlinux — Runtime OS (kernel + musl + busybox + MeshPOP)
|
|
34
|
+
L1 Wire — WireGuard mesh VPN (pip install meshpop-wire)
|
|
35
|
+
L2 vssh — Secure remote execution (pip install vssh)
|
|
36
|
+
L3 mpop — Fleet orchestration (pip install meshpop)
|
|
37
|
+
L4 MeshDB — Distributed search (pip install meshpop-db)
|
|
38
|
+
L5 Vault — Secrets management (pip install sv-vault)
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## What It Does
|
|
42
|
+
|
|
43
|
+
Builds a minimal, network-hardened Linux OS with the full MeshPOP tool suite pre-installed. Boot a node → it auto-joins the Wire mesh → instantly manageable via `mpop exec`, `mpop deploy`, `mpop ask`.
|
|
44
|
+
|
|
45
|
+
**Like Talos Linux for Kubernetes, but for MeshPOP.**
|
|
46
|
+
|
|
47
|
+
## Install
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
pip install rtlinux
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Quick Start
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
# Build runtime image (Buildroot — from source, zero dependencies)
|
|
57
|
+
rtlinux build --method buildroot
|
|
58
|
+
|
|
59
|
+
# Deploy to a new node
|
|
60
|
+
rtlinux deploy g5 --image output/meshpoplinux-rootfs.tar.gz
|
|
61
|
+
|
|
62
|
+
# Verify all nodes
|
|
63
|
+
rtlinux verify --all
|
|
64
|
+
|
|
65
|
+
# Full CI/CD loop: build → deploy → verify → fix
|
|
66
|
+
rtlinux loop --nodes "g1 g2 g3 d1 d2"
|
|
67
|
+
|
|
68
|
+
# Fleet status
|
|
69
|
+
rtlinux status
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## Build Methods
|
|
73
|
+
|
|
74
|
+
| Method | Dependencies | Time | Output |
|
|
75
|
+
|--------|-------------|------|--------|
|
|
76
|
+
| **Buildroot** (recommended) | None — kernel+BusyBox+musl from source | 20-60 min | bzImage + rootfs.cpio |
|
|
77
|
+
| Alpine | Docker | ~2 min | rootfs.tar.gz |
|
|
78
|
+
| Scratch | Linux host or Docker | ~1 min | rootfs.tar.gz |
|
|
79
|
+
|
|
80
|
+
## MCP Server
|
|
81
|
+
|
|
82
|
+
rtlinux includes an MCP server for AI-driven node management:
|
|
83
|
+
|
|
84
|
+
```json
|
|
85
|
+
{
|
|
86
|
+
"mcpServers": {
|
|
87
|
+
"rtlinux": {
|
|
88
|
+
"command": "python3",
|
|
89
|
+
"args": ["-m", "rtlinux.mcp.rtlinux_mcp_server"]
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### MCP Tools
|
|
96
|
+
|
|
97
|
+
| Tool | Description |
|
|
98
|
+
|------|-------------|
|
|
99
|
+
| `rtlinux_build` | Build runtime image |
|
|
100
|
+
| `rtlinux_deploy` | Deploy to a node |
|
|
101
|
+
| `rtlinux_verify` | Health check (all 5 layers) |
|
|
102
|
+
| `rtlinux_fleet` | Fleet status overview |
|
|
103
|
+
| `rtlinux_fix` | Auto-fix degraded node |
|
|
104
|
+
| `rtlinux_cicd` | Full CI/CD loop |
|
|
105
|
+
|
|
106
|
+
## Python API
|
|
107
|
+
|
|
108
|
+
```python
|
|
109
|
+
import rtlinux
|
|
110
|
+
|
|
111
|
+
# Build
|
|
112
|
+
result = rtlinux.build(method="buildroot")
|
|
113
|
+
|
|
114
|
+
# Deploy
|
|
115
|
+
result = rtlinux.deploy("g5")
|
|
116
|
+
|
|
117
|
+
# Verify single node
|
|
118
|
+
health = rtlinux.verify("g1")
|
|
119
|
+
# → {"status": "healthy", "layers_ok": "5/5", ...}
|
|
120
|
+
|
|
121
|
+
# Verify fleet
|
|
122
|
+
fleet = rtlinux.verify_fleet(["g1", "g2", "d1", "d2"])
|
|
123
|
+
# → {"summary": "4/4 healthy", "fleet": {...}}
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
## Architecture
|
|
127
|
+
|
|
128
|
+
```
|
|
129
|
+
┌────────────────────────────────────────────────┐
|
|
130
|
+
│ rtlinux Node │
|
|
131
|
+
│ │
|
|
132
|
+
│ kernel (Buildroot-compiled) │
|
|
133
|
+
│ └─ WireGuard (mesh VPN, auto-peering) │
|
|
134
|
+
│ └─ vssh daemon (remote execution) │
|
|
135
|
+
│ └─ mpop agent (orchestration) │
|
|
136
|
+
│ └─ MeshDB indexer (file search) │
|
|
137
|
+
│ └─ minimal userspace (BusyBox + musl) │
|
|
138
|
+
│ │
|
|
139
|
+
│ No SSH. No package manager. No systemd. │
|
|
140
|
+
│ Just MeshPOP. │
|
|
141
|
+
└────────────────────────────────────────────────┘
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
## The MeshPOP Stack
|
|
145
|
+
|
|
146
|
+
| Layer | Package | PyPI |
|
|
147
|
+
|-------|---------|------|
|
|
148
|
+
| L0 | **rtlinux** | `pip install rtlinux` |
|
|
149
|
+
| L1 | Wire | `pip install meshpop-wire` |
|
|
150
|
+
| L2 | vssh | `pip install vssh` |
|
|
151
|
+
| L3 | mpop | `pip install meshpop` |
|
|
152
|
+
| L4 | MeshDB | `pip install meshpop-db` |
|
|
153
|
+
| L5 | Vault | `pip install sv-vault` |
|
|
154
|
+
|
|
155
|
+
## Links
|
|
156
|
+
|
|
157
|
+
- **Homepage**: [mpop.dev](https://mpop.dev)
|
|
158
|
+
- **GitHub**: [github.com/meshpop/rtlinux](https://github.com/meshpop/rtlinux)
|
|
159
|
+
- **All repos**: [github.com/meshpop](https://github.com/meshpop)
|
|
160
|
+
|
|
161
|
+
## License
|
|
162
|
+
|
|
163
|
+
Apache-2.0
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
rtlinux
|