@naviyra/cloud-panel 0.0.0-stage → 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/.env.example +40 -0
- package/README.md +134 -2
- package/apps/agent/package.json +13 -0
- package/apps/agent/src/cloudflare.mjs +733 -0
- package/apps/agent/src/native-worker.mjs +52 -0
- package/apps/agent/src/native.mjs +457 -0
- package/apps/agent/src/runtime.mjs +760 -0
- package/apps/agent/src/server.mjs +195 -0
- package/apps/agent/src/static-server.mjs +53 -0
- package/apps/panel/AGENTS.md +9 -0
- package/apps/panel/CLAUDE.md +1 -0
- package/apps/panel/app/api/[...path]/route.js +445 -0
- package/apps/panel/app/globals.css +2057 -0
- package/apps/panel/app/icon.png +0 -0
- package/apps/panel/app/layout.jsx +18 -0
- package/apps/panel/app/login/page.jsx +108 -0
- package/apps/panel/app/page.jsx +33 -0
- package/apps/panel/app/ui/cloudflare.jsx +926 -0
- package/apps/panel/app/ui/dashboard.jsx +1487 -0
- package/apps/panel/app/ui/databases.jsx +293 -0
- package/apps/panel/app/ui/skeleton.jsx +196 -0
- package/apps/panel/app/ui/theme.jsx +35 -0
- package/apps/panel/lib/agent.mjs +83 -0
- package/apps/panel/lib/auth.mjs +48 -0
- package/apps/panel/lib/database-runtime.mjs +243 -0
- package/apps/panel/lib/databases.mjs +292 -0
- package/apps/panel/lib/db.mjs +6 -0
- package/apps/panel/next.config.mjs +8 -0
- package/apps/panel/package.json +22 -0
- package/apps/panel/public/naviyra-logo.png +0 -0
- package/bin/naviyra.mjs +177 -0
- package/db/001_init.sql +28 -0
- package/db/002_native_runtimes.sql +3 -0
- package/db/003_databases.sql +8 -0
- package/db/004_database_engines.sql +4 -0
- package/deploy/naviyra-agent.service +17 -0
- package/docker-compose.yml +18 -0
- package/docs/managed-runtime.md +52 -0
- package/docs/native-hosts.md +48 -0
- package/package.json +61 -4
- package/packages/runtime/artifacts.json +32 -0
- package/packages/runtime/index.cjs +526 -0
- package/packages/runtime/index.mjs +10 -0
- package/packages/runtime/package.json +6 -0
- package/packages/shared/index.mjs +85 -0
- package/packages/shared/package.json +9 -0
- package/scripts/migrate.mjs +18 -0
- package/scripts/postgres-local.mjs +97 -0
- package/scripts/runtime-download-manifest.mjs +30 -0
- package/scripts/runtime.mjs +20 -0
- package/scripts/seed.mjs +35 -0
- package/scripts/service-supervisor.mjs +164 -0
- package/scripts/setup-local.mjs +215 -0
- package/scripts/start-naviyra.mjs +303 -0
- package/scripts/windows-boot.mjs +259 -0
package/.env.example
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
DATABASE_URL=postgresql://naviyra:naviyra@127.0.0.1:55432/naviyra
|
|
2
|
+
POSTGRES_PORT=55432
|
|
3
|
+
PANEL_PORT=3000
|
|
4
|
+
# Optional absolute directory for Naviyra's private Docker runtime and data.
|
|
5
|
+
# Defaults to .runtime/docker at the repository root; never uses system Docker.
|
|
6
|
+
# NAVIYRA_RUNTIME_ROOT=D:/naviyra-data/docker
|
|
7
|
+
JWT_SECRET=replace-with-at-least-32-random-characters
|
|
8
|
+
AGENT_TOKEN=replace-with-at-least-32-random-characters
|
|
9
|
+
AGENT_URL=http://127.0.0.1:4001
|
|
10
|
+
AGENT_HOST=127.0.0.1
|
|
11
|
+
AGENT_PORT=4001
|
|
12
|
+
AGENT_MODE=native
|
|
13
|
+
# Set AGENT_MODE=native for Windows/Linux deployments without Docker.
|
|
14
|
+
# NATIVE_TUNNELS=false runs real apps locally without publishing DNS.
|
|
15
|
+
NATIVE_TUNNELS=false
|
|
16
|
+
# Optional absolute executable paths (otherwise use PATH):
|
|
17
|
+
# PYTHON_BIN=C:/Python314/python.exe
|
|
18
|
+
# PHP_BIN=C:/php/php.exe
|
|
19
|
+
# PHP_CGI_BIN=C:/php/php-cgi.exe
|
|
20
|
+
# CADDY_BIN=C:/tools/caddy.exe
|
|
21
|
+
# GO_BIN=C:/Program Files/Go/bin/go.exe
|
|
22
|
+
# GIT_BIN=C:/Program Files/Git/cmd/git.exe
|
|
23
|
+
# NPM_CLI_PATH=C:/Program Files/nodejs/node_modules/npm/bin/npm-cli.js
|
|
24
|
+
# COMPOSER_PHAR=C:/tools/composer.phar
|
|
25
|
+
# NATIVE_EXECUTABLES={"dotnet":"C:/Program Files/dotnet/dotnet.exe","java":"C:/Java/bin/java.exe"}
|
|
26
|
+
AGENT_ROOT=.runtime
|
|
27
|
+
PORT_MIN=3100
|
|
28
|
+
PORT_MAX=3999
|
|
29
|
+
ADMIN_EMAIL=admin@example.com
|
|
30
|
+
ADMIN_PASSWORD=replace-with-a-strong-password
|
|
31
|
+
# Linux production only:
|
|
32
|
+
# AGENT_MODE=host
|
|
33
|
+
# AGENT_ROOT=/opt/naviyra
|
|
34
|
+
# CLOUDFLARED_BIN=/usr/local/bin/cloudflared
|
|
35
|
+
# CLOUDFLARE_CERT=/root/.cloudflared/cert.pem
|
|
36
|
+
# CLOUDFLARE_API_TOKEN=token-with-zone-dns-edit-for-deletion
|
|
37
|
+
# CLOUDFLARE_ZONE_ID=your-zone-id
|
|
38
|
+
# APP_USER=naviyra-app
|
|
39
|
+
# APP_GROUP=naviyra-app
|
|
40
|
+
# PUBLIC_ORIGIN=https://panel.example.com
|
package/README.md
CHANGED
|
@@ -1,3 +1,135 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Naviyra Cloudflare Panel
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Install and start the panel:
|
|
4
|
+
|
|
5
|
+
```sh
|
|
6
|
+
npx @naviyra/cloud-panel
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
Run that command in an empty folder. It copies the panel there, installs dependencies, asks in the terminal for the administrator email, password, and agent port, then opens the browser. JWT and agent secrets are generated. Node.js 22.9 or newer is required. Startup also requires PostgreSQL (on Windows, PostgreSQL 18 at its default location, or set `POSTGRES_BIN` in `.env`) and the [private runtime prerequisites](docs/managed-runtime.md). Sign-in details are written to `.runtime/local-login.txt`.
|
|
10
|
+
|
|
11
|
+
On Windows, that install also registers a scheduled task named **Naviyra Cloud Panel**. The task runs as the same account, starts the panel immediately, starts it again at the next sign-in (including after a reboot), and restarts it if it stops. A supervisor restarts the panel a few seconds after a crash; Task Scheduler restarts the supervisor if that process dies. The panel keeps running after the installer exits. Progress is written to `.runtime/service.log`. Run the installer from an elevated PowerShell when the panel must start before anyone signs in. Stop it with `node scripts/windows-boot.mjs stop`, or remove it with `node scripts/windows-boot.mjs remove`.
|
|
12
|
+
|
|
13
|
+
To install and configure prerequisites before leaving the panel running, use `npx @naviyra/cloud-panel --install-only`. Use `--no-browser` to start without opening a browser. Re-running the installer checks all workspace dependencies and preserves existing `.env` credentials. This package is separate from `@naviyra/hosting-panel`.
|
|
14
|
+
|
|
15
|
+
**Native multi-platform hosting is now available:** Windows and Linux can deploy Node.js, Python (ASGI/WSGI), PHP (Caddy + PHP-CGI), Go, static frontends, and prebuilt applications through configured executable aliases. See [Native host setup](docs/native-hosts.md). Choose `AGENT_MODE=native`; Docker is not required for application deployments or for PostgreSQL if you use a native/remote database. The original Phase 1 systemd instructions below describe the retained legacy `host` backend.
|
|
16
|
+
|
|
17
|
+
A hosting panel built with Next.js App Router, PostgreSQL, and a separate Node.js agent. Create a project, choose its runtime, supply a public Git repository or ZIP, then deploy with an allocated port and supervised native processes. Cloudflare publishing is optional. The UI includes project search, status filters, deployment history, logs, host metrics, restart, redeploy, and deletion.
|
|
18
|
+
|
|
19
|
+
## Local development
|
|
20
|
+
|
|
21
|
+
### Single-click startup on Windows
|
|
22
|
+
|
|
23
|
+
Double-click **Start Naviyra.cmd** in the project folder. It checks/starts the local panel PostgreSQL database, applies migrations, starts Naviyra's private Docker runtime, starts the agent, builds/starts the panel, and opens the browser. An existing administrator password is never reset. Already-running services are reused, and repeated clicks wait for the existing launcher.
|
|
24
|
+
|
|
25
|
+
Keep the single launcher window open. Press Ctrl+C to stop the panel and agent started by that window; PostgreSQL, Docker, and stored database data are retained. Double-clicking the command file starts the current session only. The `npx @naviyra/cloud-panel` installer is what registers the Windows startup task. Node.js, `npm install`, the configured panel PostgreSQL installation, and OS runtime prerequisites must be available. Startup failures remain visible in the window. The same launcher can be run on Linux with `npm run services:start`.
|
|
26
|
+
|
|
27
|
+
Set `PANEL_PORT` in `.env` if port 3000 is unavailable. The launcher expects a local agent matching `AGENT_URL`/`AGENT_PORT` and opens `PUBLIC_ORIGIN` when configured.
|
|
28
|
+
|
|
29
|
+
Requires Node.js 22.9+ and PostgreSQL. Docker is optional. For the no-Docker path below, install PostgreSQL first; see [native setup](docs/native-hosts.md) for executable paths and other runtimes.
|
|
30
|
+
|
|
31
|
+
Run `npm run setup:local` in a terminal to enter the administrator email, password, and agent port instead of copying the environment template. JWT and agent secrets are generated. The agent URL uses the port you enter. Credentials are written to the ignored `.runtime/local-login.txt`. PostgreSQL is published only on loopback port 55432.
|
|
32
|
+
|
|
33
|
+
```powershell
|
|
34
|
+
npm install
|
|
35
|
+
Copy-Item .env.example .env
|
|
36
|
+
# Edit .env: choose unique JWT_SECRET / AGENT_TOKEN (32+ chars),
|
|
37
|
+
# ADMIN_EMAIL and ADMIN_PASSWORD (12+ chars).
|
|
38
|
+
npm run db:local
|
|
39
|
+
npm run db:migrate
|
|
40
|
+
npm run db:seed
|
|
41
|
+
npm run agent
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
In a second terminal at the repository root:
|
|
45
|
+
|
|
46
|
+
```powershell
|
|
47
|
+
npm run dev
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
Open <http://localhost:3000> and sign in with your seeded administrator. `npm run db:seed` resets the configured administrator password when rerun. Start both processes after changing `.env`. Never commit credentials.
|
|
51
|
+
|
|
52
|
+
The environment template uses `AGENT_MODE=native` with `NATIVE_TUNNELS=false`: applications run for real locally, while public DNS/tunnels remain disabled. Use `AGENT_MODE=mock` for simulation-only UI work. Mock mode does not install or start apps, and its public URLs do not work. Both modes use real PostgreSQL. The local agent state lives in `apps/agent/.runtime` when `AGENT_ROOT=.runtime` is used through `npm run agent`. If you prefer a disposable Docker database, `docker compose up -d` remains available instead of `db:local`; do not start both on the same port.
|
|
53
|
+
|
|
54
|
+
## Legacy Linux systemd host (`AGENT_MODE=host`, Node.js only)
|
|
55
|
+
|
|
56
|
+
This MVP is for a **single trusted server owner deploying trusted code**. It is not a sandbox for hostile tenants. Package lifecycle/build/start scripts run as the unprivileged `naviyra-app` user, shared across apps; the host agent runs as root to manage systemd. The agent uses fixed executables and argument arrays, never a shell for panel-supplied commands. Repository URLs accept public HTTPS GitHub, GitLab and Bitbucket sources only; redirects and submodules are disabled. Repositories and package scripts still require your trust.
|
|
57
|
+
|
|
58
|
+
1. Install Node.js 22.9+, npm, git, systemd, PostgreSQL, and [cloudflared](https://developers.cloudflare.com/tunnel/downloads/). The runner expects `/usr/bin/node`, `/usr/bin/npm`, `/usr/bin/git`, `/usr/sbin/runuser` and `/usr/local/bin/cloudflared`; set `CLOUDFLARED_BIN` if needed. Use system packages rather than a root-only nvm installation.
|
|
59
|
+
2. Place the repository at `/opt/naviyra-panel`, run `npm ci`, and create `.env` from the example. Use a production PostgreSQL URL and unique random secrets. Restrict `.env` to the service accounts that need it.
|
|
60
|
+
3. Create the application account:
|
|
61
|
+
|
|
62
|
+
```sh
|
|
63
|
+
sudo useradd --system --user-group --home-dir /nonexistent --shell /usr/sbin/nologin naviyra-app
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
4. Authenticate once as the agent's owner:
|
|
67
|
+
|
|
68
|
+
```sh
|
|
69
|
+
sudo cloudflared tunnel login
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
The chosen domain must be in your Cloudflare account. Set `CLOUDFLARE_CERT` to the generated `cert.pem`. Each project gets a locally managed tunnel, its own credentials/config, and a separate tunnel service. See [Cloudflare's local tunnel guide](https://developers.cloudflare.com/tunnel/features/locally-managed-tunnels/create-local-tunnel/).
|
|
73
|
+
|
|
74
|
+
5. Set `AGENT_MODE=host`, `AGENT_ROOT=/opt/naviyra`, `AGENT_HOST=127.0.0.1`, `AGENT_URL=http://127.0.0.1:4001`, and `PUBLIC_ORIGIN=https://panel.example.com`. For automatic DNS deletion also set `CLOUDFLARE_ZONE_ID` and `CLOUDFLARE_API_TOKEN` with DNS Edit for that zone. Deletion refuses to discard project state if external cleanup fails, so you can retry. Only matching tunnel CNAMEs are removed. This MVP assumes one DNS zone.
|
|
75
|
+
6. Run migrations, seed the owner, and build:
|
|
76
|
+
|
|
77
|
+
```sh
|
|
78
|
+
npm run db:migrate
|
|
79
|
+
npm run db:seed
|
|
80
|
+
npm run build
|
|
81
|
+
sudo cp deploy/naviyra-agent.service /etc/systemd/system/
|
|
82
|
+
sudo systemctl daemon-reload
|
|
83
|
+
sudo systemctl enable --now naviyra-agent
|
|
84
|
+
npm start
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
Run the panel under a process supervisor as an unprivileged account, with access to its configuration. Publish its loopback port through a separately configured Cloudflare tunnel or HTTPS reverse proxy. Production cookies require HTTPS. Keep the agent and PostgreSQL ports private; if the agent is on another host, terminate TLS and use an HTTPS `AGENT_URL` (plaintext remote URLs are rejected). The supplied agent unit is root-only; use a separate panel process.
|
|
88
|
+
|
|
89
|
+
7. Create a project using a full hostname such as `api.example.com`, upload a ZIP or enter a repository URL, open the project and click **Deploy project**. Watch deployment output. An application must provide a `package.json` at the source root with a `start` script, listen on `process.env.PORT`, and bind to `127.0.0.1`. If `build` exists it runs before start. Locked projects use `npm ci`; others use `npm install`. ZIPs are limited to 25 MB compressed / 200 MB expanded / 10,000 entries and cannot contain symlinks, `.git`, or `node_modules`.
|
|
90
|
+
|
|
91
|
+
## Data and operations
|
|
92
|
+
|
|
93
|
+
### Application database installation
|
|
94
|
+
|
|
95
|
+
The Databases screen supports PostgreSQL, MySQL, and MariaDB. Selecting one automatically checks for its Docker image, downloads it if missing, creates an isolated database container, and waits for readiness before returning credentials. Images are `postgres:17`, `mysql:8.4`, and `mariadb:11.4`; cached images are reused. Initialization follows the official [PostgreSQL](https://hub.docker.com/_/postgres), [MySQL](https://hub.docker.com/_/mysql), and [MariaDB](https://hub.docker.com/_/mariadb) images.
|
|
96
|
+
|
|
97
|
+
Run `npm install` and `npm run db:migrate` after upgrading. **No separate Docker installation or Docker Desktop is required.** Naviyra downloads pinned, SHA-256 verified Docker binaries on first use and starts a private engine. Native applications on the panel server connect using the returned loopback host and allocated port. External Docker executables, contexts, credentials, and `DOCKER_HOST` are not used. A containerized panel is not supported by this connection model. See [managed runtime setup](docs/managed-runtime.md) for Windows/WSL2 and Linux prerequisites.
|
|
98
|
+
|
|
99
|
+
Each managed database keeps its data in a private Docker volume and restarts with the managed engine unless explicitly stopped. Password reset and deletion operate on the selected engine; deletion removes that container and its data volume. Passwords are returned only on creation/reset, although runtime administrators can inspect initialization secrets. First downloads may take several minutes; allow long-running requests through your reverse proxy. If setup fails, its newly created container and volume are removed; interrupted panel processes may require manual cleanup of a labeled `naviyra-db-<id>` container.
|
|
100
|
+
|
|
101
|
+
The **PostgreSQL (existing native server)** option retains the original no-Docker provisioning path. Existing databases continue to work. The panel's own metadata still requires PostgreSQL configured through `DATABASE_URL`; application engine selection does not change that prerequisite.
|
|
102
|
+
|
|
103
|
+
- `db/001_init.sql`: users, agents, projects, tunnels, deployments, and audit trail. Migrations are repeatable for this initial schema.
|
|
104
|
+
- Agent state is atomically written to `AGENT_ROOT/state.json`; deployments are serialized and accepted before work runs. Interrupted jobs become failed after agent restart. Panel polling reconciles statuses and tunnel metadata to PostgreSQL; reconciliation runs when the panel is open. A deployment continues if the browser closes.
|
|
105
|
+
- Deployment logs are bounded to the last 100 KB; service/tunnel logs come from `journalctl`. Deployment history stores job status/error and a reference to the project's recent log stream, not a permanent per-job log archive.
|
|
106
|
+
- Redeploy stops the previous app and replaces its source; this MVP has downtime and no rollback. A failed deployment stops its services and retains source/tunnel metadata for retry or explicit deletion. Delete performs DNS, systemd, tunnel and filesystem cleanup before removing the database row.
|
|
107
|
+
- Running means the app accepted a local TCP connection and both systemd services were active at deployment completion. Detail metrics report current service state. Tunnel service activity does not prove global DNS propagation or external HTTPS availability.
|
|
108
|
+
- CPU shows cumulative systemd service CPU seconds; RAM shows current service bytes. Host load is the OS load average (not a percentage); Windows does not provide it. Service counters unavailable from systemd display zero.
|
|
109
|
+
- Authentication uses bcrypt and an 8-hour signed JWT in an HTTP-only same-site cookie, same-origin checks for writes, owner-scoped project reads and administrator-only mutations. Login throttling is in-memory per email for this single panel instance. Configure edge rate limiting for public production access. Accounts are provisioned by the seed command; no public signup.
|
|
110
|
+
- Project environment-variable editing, private Git auth, other runtimes, rollback, backups, full tenant isolation, and multiple agents are deferred.
|
|
111
|
+
|
|
112
|
+
## Checks
|
|
113
|
+
|
|
114
|
+
```sh
|
|
115
|
+
npm test
|
|
116
|
+
npm run build
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
Tests exercise authentication, input/command restrictions, ZIP traversal and symlink rejection, mock deployment, unique ports, restart/delete, persistence, and interrupted-job recovery. Linux systemd / real Cloudflare provisioning require a configured Linux host and account; local mock tests cannot certify those external integrations.
|
|
120
|
+
|
|
121
|
+
With PostgreSQL, the mock agent, and the development panel running, `npm run test:e2e` runs the browser workflow against the administrator configured in `.env`. It uses an installed Microsoft Edge, verifies sign-in, CSRF rejection, create/deploy/redeploy/restart/delete, checks mobile overflow, and saves desktop/mobile screenshots under `.runtime`. Use a disposable development database for this check. `examples/hello-node` is a minimal deployable app; ZIP the contents of that directory for an upload test.
|
|
122
|
+
|
|
123
|
+
## Layout
|
|
124
|
+
|
|
125
|
+
```text
|
|
126
|
+
apps/panel Next.js UI, session auth, PostgreSQL API, agent client
|
|
127
|
+
apps/agent Authenticated HTTP API and privileged host runner
|
|
128
|
+
packages/shared Zod input validation and limits
|
|
129
|
+
db PostgreSQL schema
|
|
130
|
+
scripts Migration and administrator bootstrap
|
|
131
|
+
deploy Linux systemd service
|
|
132
|
+
tests Agent integration and security regression tests
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
Next.js setup follows the [App Router installation documentation](https://nextjs.org/docs/app/getting-started/installation). The original scope is in `.cursor/plans/naviyra_panel_mvp_54bbb80a.plan.md`.
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@naviyra/agent",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"private": true,
|
|
5
|
+
"type": "module",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"start": "node --env-file-if-exists=../../.env src/server.mjs"
|
|
8
|
+
},
|
|
9
|
+
"dependencies": {
|
|
10
|
+
"@naviyra/shared": "1.0.0",
|
|
11
|
+
"yauzl": "^3.2.0"
|
|
12
|
+
}
|
|
13
|
+
}
|