phonepod 0.0.1
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.
- package/README.md +88 -0
- package/bin/phonepod.js +214 -0
- package/package.json +35 -0
package/README.md
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
# PhonePod
|
|
2
|
+
|
|
3
|
+
Solid pod on your phone. One command install for Android/Termux.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **Solid Pod** - Full LDP server with WebID, WAC
|
|
8
|
+
- **Nostr Relay** - Built-in NIP-01 relay
|
|
9
|
+
- **Git Server** - Clone and push via HTTP
|
|
10
|
+
- **~100MB RAM** - Lighter than a browser tab
|
|
11
|
+
|
|
12
|
+
## Quick Install (Termux)
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
pkg install nodejs-lts
|
|
16
|
+
npm install -g phonepod
|
|
17
|
+
phonepod start
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Usage
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
phonepod start # Start the pod
|
|
24
|
+
phonepod start --port 3000 # Custom port
|
|
25
|
+
phonepod tunnel user@host # Setup SSH tunnel for public access
|
|
26
|
+
phonepod status # Show configuration
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Public Access
|
|
30
|
+
|
|
31
|
+
To make your pod publicly accessible, you need a relay server:
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
# Setup tunnel (generates SSH key, creates tunnel script)
|
|
35
|
+
phonepod tunnel ubuntu@relay.example.com
|
|
36
|
+
|
|
37
|
+
# Add the printed SSH key to your relay server
|
|
38
|
+
# Then start tunnel with PM2:
|
|
39
|
+
pm2 start ~/.phonepod/tunnel.sh --name tunnel
|
|
40
|
+
pm2 save
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Boot Persistence
|
|
44
|
+
|
|
45
|
+
Install Termux:Boot from F-Droid, then:
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
mkdir -p ~/.termux/boot
|
|
49
|
+
echo '#!/bin/bash
|
|
50
|
+
termux-wake-lock
|
|
51
|
+
pm2 resurrect' > ~/.termux/boot/start.sh
|
|
52
|
+
chmod +x ~/.termux/boot/start.sh
|
|
53
|
+
|
|
54
|
+
# Save current processes
|
|
55
|
+
pm2 start phonepod -- start
|
|
56
|
+
pm2 save
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Endpoints
|
|
60
|
+
|
|
61
|
+
| Endpoint | Description |
|
|
62
|
+
|----------|-------------|
|
|
63
|
+
| `http://localhost:8080/` | Solid pod root |
|
|
64
|
+
| `ws://localhost:8080/relay` | Nostr relay |
|
|
65
|
+
| `http://localhost:8080/relay/info` | NIP-11 relay info |
|
|
66
|
+
| `git clone http://localhost:8080/` | Git clone |
|
|
67
|
+
|
|
68
|
+
## Configuration
|
|
69
|
+
|
|
70
|
+
Config stored in `~/.phonepod/config.json`:
|
|
71
|
+
|
|
72
|
+
```json
|
|
73
|
+
{
|
|
74
|
+
"port": 8080,
|
|
75
|
+
"nostr": true,
|
|
76
|
+
"git": true
|
|
77
|
+
}
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
## Requirements
|
|
81
|
+
|
|
82
|
+
- Android with Termux
|
|
83
|
+
- Node.js 18+
|
|
84
|
+
- For public access: relay server with SSH access
|
|
85
|
+
|
|
86
|
+
## License
|
|
87
|
+
|
|
88
|
+
MIT
|
package/bin/phonepod.js
ADDED
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* PhonePod CLI
|
|
5
|
+
*
|
|
6
|
+
* Solid pod on your phone - Android/Termux
|
|
7
|
+
*
|
|
8
|
+
* Usage:
|
|
9
|
+
* phonepod start [options] Start the pod
|
|
10
|
+
* phonepod setup Interactive setup
|
|
11
|
+
* phonepod tunnel <host> Setup SSH tunnel to relay
|
|
12
|
+
* phonepod status Show status
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import { spawn } from 'child_process';
|
|
16
|
+
import { existsSync, mkdirSync, writeFileSync, readFileSync } from 'fs';
|
|
17
|
+
import { join } from 'path';
|
|
18
|
+
import { homedir } from 'os';
|
|
19
|
+
import { createInterface } from 'readline';
|
|
20
|
+
|
|
21
|
+
const args = process.argv.slice(2);
|
|
22
|
+
const command = args[0];
|
|
23
|
+
|
|
24
|
+
// Config directory
|
|
25
|
+
const CONFIG_DIR = join(homedir(), '.phonepod');
|
|
26
|
+
const CONFIG_FILE = join(CONFIG_DIR, 'config.json');
|
|
27
|
+
|
|
28
|
+
// Ensure config dir exists
|
|
29
|
+
if (!existsSync(CONFIG_DIR)) {
|
|
30
|
+
mkdirSync(CONFIG_DIR, { recursive: true });
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// Load or create config
|
|
34
|
+
function loadConfig() {
|
|
35
|
+
if (existsSync(CONFIG_FILE)) {
|
|
36
|
+
return JSON.parse(readFileSync(CONFIG_FILE, 'utf8'));
|
|
37
|
+
}
|
|
38
|
+
return { port: 8080, nostr: true, git: true };
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function saveConfig(config) {
|
|
42
|
+
writeFileSync(CONFIG_FILE, JSON.stringify(config, null, 2));
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// Run JSS with phonepod defaults
|
|
46
|
+
function startPod(options = {}) {
|
|
47
|
+
const config = loadConfig();
|
|
48
|
+
const jssArgs = [
|
|
49
|
+
'start',
|
|
50
|
+
'--port', String(options.port || config.port || 8080),
|
|
51
|
+
];
|
|
52
|
+
|
|
53
|
+
if (options.nostr ?? config.nostr) jssArgs.push('--nostr');
|
|
54
|
+
if (options.git ?? config.git) jssArgs.push('--git');
|
|
55
|
+
if (options.root) jssArgs.push('--root', options.root);
|
|
56
|
+
|
|
57
|
+
console.log('Starting PhonePod...');
|
|
58
|
+
console.log(` Port: ${options.port || config.port || 8080}`);
|
|
59
|
+
console.log(` Nostr: ${(options.nostr ?? config.nostr) ? 'enabled' : 'disabled'}`);
|
|
60
|
+
console.log(` Git: ${(options.git ?? config.git) ? 'enabled' : 'disabled'}`);
|
|
61
|
+
console.log('');
|
|
62
|
+
|
|
63
|
+
// Find jss binary
|
|
64
|
+
const jss = spawn('jss', jssArgs, { stdio: 'inherit' });
|
|
65
|
+
|
|
66
|
+
jss.on('error', (err) => {
|
|
67
|
+
if (err.code === 'ENOENT') {
|
|
68
|
+
console.error('Error: jss not found. Run: npm install -g javascript-solid-server');
|
|
69
|
+
} else {
|
|
70
|
+
console.error('Error:', err.message);
|
|
71
|
+
}
|
|
72
|
+
process.exit(1);
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
jss.on('exit', (code) => process.exit(code || 0));
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// Setup tunnel
|
|
79
|
+
async function setupTunnel(relayHost) {
|
|
80
|
+
if (!relayHost) {
|
|
81
|
+
console.error('Usage: phonepod tunnel <relay-host>');
|
|
82
|
+
console.error('Example: phonepod tunnel relay.example.com');
|
|
83
|
+
process.exit(1);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
const config = loadConfig();
|
|
87
|
+
const port = config.port || 8080;
|
|
88
|
+
|
|
89
|
+
console.log('');
|
|
90
|
+
console.log('Setting up SSH tunnel to', relayHost);
|
|
91
|
+
console.log('');
|
|
92
|
+
|
|
93
|
+
// Check for SSH key
|
|
94
|
+
const sshKeyPath = join(homedir(), '.ssh', 'id_ed25519');
|
|
95
|
+
const sshPubKeyPath = sshKeyPath + '.pub';
|
|
96
|
+
|
|
97
|
+
if (!existsSync(sshKeyPath)) {
|
|
98
|
+
console.log('Generating SSH key...');
|
|
99
|
+
const keygen = spawn('ssh-keygen', ['-t', 'ed25519', '-f', sshKeyPath, '-N', ''], { stdio: 'inherit' });
|
|
100
|
+
await new Promise(resolve => keygen.on('exit', resolve));
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// Show public key
|
|
104
|
+
if (existsSync(sshPubKeyPath)) {
|
|
105
|
+
const pubKey = readFileSync(sshPubKeyPath, 'utf8').trim();
|
|
106
|
+
console.log('');
|
|
107
|
+
console.log('Add this SSH key to your relay server:');
|
|
108
|
+
console.log('');
|
|
109
|
+
console.log(pubKey);
|
|
110
|
+
console.log('');
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// Create tunnel script
|
|
114
|
+
const tunnelScript = join(CONFIG_DIR, 'tunnel.sh');
|
|
115
|
+
writeFileSync(tunnelScript, `#!/bin/bash
|
|
116
|
+
exec autossh -M 0 -o ServerAliveInterval=30 -o ServerAliveCountMax=3 -N -R ${port}:localhost:${port} ${relayHost}
|
|
117
|
+
`);
|
|
118
|
+
spawn('chmod', ['+x', tunnelScript]);
|
|
119
|
+
|
|
120
|
+
console.log(`Tunnel script created: ${tunnelScript}`);
|
|
121
|
+
console.log('');
|
|
122
|
+
console.log('To start tunnel manually:');
|
|
123
|
+
console.log(` ${tunnelScript}`);
|
|
124
|
+
console.log('');
|
|
125
|
+
console.log('To add to PM2:');
|
|
126
|
+
console.log(` pm2 start ${tunnelScript} --name tunnel`);
|
|
127
|
+
console.log(' pm2 save');
|
|
128
|
+
console.log('');
|
|
129
|
+
|
|
130
|
+
// Save relay host to config
|
|
131
|
+
config.relayHost = relayHost;
|
|
132
|
+
saveConfig(config);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// Show status
|
|
136
|
+
function showStatus() {
|
|
137
|
+
const config = loadConfig();
|
|
138
|
+
console.log('');
|
|
139
|
+
console.log('PhonePod Configuration:');
|
|
140
|
+
console.log('');
|
|
141
|
+
console.log(` Port: ${config.port || 8080}`);
|
|
142
|
+
console.log(` Nostr: ${config.nostr ? 'enabled' : 'disabled'}`);
|
|
143
|
+
console.log(` Git: ${config.git ? 'enabled' : 'disabled'}`);
|
|
144
|
+
if (config.relayHost) {
|
|
145
|
+
console.log(` Relay: ${config.relayHost}`);
|
|
146
|
+
}
|
|
147
|
+
console.log('');
|
|
148
|
+
console.log(` Config: ${CONFIG_FILE}`);
|
|
149
|
+
console.log('');
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// Help
|
|
153
|
+
function showHelp() {
|
|
154
|
+
console.log(`
|
|
155
|
+
PhonePod - Solid pod on your phone
|
|
156
|
+
|
|
157
|
+
Usage:
|
|
158
|
+
phonepod start [options] Start the pod
|
|
159
|
+
phonepod tunnel <host> Setup SSH tunnel to relay
|
|
160
|
+
phonepod status Show configuration
|
|
161
|
+
phonepod help Show this help
|
|
162
|
+
|
|
163
|
+
Start Options:
|
|
164
|
+
--port <n> Port to listen on (default: 8080)
|
|
165
|
+
--no-nostr Disable Nostr relay
|
|
166
|
+
--no-git Disable Git server
|
|
167
|
+
|
|
168
|
+
Examples:
|
|
169
|
+
phonepod start
|
|
170
|
+
phonepod start --port 3000
|
|
171
|
+
phonepod tunnel ubuntu@relay.example.com
|
|
172
|
+
`);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
// Parse start options
|
|
176
|
+
function parseStartOptions() {
|
|
177
|
+
const options = {};
|
|
178
|
+
for (let i = 1; i < args.length; i++) {
|
|
179
|
+
if (args[i] === '--port' && args[i + 1]) {
|
|
180
|
+
options.port = parseInt(args[++i], 10);
|
|
181
|
+
} else if (args[i] === '--no-nostr') {
|
|
182
|
+
options.nostr = false;
|
|
183
|
+
} else if (args[i] === '--no-git') {
|
|
184
|
+
options.git = false;
|
|
185
|
+
} else if (args[i] === '--root' && args[i + 1]) {
|
|
186
|
+
options.root = args[++i];
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
return options;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
// Main
|
|
193
|
+
switch (command) {
|
|
194
|
+
case 'start':
|
|
195
|
+
startPod(parseStartOptions());
|
|
196
|
+
break;
|
|
197
|
+
case 'tunnel':
|
|
198
|
+
setupTunnel(args[1]);
|
|
199
|
+
break;
|
|
200
|
+
case 'status':
|
|
201
|
+
showStatus();
|
|
202
|
+
break;
|
|
203
|
+
case 'help':
|
|
204
|
+
case '--help':
|
|
205
|
+
case '-h':
|
|
206
|
+
showHelp();
|
|
207
|
+
break;
|
|
208
|
+
default:
|
|
209
|
+
if (command) {
|
|
210
|
+
console.error(`Unknown command: ${command}`);
|
|
211
|
+
}
|
|
212
|
+
showHelp();
|
|
213
|
+
process.exit(command ? 1 : 0);
|
|
214
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "phonepod",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "Solid pod on your phone - one command install for Android/Termux",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"bin": {
|
|
8
|
+
"phonepod": "./bin/phonepod.js"
|
|
9
|
+
},
|
|
10
|
+
"scripts": {
|
|
11
|
+
"test": "echo \"No tests yet\""
|
|
12
|
+
},
|
|
13
|
+
"repository": {
|
|
14
|
+
"type": "git",
|
|
15
|
+
"url": "git+https://github.com/JavaScriptSolidServer/phonepod.git"
|
|
16
|
+
},
|
|
17
|
+
"keywords": [
|
|
18
|
+
"solid",
|
|
19
|
+
"pod",
|
|
20
|
+
"phone",
|
|
21
|
+
"android",
|
|
22
|
+
"termux",
|
|
23
|
+
"nostr",
|
|
24
|
+
"decentralized"
|
|
25
|
+
],
|
|
26
|
+
"author": "",
|
|
27
|
+
"license": "MIT",
|
|
28
|
+
"bugs": {
|
|
29
|
+
"url": "https://github.com/JavaScriptSolidServer/phonepod/issues"
|
|
30
|
+
},
|
|
31
|
+
"homepage": "https://github.com/JavaScriptSolidServer/phonepod#readme",
|
|
32
|
+
"dependencies": {
|
|
33
|
+
"javascript-solid-server": "^0.0.60"
|
|
34
|
+
}
|
|
35
|
+
}
|