pockethost 1.0.0-rc.1 → 1.1.0
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/common.ts +1 -0
- package/core.ts +2 -0
- package/package.json +24 -112
- package/readme.md +36 -146
- package/src/cli/commands/ConfigCommand/index.ts +99 -0
- package/src/cli/commands/PluginCommand/index.ts +123 -0
- package/src/cli/commands/PluginCommand/util.ts +140 -0
- package/src/cli/commands/ServeCommand/index.ts +20 -0
- package/src/cli/index.ts +39 -0
- package/src/common/CleanupManager.ts +65 -0
- package/src/common/Logger.ts +168 -0
- package/src/common/ResourceAllocator.ts +49 -0
- package/src/common/TimerManager.ts +64 -0
- package/src/common/assert.ts +26 -0
- package/src/common/debug.ts +8 -0
- package/src/common/events.ts +53 -0
- package/src/common/index.ts +12 -0
- package/src/common/mergeConfig.ts +27 -0
- package/src/common/mkSingleton.ts +28 -0
- package/src/common/plugin/action.ts +60 -0
- package/src/common/plugin/filter.ts +65 -0
- package/src/common/plugin/helpers.ts +17 -0
- package/src/common/plugin/index.ts +27 -0
- package/src/common/pocketbase-client-helpers/RestHelper.ts +69 -0
- package/src/common/pocketbase-client-helpers/index.ts +1 -0
- package/src/common/promiseSerializer.ts +22 -0
- package/src/common/schema/Instance.ts +45 -0
- package/src/common/schema/InstanceLog.ts +12 -0
- package/src/common/schema/Rest/CreateInstance.ts +20 -0
- package/src/common/schema/Rest/DeleteInstance.ts +21 -0
- package/src/common/schema/Rest/GetUserTokenInfo.ts +22 -0
- package/src/common/schema/Rest/UpdateInstance.ts +61 -0
- package/src/common/schema/Rest/index.ts +23 -0
- package/src/common/schema/User.ts +24 -0
- package/src/common/schema/index.ts +6 -0
- package/src/common/schema/types.ts +18 -0
- package/src/common/schema/util.ts +1 -0
- package/src/constants.ts +74 -0
- package/src/core/Settings.ts +119 -0
- package/src/core/asyncExecutionGuard.ts +49 -0
- package/src/core/exit.ts +11 -0
- package/src/core/index.ts +7 -0
- package/src/core/internal.ts +3 -0
- package/src/core/smartFetch.ts +32 -0
- package/src/core/tryFetch.ts +66 -0
- package/src/server.ts +119 -0
- package/dist/index.mjs +0 -3156
- package/dist/instance-app/migrations/1699198734_pockethost_defaults.js +0 -39
- package/dist/instance-app/pb_hooks/_ph_admin_sync.pb.js +0 -71
- package/dist/instance-app/pb_hooks/_ph_lib.js +0 -19
- package/dist/instance-app/tsconfig.json +0 -8
- package/dist/instance-app/types/goja.d.ts +0 -58
- package/dist/instance-app/types/lib.d.ts +0 -5
- package/dist/instance-app/types/types.d.ts +0 -19573
- package/dist/mothership-app/migrations/1705062576_collections_snapshot.js +0 -1863
- package/dist/mothership-app/migrations/1705083826_updated_stats.js +0 -721
- package/dist/mothership-app/migrations/1706060446_updated_instances.js +0 -44
- package/dist/mothership-app/pb_hooks/src/instances-create.pb.js +0 -65
- package/dist/mothership-app/pb_hooks/src/instances-delete.pb.js +0 -69
- package/dist/mothership-app/pb_hooks/src/instances-migrate-versions.pb.js +0 -33
- package/dist/mothership-app/pb_hooks/src/instances-notify-discord-after-create.pb.js +0 -31
- package/dist/mothership-app/pb_hooks/src/instances-notify-on-maintenance-mode.pb.js +0 -52
- package/dist/mothership-app/pb_hooks/src/instances-reset-idle.pb.js +0 -7
- package/dist/mothership-app/pb_hooks/src/instances-update.pb.js +0 -121
- package/dist/mothership-app/pb_hooks/src/instances-validate-before-create.pb.js +0 -16
- package/dist/mothership-app/pb_hooks/src/instances-validate-before-update.pb.js +0 -43
- package/dist/mothership-app/pb_hooks/src/lib.js +0 -171
- package/dist/mothership-app/pb_hooks/src/ls.pb.js +0 -159
- package/dist/mothership-app/pb_hooks/src/mail.pb.js +0 -49
- package/dist/mothership-app/pb_hooks/src/notifications.pb.js +0 -62
- package/dist/mothership-app/pb_hooks/src/random-words.js +0 -2085
- package/dist/mothership-app/pb_hooks/src/signup.pb.js +0 -214
- package/dist/mothership-app/pb_hooks/src/sns.pb.js +0 -133
- package/dist/mothership-app/pb_hooks/src/unsubscribe.pb.js +0 -33
- package/dist/mothership-app/pb_hooks/src/user-token.pb.js +0 -33
- package/dist/mothership-app/pb_hooks/src/user-welcome-msg.pb.js +0 -32
- package/dist/mothership-app/pb_hooks/src/versions-route.pb.js +0 -12
- package/dist/mothership-app/pb_hooks/src/versions.js +0 -0
- package/dist/mothership-app/pb_hooks/tsconfig.json +0 -8
- package/dist/mothership-app/pb_hooks/types/global.d.ts +0 -1
- package/dist/mothership-app/pb_hooks/types/goja.d.ts +0 -58
- package/dist/mothership-app/pb_hooks/types/lemon.d.ts +0 -12
- package/dist/mothership-app/pb_hooks/types/lib.d.ts +0 -55
- package/dist/mothership-app/pb_hooks/types/types.d.ts +0 -19573
- package/dist/mothership-app/ph_app/index.js +0 -11
- package/dist/mothership-app/ph_app/package-lock.json +0 -657
- package/dist/mothership-app/ph_app/package.json +0 -14
package/common.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './src/common'
|
package/core.ts
ADDED
package/package.json
CHANGED
|
@@ -1,144 +1,56 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pockethost",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"author": {
|
|
5
5
|
"name": "Ben Allfree",
|
|
6
6
|
"url": "https://github.com/benallfree"
|
|
7
7
|
},
|
|
8
8
|
"license": "MIT",
|
|
9
|
-
"main": "
|
|
10
|
-
"
|
|
11
|
-
"check:types": "concurrently 'pnpm:check:types:*'",
|
|
12
|
-
"check:types:dashboard": "cd frontends/dashboard && pnpm check:types",
|
|
13
|
-
"check:types:pockethost": "tsc --noEmit --skipLibCheck",
|
|
14
|
-
"lint": "prettier -c \"./**/*.{ts,js,cjs,svelte,json}\"",
|
|
15
|
-
"lint:fix": "prettier -w \"./**/*.{ts,js,cjs,svelte,json}\"",
|
|
16
|
-
"download-versions": "tsx ./src/cli/download.ts",
|
|
17
|
-
"build": "concurrently 'pnpm:build:*'",
|
|
18
|
-
"build-cli": "tsx build.ts",
|
|
19
|
-
"build-frontends": "concurrently 'pnpm:build:frontend:*'",
|
|
20
|
-
"build:frontend:dashboard": "cd frontends/dashboard && pnpm build",
|
|
21
|
-
"build:docker": "cd src/services/PocketBaseService && docker build . -t pockethost-instance",
|
|
22
|
-
"build:frontend:lander": "cd frontends/lander && pnpm build",
|
|
23
|
-
"build:frontend:superadmin": "cd frontends/superadmin && pnpm build",
|
|
24
|
-
"dev": "NODE_ENV=development concurrently 'pnpm:dev:*'",
|
|
25
|
-
"dev-cli": "nodemon --signal SIGTERM dist/index.mjs",
|
|
26
|
-
"dev:lander": "cd frontends/lander && pnpm start",
|
|
27
|
-
"dev:dashboard": "cd frontends/dashboard && pnpm dev",
|
|
28
|
-
"dev:superadmin": "cd frontends/superadmin && pnpm dev",
|
|
29
|
-
"prod:proxy": "dotenv tsx ./src/cli/proxy/server.ts",
|
|
30
|
-
"prod:edge:daemon": "tsx src/cli/edge-daemon.ts",
|
|
31
|
-
"prod:edge:ftp": "tsx src/cli/edge-ftp.ts",
|
|
32
|
-
"prod:edge:health": "tsx src/cli/edge-health.ts",
|
|
33
|
-
"prod:edge:syslog": "tsx src/cli/edge-syslogd.ts",
|
|
34
|
-
"prod:mothership": "tsx src/cli/mothership.ts",
|
|
35
|
-
"plop": "plop",
|
|
36
|
-
"nofile": "cat /proc/sys/fs/file-nr",
|
|
37
|
-
"mail": "tsx ./src/cli/sendmail.ts",
|
|
38
|
-
"watch": "node build.cjs"
|
|
39
|
-
},
|
|
40
|
-
"prettier": {
|
|
41
|
-
"semi": false,
|
|
42
|
-
"useTabs": false,
|
|
43
|
-
"singleQuote": true,
|
|
44
|
-
"trailingComma": "all",
|
|
45
|
-
"plugins": [
|
|
46
|
-
"./node_modules/prettier-plugin-organize-imports/index.js",
|
|
47
|
-
"./node_modules/prettier-plugin-svelte/plugin.js",
|
|
48
|
-
"./node_modules/prettier-plugin-jsdoc/dist/index.js"
|
|
49
|
-
]
|
|
50
|
-
},
|
|
9
|
+
"main": "./common.ts",
|
|
10
|
+
"module": "./common.ts",
|
|
51
11
|
"type": "module",
|
|
12
|
+
"bin": {
|
|
13
|
+
"pockethost": "src/cli/index.ts"
|
|
14
|
+
},
|
|
52
15
|
"dependencies": {
|
|
53
16
|
"@s-libs/micro-dash": "^16.1.0",
|
|
54
|
-
"@types/node-os-utils": "^1.3.4",
|
|
55
|
-
"@types/winston-syslog": "^2.4.3",
|
|
56
17
|
"ajv": "^8.12.0",
|
|
57
18
|
"boolean": "^3.2.0",
|
|
58
19
|
"bottleneck": "^2.19.5",
|
|
20
|
+
"chalk": "^5.3.0",
|
|
59
21
|
"commander": "^11.1.0",
|
|
60
|
-
"cors": "^2.8.5",
|
|
61
|
-
"decompress": "^4.2.1",
|
|
62
|
-
"decompress-unzip": "https://github.com/pockethost/decompress-unzip.git#6ef397b9a2df11d39c7b26ce779e123833844751",
|
|
63
|
-
"dockerode": "^3.3.5",
|
|
64
22
|
"dotenv": "^16.3.1",
|
|
65
|
-
"
|
|
66
|
-
"eventsource": "^2.0.2",
|
|
23
|
+
"env-paths": "^3.0.0",
|
|
67
24
|
"exit-hook": "^4.0.0",
|
|
68
25
|
"express": "^4.18.2",
|
|
69
26
|
"express-async-errors": "^3.1.1",
|
|
70
|
-
"find-up": "^6.3.0",
|
|
71
|
-
"ftp-srv": "github:pockethost/ftp-srv#0fc708bae0d5d7a55ce948767f082d6fcfb2af59",
|
|
72
27
|
"get-port": "^6.1.2",
|
|
73
|
-
"glob": "^10.3.10",
|
|
74
28
|
"http-proxy": "^1.18.1",
|
|
75
|
-
"http-proxy-middleware": "^2.0.6",
|
|
76
|
-
"ip-cidr": "^3.1.0",
|
|
77
29
|
"json-stringify-safe": "^5.0.1",
|
|
78
|
-
"
|
|
79
|
-
"memorystream": "^0.3.1",
|
|
30
|
+
"listr2": "^8.2.3",
|
|
80
31
|
"nanoid": "^5.0.2",
|
|
81
32
|
"node-fetch": "^3.3.2",
|
|
82
|
-
"
|
|
83
|
-
"
|
|
84
|
-
"semver": "^7.
|
|
85
|
-
"sqlite3": "^5.1.6",
|
|
86
|
-
"syslog-parse": "^2.0.0",
|
|
87
|
-
"tail": "^2.2.6",
|
|
33
|
+
"pocketbase": "^0.21.3",
|
|
34
|
+
"rimraf": "^5.0.5",
|
|
35
|
+
"semver": "^7.6.2",
|
|
88
36
|
"tmp": "^0.2.1",
|
|
89
|
-
"
|
|
90
|
-
"
|
|
91
|
-
"
|
|
92
|
-
"
|
|
37
|
+
"tsx": "^4.15.7",
|
|
38
|
+
"type-fest": "^4.6.0",
|
|
39
|
+
"typescript": "^5.4.5",
|
|
40
|
+
"url-pattern": "^1.0.3"
|
|
93
41
|
},
|
|
94
42
|
"devDependencies": {
|
|
95
|
-
"@swc/cli": "^0.1.62",
|
|
96
|
-
"@swc/core": "^1.3.95",
|
|
97
|
-
"@types/bootstrap": "^5.2.8",
|
|
98
|
-
"@types/copyfiles": "^2.4.4",
|
|
99
|
-
"@types/cors": "^2.8.17",
|
|
100
|
-
"@types/d3-scale": "^4.0.6",
|
|
101
|
-
"@types/d3-scale-chromatic": "^3.0.1",
|
|
102
|
-
"@types/decompress": "^4.2.6",
|
|
103
|
-
"@types/dockerode": "^3.3.21",
|
|
104
|
-
"@types/eventsource": "^1.1.14",
|
|
105
43
|
"@types/express": "^4.17.21",
|
|
106
44
|
"@types/http-proxy": "^1.17.13",
|
|
107
|
-
"@types/js-cookie": "^3.0.5",
|
|
108
45
|
"@types/json-stringify-safe": "^5.0.2",
|
|
109
|
-
"@types/marked": "^4.3.2",
|
|
110
|
-
"@types/memorystream": "^0.3.3",
|
|
111
|
-
"@types/ncp": "^2.0.8",
|
|
112
46
|
"@types/node": "^20.8.10",
|
|
113
47
|
"@types/semver": "^7.5.4",
|
|
114
|
-
"@types/
|
|
115
|
-
"@types/tmp": "^0.2.5",
|
|
116
|
-
"@types/unzipper": "^0.10.8",
|
|
117
|
-
"@types/vhost": "^3.0.9",
|
|
118
|
-
"chalk": "^5.3.0",
|
|
119
|
-
"chokidar-cli": "^3.0.0",
|
|
120
|
-
"concurrently": "^8.2.2",
|
|
121
|
-
"copyfiles": "^2.4.1",
|
|
122
|
-
"date-fns": "^2.30.0",
|
|
123
|
-
"dotenv-cli": "^7.3.0",
|
|
124
|
-
"esbuild": "^0.20.0",
|
|
125
|
-
"esbuild-node-externals": "^1.13.0",
|
|
126
|
-
"js-yaml": "^4.1.0",
|
|
127
|
-
"ncp": "^2.0.0",
|
|
128
|
-
"nodemon": "^3.0.3",
|
|
129
|
-
"ora": "^7.0.1",
|
|
130
|
-
"plop": "^4.0.0",
|
|
131
|
-
"postinstall-postinstall": "^2.1.0",
|
|
132
|
-
"prettier": "^3.0.3",
|
|
133
|
-
"prettier-plugin-jsdoc": "^1.3.0",
|
|
134
|
-
"prettier-plugin-organize-imports": "^3.2.3",
|
|
135
|
-
"prettier-plugin-svelte": "^3.0.3",
|
|
136
|
-
"rizzdown": "^0.0.6",
|
|
137
|
-
"svelte": "^4.2.2",
|
|
138
|
-
"tslib": "^2.6.2",
|
|
139
|
-
"tsx": "^3.14.0",
|
|
140
|
-
"type-fest": "^4.6.0",
|
|
141
|
-
"typescript": "^5.2.2"
|
|
48
|
+
"@types/tmp": "^0.2.5"
|
|
142
49
|
},
|
|
143
|
-
"
|
|
144
|
-
|
|
50
|
+
"scripts": {
|
|
51
|
+
"check-types": "tsc --noEmit ",
|
|
52
|
+
"lint": "prettier -c \"./**/*.{ts,js,cjs,svelte,json}\"",
|
|
53
|
+
"dev": "NODE_ENV=development tsx --watch ./src/cli/index.ts",
|
|
54
|
+
"start": "tsx ./src/cli/index.ts"
|
|
55
|
+
}
|
|
56
|
+
}
|
package/readme.md
CHANGED
|
@@ -1,168 +1,58 @@
|
|
|
1
|
-
#
|
|
1
|
+
# PocketHost
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
PocketHost is the open source multi-tenant PocketBase server. PocketHost can run dozens, hundreds, even thousands of PocketBase instances on a single server or across a global cloud.
|
|
4
4
|
|
|
5
|
-
PocketHost
|
|
5
|
+
Extend PocketHost with its Plugin ecosystem. Start with the bare-bones dev server and add plugins to grow your enterprise into a global cloud.
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
---
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
- Each instance runs on a subdomain of `pockethost.io`
|
|
11
|
-
- Run your instance in an ultra-beefy shared environment
|
|
9
|
+
### Sponsored by https://pockethost.io. Instantly host your PocketBase projects.
|
|
12
10
|
|
|
13
|
-
|
|
11
|
+
---
|
|
14
12
|
|
|
15
|
-
|
|
13
|
+
## Quickstart
|
|
16
14
|
|
|
17
|
-
1. Create an account at pockethost.io
|
|
18
|
-
2. Provision your first PocketBase instance
|
|
19
|
-
3. Connect from anywhere
|
|
20
|
-
|
|
21
|
-
```ts
|
|
22
|
-
const client = new PocketBase(`https://harvest.pockethost.io`)
|
|
23
|
-
```
|
|
24
|
-
|
|
25
|
-
**Batteries Included**
|
|
26
|
-
|
|
27
|
-
Here's all the Linux/devops stuff that PocketHost does for you:
|
|
28
|
-
|
|
29
|
-
- Email and DKIM+SPF and more
|
|
30
|
-
- DNS jargon: MX, TXT, CNAME
|
|
31
|
-
- SSL cert provisioning and management
|
|
32
|
-
- Storage
|
|
33
|
-
- Volume mounts
|
|
34
|
-
- Cloud computing or VPS deployment
|
|
35
|
-
- CDN and static asset hosting
|
|
36
|
-
- Amazon AWS
|
|
37
|
-
- Lots more - scaling, firewalls, DDoS defense, user security, log rotation, patches, updates, build tools, CPU architectures, multitenancy, on and on
|
|
38
|
-
|
|
39
|
-
PocketHost is free and open source project licensed under the MIT License.
|
|
40
|
-
|
|
41
|
-
This monorepo contains the entire open source stack that powers pockethost.io. You can use it to run your own private or public multitenant platform.
|
|
42
|
-
|
|
43
|
-
**Questions?**
|
|
44
|
-
|
|
45
|
-
Head over to Discord and ask away.
|
|
46
|
-
|
|
47
|
-
## Frontend only
|
|
48
|
-
|
|
49
|
-
If you just want to work on the UI/frontend client apps, they are configured to connect to pockethost.io out of the box. This is the most convenient way to make UI modifications to the PocketHost project.
|
|
50
|
-
|
|
51
|
-
```bash
|
|
52
|
-
git clone git@github.com:benallfree/pockethost.git
|
|
53
|
-
cd pockethost
|
|
54
|
-
pnpm
|
|
55
|
-
pnpm dev:lander # Marketing/blog area
|
|
56
|
-
pnpm dev:dashboard # Dashboard/control panel
|
|
57
|
-
```
|
|
58
|
-
|
|
59
|
-
## All our base
|
|
60
|
-
|
|
61
|
-
**Running in dev mode**
|
|
62
|
-
|
|
63
|
-
Note for OS X users: if the `pocketbase` binaries do not run, it's probably your [security settings](https://support.apple.com/guide/mac-help/open-a-mac-app-from-an-unidentified-developer-mh40616/mac).
|
|
64
|
-
|
|
65
|
-
**Prerequisites**
|
|
66
|
-
|
|
67
|
-
Local PocketHost development relies on Caddy to create reverse proxies into the various services powering the PocketHost backend. We use `lvh.me` to work with subdomains that resolve to localhost.
|
|
68
|
-
|
|
69
|
-
```bash
|
|
70
|
-
brew install caddy
|
|
71
15
|
```
|
|
72
|
-
|
|
73
|
-
Then:
|
|
74
|
-
|
|
75
|
-
```bash
|
|
76
|
-
git clone git@github.com:benallfree/pockethost.git
|
|
77
|
-
cd pockethost
|
|
78
|
-
pnpm
|
|
79
|
-
cp .env-template .env
|
|
16
|
+
npx pockethost serve
|
|
80
17
|
```
|
|
81
18
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
```bash
|
|
85
|
-
pnpm dev
|
|
86
|
-
|
|
87
|
-
# marketing/blog
|
|
88
|
-
open https://pockethost.lvh.me
|
|
89
|
-
|
|
90
|
-
# dashboard
|
|
91
|
-
open https://app.pockethost.lvh.me
|
|
92
|
-
|
|
93
|
-
# mothership
|
|
94
|
-
open https://pockethost-central.pockethost.lvh.me
|
|
95
|
-
|
|
96
|
-
# sample edge server (ph1)
|
|
97
|
-
open https://instance1.ph1.edge.pockethost.lvh.me
|
|
98
|
-
|
|
99
|
-
# second edge server (ph2)
|
|
100
|
-
open https://instance2.ph2.edge.pockethost.lvh.me
|
|
101
|
-
```
|
|
102
|
-
|
|
103
|
-
Additionally, the setup creates the following users and instances:
|
|
104
|
-
|
|
105
|
-
**Admin**
|
|
106
|
-
https://pockethost-central.pockethost.lvh.me
|
|
107
|
-
login: `admin@pockethost.lvh.me`
|
|
108
|
-
password: `password`
|
|
109
|
-
|
|
110
|
-
**User**
|
|
111
|
-
https://app.pockethost.lvh.me
|
|
112
|
-
login: `user@pockethost.lvh.me`
|
|
113
|
-
password: `password`
|
|
114
|
-
|
|
115
|
-
The user `user@pockethost.lvh.me` owns `instance1` and `instance2`, each which is running in its own region on separate edge servers.
|
|
116
|
-
|
|
117
|
-
That's it! You can control all this and much more from the `.env-template` file. It's fully documented, but here it is again just in case.
|
|
118
|
-
|
|
119
|
-
## Public Variables (available to frontend and backend)
|
|
19
|
+
## Configuration
|
|
120
20
|
|
|
121
|
-
|
|
122
|
-
| ----------------------- | --------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
123
|
-
| PUBLIC_DEBUG | `true` | The global debugging variable, used by both frontends and backend services. |
|
|
124
|
-
| PUBLIC_HTTP_PROTOCOL | `https` | You can use `http` if you like, but there is really no reason to. Caddy automatically provisions SSL certificates even for local development, and Cloudflare (recommended for DNS and CDN) does too. |
|
|
125
|
-
| PUBLIC_APEX_DOMAIN | `pockethost.lvh.me` | The apex domain is the domain on which all other subdomains live. If you set up your own PocketHost-based service, you'll want to change this. If you're just focusing on contributing to the project (please do!), then you can leave this as-is. |
|
|
126
|
-
| PUBLIC_APP_DOMAIN | `app.<apex>` | The fully qualified domain on which the dashboard/control panel lives (app). Probably no reason to alter this, as it defaults to `app` on the apex domain defined earlier. |
|
|
127
|
-
| PUBLIC_BLOG_DOMAIN | `<apex>` | The marketing/blog site lives on `<apex>` itself. |
|
|
128
|
-
| PUBLIC_EDGE_APEX_DOMAIN | `<id>.edge.<apex>` | Edge servers are the work horses of PocketHost. They receive incoming requests and route them to PocketBase instances. Each edge server needs a unique `<id>`, which are generally named after geographic regions such as `sfo-1`, `nyc-2`, etc. |
|
|
129
|
-
| PUBLIC_MOTHERSHIP_URL | `pockethost-central.<apex>` | The mothership URL is configurable because there may be cases where you want to deploy the mothership to its own central region. It does not live on an edge node. |
|
|
21
|
+
PocketHost supports configuration by environment variable. All PocketHost environment variables begin with `PH_`.
|
|
130
22
|
|
|
131
|
-
|
|
23
|
+
PocketHost will search the current directory for an `.env` when it loads. Anything in `.env` will be merged with and override any `<PH_HOME>/.env` that may exist.
|
|
132
24
|
|
|
133
|
-
|
|
25
|
+
Use `pockethost config` to set global defaults stored in `<PH_HOME>/.env`.
|
|
134
26
|
|
|
135
|
-
|
|
136
|
-
| ------------------------- | -------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
137
|
-
| MOTHERSHIP_MIGRATIONS_DIR | `<root>/src/mothership-app/migrations` | The directory where the Mothership migrations live. This is typically kept in revision control, so the default location is within the project directory structure. |
|
|
138
|
-
| MOTHERSHIP_HOOKS_DIR | `<root>/src/mothership-app/pb_hooks` | The directory where the Mothership `pb_hooks` live. This is typically kept in revision control, so the default location is within the project directory structure. |
|
|
139
|
-
| MOTHERSHIP_ADMIN_USERNAME | `admin@pockethost.lvh.me` | This admin login is created the first time PocketHost runs. |
|
|
140
|
-
| MOTHERSHIP_ADMIN_PASSWORD | `password` | |
|
|
141
|
-
| DEMO_USER_USERNAME | `user@pockethost.lvh.me` | This login is created the first time PocketHost runs |
|
|
142
|
-
| DEMO_USER_PASSWORD | `password` | |
|
|
143
|
-
| MOTHERSHIP_PORT | `8091` | The port the Mothership service will listen on. |
|
|
144
|
-
| MOTHERSHIP_SEMVER | `(blank)` | The semver used to lock the Mothership to a specific `pocketbase` version range. The Mothership will never launch with a `pocketbase` binary version outside this range. |
|
|
145
|
-
| MOTHERSHIP_PRIVATE_URL | `http://mothership.pockdthost.lvh.me` | This should be set to an intranet IP address in production settings. |
|
|
27
|
+
### Variables
|
|
146
28
|
|
|
147
|
-
|
|
29
|
+
| Name | Default | Discussion |
|
|
30
|
+
| -------------- | -------------------------- | ----------------------------------------------------------------------------- |
|
|
31
|
+
| PH_HOME | `~/.pockethost` | PocketHost's home directory where it holds all data. |
|
|
32
|
+
| PH_APEX_DOMAIN | `pockethost.lvh.me` | The apex domain used for routing and determining instance names. |
|
|
33
|
+
| PH_PORT | `3000` | The port PocketHost listens on |
|
|
34
|
+
| PH_DEBUG | `NODE_ENV==='development'` | Debug mode |
|
|
35
|
+
| PH_PLUGINS | (see below) | A comma-separated list of Plugins to load |
|
|
36
|
+
| PH_DATA_DIR | `~/.pockethost/data` | The root directory for storing PocketHost data, including instance databases. |
|
|
37
|
+
| PH_DEV | `NODE_ENV==='development'` | Whether PocketHost is running in development mode. |
|
|
148
38
|
|
|
149
|
-
|
|
39
|
+
### Default Plugins
|
|
150
40
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
| EDGE_DATA_ROOT | `<root>/.data` | Where the edge node should store its pocketbase instance data |
|
|
154
|
-
| EDGE_INSTANCE_MIN_IDLE_TTL | `5000` | The minimum amount of time an instance must remain idle (no connections) before an edge node is allowed to shut it down to free up resources |
|
|
155
|
-
| EDGE_INSTANCE_POOL_SIZE | `20` | The maximum number of simultaneous instances the edge node will allow to run concurrently. If this limit is exceeded, connections to instances not yet running in the pool will be denied. |
|
|
156
|
-
| \*\*IP_CIDR | `(blank)` | A comma-separated list of upstream proxy IP addresses or ranges PocketHost will respond to. |
|
|
41
|
+
- `@pockethost/plugin-console-logger`
|
|
42
|
+
- `@pockethost/plugin-launcher-spawn`
|
|
157
43
|
|
|
158
|
-
|
|
44
|
+
## Plugins
|
|
159
45
|
|
|
160
|
-
|
|
46
|
+
PocketHost uses a hook architecture and features many plugins. Some plugins have a CLI component, whereas others add purely programmatic support to alter how PocketHost works:
|
|
161
47
|
|
|
162
|
-
|
|
48
|
+
| name | description |
|
|
49
|
+
| ---------------------- | -------------------------------------------------------------------------------------------------------------------------------------- |
|
|
50
|
+
| plugin-ftp-server | Used to provide secure FTPS access to PocketBase instance data. This FTP server can run along-side a PocketHost server. |
|
|
51
|
+
| plugin-launcher-docker | Launches PocketBase instances via Docker. This is useful for running untrusted PocketBase code and instances. pockethost.io uses this. |
|
|
52
|
+
| plugin-launcher-spawn | Launches PocketBase instances via `spawn()` on the local machine. PocketHost uses this by default. |
|
|
53
|
+
| plugin-waf | A Web Application Firewall |
|
|
54
|
+
| plugin-waf-enforce-ssl | Enforce SSL at the WAF |
|
|
163
55
|
|
|
164
|
-
|
|
165
|
-
| ------- | --------- | ------------------------------------------------------------------------------------------- |
|
|
166
|
-
| IP_CIDR | `(blank)` | A comma-separated list of upstream proxy IP addresses or ranges PocketHost will respond to. |
|
|
56
|
+
## Support
|
|
167
57
|
|
|
168
|
-
|
|
58
|
+
PocketHost has a thriving [Discord community](https://discord.gg/nVTxCMEcGT).
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { forEach, keys, omit } from '@s-libs/micro-dash'
|
|
2
|
+
import { Command } from 'commander'
|
|
3
|
+
import { parse } from 'dotenv'
|
|
4
|
+
import { existsSync, readFileSync, writeFileSync } from 'fs'
|
|
5
|
+
import { info } from '../..'
|
|
6
|
+
import { PH_HOME, isSettingKey, settings } from '../../../constants'
|
|
7
|
+
|
|
8
|
+
const envFile = () => {
|
|
9
|
+
const envFile = PH_HOME(`.env`)
|
|
10
|
+
if (!existsSync(envFile)) {
|
|
11
|
+
writeFileSync(envFile, '')
|
|
12
|
+
}
|
|
13
|
+
return envFile
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const _parse = () =>
|
|
17
|
+
parse(readFileSync(envFile(), { encoding: 'utf8' }).toString())
|
|
18
|
+
|
|
19
|
+
export const ConfigCommand = () => {
|
|
20
|
+
const cmd = new Command(`config`)
|
|
21
|
+
.description(`Set global config defaults`)
|
|
22
|
+
.addCommand(
|
|
23
|
+
new Command(`set`)
|
|
24
|
+
.argument(`<name>`, `Config name`)
|
|
25
|
+
.argument(`<value>`, `Config value`)
|
|
26
|
+
.description(`Set a config value`)
|
|
27
|
+
.action((name, value) => {
|
|
28
|
+
if (!isSettingKey(name))
|
|
29
|
+
throw new Error(`Invalid setting name ${name}`)
|
|
30
|
+
|
|
31
|
+
if (value === '=') throw new Error(`Invalid value ${value}`)
|
|
32
|
+
|
|
33
|
+
const values = _parse()
|
|
34
|
+
values[name] = value
|
|
35
|
+
writeFileSync(
|
|
36
|
+
envFile(),
|
|
37
|
+
Object.entries(values)
|
|
38
|
+
.map(([k, v]) => `${k}=${v}`)
|
|
39
|
+
.join('\n'),
|
|
40
|
+
)
|
|
41
|
+
info(`Set ${name}=${value}`)
|
|
42
|
+
info(`Written to ${envFile()}`)
|
|
43
|
+
}),
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
.addCommand(
|
|
47
|
+
new Command(`unset`)
|
|
48
|
+
.argument(`<name>`, `Config name`)
|
|
49
|
+
.description(`Unset a config value`)
|
|
50
|
+
.action((name) => {
|
|
51
|
+
if (!isSettingKey(name))
|
|
52
|
+
throw new Error(`Invalid setting name ${name}`)
|
|
53
|
+
|
|
54
|
+
const values = _parse()
|
|
55
|
+
delete values[name]
|
|
56
|
+
writeFileSync(
|
|
57
|
+
envFile(),
|
|
58
|
+
Object.entries(values)
|
|
59
|
+
.map(([k, v]) => `${k}=${v}`)
|
|
60
|
+
.join('\n'),
|
|
61
|
+
)
|
|
62
|
+
info(`Unset ${name}`)
|
|
63
|
+
info(`Written to ${envFile()}`)
|
|
64
|
+
}),
|
|
65
|
+
)
|
|
66
|
+
.addCommand(
|
|
67
|
+
new Command(`list`)
|
|
68
|
+
.description(`List all config values`)
|
|
69
|
+
.alias(`ls`)
|
|
70
|
+
.action(() => {
|
|
71
|
+
const values = _parse()
|
|
72
|
+
|
|
73
|
+
if (keys(values).length > 0) {
|
|
74
|
+
info()
|
|
75
|
+
info(`Config values from ${envFile()}:`)
|
|
76
|
+
forEach(values, (v, k) => {
|
|
77
|
+
info(`\t${k}=${v}`)
|
|
78
|
+
})
|
|
79
|
+
info()
|
|
80
|
+
} else {
|
|
81
|
+
info(`No config values found in ${envFile()}`)
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const defaults = omit(settings, keys(values) as any)
|
|
85
|
+
if (keys(defaults).length > 0) {
|
|
86
|
+
info(`Default values:`)
|
|
87
|
+
forEach(settings, (v, k) => {
|
|
88
|
+
if (k in values) return
|
|
89
|
+
info(`\t${k}=${v}`)
|
|
90
|
+
})
|
|
91
|
+
} else {
|
|
92
|
+
info(
|
|
93
|
+
`No default values because all values are defined in ${envFile()}`,
|
|
94
|
+
)
|
|
95
|
+
}
|
|
96
|
+
}),
|
|
97
|
+
)
|
|
98
|
+
return cmd
|
|
99
|
+
}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import { uniq } from '@s-libs/micro-dash'
|
|
2
|
+
import { Command } from 'commander'
|
|
3
|
+
import { parse } from 'dotenv'
|
|
4
|
+
import { existsSync, readFileSync, writeFileSync } from 'fs'
|
|
5
|
+
import { error, info } from '../..'
|
|
6
|
+
import { PH_HOME, PH_PLUGINS, PH_PROJECT_DIR } from '../../../constants'
|
|
7
|
+
import { getCompatibleVersions, getPackageJson, removePackage } from './util'
|
|
8
|
+
|
|
9
|
+
const envFile = () => {
|
|
10
|
+
const envFile = PH_HOME(`.env`)
|
|
11
|
+
if (!existsSync(envFile)) {
|
|
12
|
+
writeFileSync(envFile, '')
|
|
13
|
+
}
|
|
14
|
+
return envFile
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const _parse = () =>
|
|
18
|
+
parse(readFileSync(envFile(), { encoding: 'utf8' }).toString())
|
|
19
|
+
|
|
20
|
+
export const PluginCommand = () => {
|
|
21
|
+
const cmd = new Command(`plugin`)
|
|
22
|
+
.description(`Manage PocketHost plugins`)
|
|
23
|
+
.addCommand(
|
|
24
|
+
new Command(`install`)
|
|
25
|
+
.alias(`i`)
|
|
26
|
+
.argument(`<name>`, `NPM registry plugin name`)
|
|
27
|
+
.description(`Install a plugin`)
|
|
28
|
+
.action(async (name: string) => {
|
|
29
|
+
try {
|
|
30
|
+
const pkg = JSON.parse(
|
|
31
|
+
readFileSync(PH_PROJECT_DIR(`package.json`), 'utf8').toString(),
|
|
32
|
+
)
|
|
33
|
+
const { version } = pkg
|
|
34
|
+
await getCompatibleVersions(`pockethost`, version, [name])
|
|
35
|
+
|
|
36
|
+
const values = _parse()
|
|
37
|
+
values[`PH_PLUGINS`] = uniq([
|
|
38
|
+
...(values[`PH_PLUGINS`]
|
|
39
|
+
?.split(/,/)
|
|
40
|
+
.map((v) => v.trim())
|
|
41
|
+
.filter((v) => !!v) || []),
|
|
42
|
+
name,
|
|
43
|
+
]).join(`,`)
|
|
44
|
+
writeFileSync(
|
|
45
|
+
envFile(),
|
|
46
|
+
Object.entries(values)
|
|
47
|
+
.map(([k, v]) => `${k}=${v}`)
|
|
48
|
+
.join('\n'),
|
|
49
|
+
)
|
|
50
|
+
info(`Installed ${name}`)
|
|
51
|
+
info(`Written to ${envFile()}`)
|
|
52
|
+
} catch (e) {
|
|
53
|
+
error(`${e}`)
|
|
54
|
+
}
|
|
55
|
+
}),
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
.addCommand(
|
|
59
|
+
new Command(`list`)
|
|
60
|
+
.alias(`ls`)
|
|
61
|
+
.description(`List plugins`)
|
|
62
|
+
.action(async (name: string) => {
|
|
63
|
+
try {
|
|
64
|
+
for (const plugin of PH_PLUGINS()) {
|
|
65
|
+
const pkg = await getPackageJson(plugin)
|
|
66
|
+
console.log({ pkg })
|
|
67
|
+
info(`${plugin}@${pkg.version} - ${pkg?.description}`)
|
|
68
|
+
}
|
|
69
|
+
} catch (e) {
|
|
70
|
+
error(`${e}`)
|
|
71
|
+
}
|
|
72
|
+
}),
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
.addCommand(
|
|
76
|
+
new Command(`remove`)
|
|
77
|
+
.alias(`rm`)
|
|
78
|
+
.alias(`uninstall`)
|
|
79
|
+
.alias(`delete`)
|
|
80
|
+
.argument(`<name>`, `Plugin name`)
|
|
81
|
+
.description(`Remove a plugin`)
|
|
82
|
+
.action(async (name) => {
|
|
83
|
+
try {
|
|
84
|
+
await removePackage(name)
|
|
85
|
+
const values = _parse()
|
|
86
|
+
values[`PH_PLUGINS`] = uniq([
|
|
87
|
+
...(values[`PH_PLUGINS`]
|
|
88
|
+
?.split(/,/)
|
|
89
|
+
.map((v) => v.trim())
|
|
90
|
+
.filter((v) => v !== name) || []),
|
|
91
|
+
]).join(`,`)
|
|
92
|
+
writeFileSync(
|
|
93
|
+
envFile(),
|
|
94
|
+
Object.entries(values)
|
|
95
|
+
.map(([k, v]) => `${k}=${v}`)
|
|
96
|
+
.join('\n'),
|
|
97
|
+
)
|
|
98
|
+
info(`Removed ${name}`)
|
|
99
|
+
info(`Written to ${envFile()}`)
|
|
100
|
+
} catch (e) {
|
|
101
|
+
error(`${e}`)
|
|
102
|
+
}
|
|
103
|
+
}),
|
|
104
|
+
)
|
|
105
|
+
|
|
106
|
+
.addCommand(
|
|
107
|
+
new Command(`update`)
|
|
108
|
+
.alias(`up`)
|
|
109
|
+
.description(`Update all plugins`)
|
|
110
|
+
.action(async () => {
|
|
111
|
+
try {
|
|
112
|
+
const pkg = JSON.parse(
|
|
113
|
+
readFileSync(PH_PROJECT_DIR(`package.json`), 'utf8').toString(),
|
|
114
|
+
)
|
|
115
|
+
const { version } = pkg
|
|
116
|
+
await getCompatibleVersions(`pockethost`, version, PH_PLUGINS())
|
|
117
|
+
} catch (e) {
|
|
118
|
+
error(`${e}`)
|
|
119
|
+
}
|
|
120
|
+
}),
|
|
121
|
+
)
|
|
122
|
+
return cmd
|
|
123
|
+
}
|