@cyaxis/ulvia 0.0.1-alpha.9 → 0.0.3

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.
@@ -0,0 +1,182 @@
1
+ # Install Ulvia
2
+
3
+ This guide installs the Ulvia CLI and creates a first CMS instance on Ubuntu.
4
+ It is for operators and site owners; workspace contributors should use the
5
+ [development guide](../development/README.md).
6
+
7
+ > **Prerelease availability:** `@cyaxis/ulvia` is the official release package.
8
+ > Prereleases use the npm `next` tag; stable releases use `latest`.
9
+
10
+ ## 1. Prerequisites On Ubuntu
11
+
12
+ Ulvia requires a supported Ubuntu host, Docker Engine with the Docker Compose
13
+ plugin, and Bun. Follow the upstream instructions rather than copying an
14
+ unversioned third-party installation script:
15
+
16
+ - [Install Docker Engine on Ubuntu](https://docs.docker.com/engine/install/ubuntu/)
17
+ - [Install the Docker Compose plugin on Linux](https://docs.docker.com/compose/install/linux/)
18
+ - [Run Docker without `sudo` and configure startup](https://docs.docker.com/engine/install/linux-postinstall/)
19
+ - [Install Bun on Linux](https://bun.com/docs/installation)
20
+
21
+ Docker's Ubuntu packages include the Compose plugin when
22
+ `docker-compose-plugin` is installed. Verify the complete toolchain:
23
+
24
+ ```bash
25
+ docker version
26
+ docker compose version
27
+ bun --version
28
+ ```
29
+
30
+ The current release toolchain targets Bun 1.4.2 or newer. Docker must be running
31
+ and accessible to the account that executes `ulvia`.
32
+
33
+ ## 2. Install The CLI
34
+
35
+ Install the current prerelease globally from the public npm registry:
36
+
37
+ ```bash
38
+ bun add --global @cyaxis/ulvia@next
39
+ ulvia --help
40
+ ```
41
+
42
+ If `ulvia` is not found, reopen the terminal and check that `~/.bun/bin` is in
43
+ `PATH`, as described by the Bun installation guide.
44
+
45
+ ## 3. Create A Local Site
46
+
47
+ Start the shared infrastructure, then create one named instance:
48
+
49
+ ```bash
50
+ ulvia services start
51
+ ulvia instance create my-site --label "My site"
52
+ ulvia instance credentials my-site
53
+ ```
54
+
55
+ The first start uses the exact software version bundled into the installed CLI.
56
+ To bootstrap a different exact prerelease explicitly, use
57
+ `ulvia services start --version 0.0.1-beta`. This option never upgrades an
58
+ existing installation.
59
+
60
+ The site is available at `http://my-site.localhost:5100`. The credentials
61
+ command prints the initial administrator email and password. It never prints
62
+ the Provider, Repository, encryption, or instance service secrets.
63
+
64
+ Ulvia deliberately separates shared services from sites:
65
+
66
+ | Command | Responsibility |
67
+ | --- | --- |
68
+ | `ulvia services start` | Starts the proxy, MongoDB, Official Repository, and Provider. |
69
+ | `ulvia instance create <name>` | Provisions one Provider tenant and starts its Kernel. |
70
+ | `ulvia instance start <name>` | Restarts an existing instance without provisioning it again. |
71
+ | `ulvia start` | Starts shared services and every existing instance; it creates nothing. |
72
+
73
+ List and inspect the installation at any time:
74
+
75
+ ```bash
76
+ ulvia services status
77
+ ulvia instance list
78
+ ulvia instance status my-site
79
+ ```
80
+
81
+ Persistent data lives below `$XDG_DATA_HOME/ulvia` or
82
+ `~/.local/share/ulvia`. Commands can be run from any working directory.
83
+
84
+ ## 4. Daily Operations
85
+
86
+ ```bash
87
+ ulvia start
88
+ ulvia instance stop my-site
89
+ ulvia instance start my-site
90
+ ulvia services logs all --level warn
91
+ ulvia instance logs my-site kernel
92
+ ulvia services stop
93
+ ```
94
+
95
+ Stopping containers preserves persistent data. `services stop` also makes every
96
+ site unavailable because Kernels depend on the shared Provider and proxy.
97
+
98
+ ## 5. Upgrade Ulvia
99
+
100
+ Upgrade the host CLI through Bun:
101
+
102
+ ```bash
103
+ bun update --global @cyaxis/ulvia
104
+ ```
105
+
106
+ Upgrade deployable components independently with exact versions:
107
+
108
+ ```bash
109
+ ulvia upgrade kernel --version 0.0.1-beta
110
+ ulvia upgrade provider --version 0.0.1-beta
111
+ ulvia upgrade repository --version 0.0.1-beta
112
+ ```
113
+
114
+ Ulvia resolves each official Docker Hub tag to an immutable digest and reuses
115
+ that digest on subsequent starts. Registry channels such as `next` or `latest`
116
+ may identify releases for humans, but an installation never persists or
117
+ silently follows those mutable tags.
118
+
119
+ ## 6. Public Domain And HTTPS
120
+
121
+ Configure public networking before creating the first instance because the
122
+ canonical Kernel URLs become part of Provider provisioning:
123
+
124
+ ```bash
125
+ ulvia configure network \
126
+ --bind 0.0.0.0 \
127
+ --http-port 80 \
128
+ --tls acme \
129
+ --https-port 443 \
130
+ --acme-email ops@example.com
131
+
132
+ ulvia services start
133
+ ulvia instance create website --domain example.com
134
+ ulvia instance credentials website
135
+ ```
136
+
137
+ Before starting, point the domain's DNS records to the host and allow inbound
138
+ TCP traffic on ports 80 and 443. Review Docker's documented firewall behavior:
139
+ published container ports can bypass some `ufw` and `firewalld` rules unless
140
+ the host policy uses Docker's supported chains.
141
+
142
+ Repository and Provider management endpoints remain bound to loopback. Only the
143
+ shared proxy is exposed publicly.
144
+
145
+ ## 7. Backup, Reset, And Removal
146
+
147
+ Stop the installation before taking a filesystem-level backup of the Ulvia data
148
+ directory. Preserve the complete directory, including MongoDB, files,
149
+ credentials, encryption material, Repository state, and instance definitions.
150
+ Do not restore only selected secret or database files from different snapshots.
151
+
152
+ `reset` permanently removes Ulvia-owned local state:
153
+
154
+ ```bash
155
+ ulvia reset --yes
156
+ ```
157
+
158
+ Remove the CLI separately after stopping or resetting the installation:
159
+
160
+ ```bash
161
+ bun remove --global @cyaxis/ulvia
162
+ ```
163
+
164
+ Removing the CLI alone does not delete persistent CMS data or Docker resources.
165
+
166
+ ## 8. Troubleshooting
167
+
168
+ - **Docker permission denied:** complete Docker's Linux post-installation steps,
169
+ then start a new login session.
170
+ - **`docker compose` is unknown:** install the official Compose plugin rather
171
+ than the retired standalone `docker-compose` package.
172
+ - **Port 5100, 80, or 443 is occupied:** inspect the owner before changing the
173
+ persisted network configuration.
174
+ - **An image cannot be pulled:** verify network access and that the requested
175
+ exact Cyaxis image version has been published.
176
+ - **An instance returns 503:** check `ulvia services status`, then the Provider
177
+ and instance Kernel logs.
178
+ - **Stored encrypted data cannot be opened:** do not generate replacement keys
179
+ over an existing data directory; restore the matching complete backup.
180
+
181
+ For implementation diagnostics and contributor-only environment overrides, see
182
+ the [development and validation guide](../development/README.md).
package/README.md CHANGED
@@ -2,6 +2,9 @@
2
2
 
3
3
  Ulvia installation and release CLI.
4
4
 
5
+ For the operator journey from a fresh Ubuntu host to a running local or public
6
+ site, follow the [canonical installation guide](INSTALLATION.md).
7
+
5
8
  The workspace package contains private source code. Official releases are
6
9
  bundled without workspace dependencies and published publicly as
7
10
  `@cyaxis/ulvia`:
@@ -14,14 +17,16 @@ ulvia --help
14
17
  From the workspace, build and publish one exact release with:
15
18
 
16
19
  ```bash
17
- bun run cli:build --version 0.0.1-alpha.9
18
- bun run cli:publish --version 0.0.1-alpha.9
20
+ bun run cli:build --version 0.0.2 --stack-version 0.0.1-beta
21
+ bun run cli:publish --version 0.0.2
19
22
  ```
20
23
 
21
24
  The build creates a checked npm archive and SHA-256 receipt below
22
- `artifacts/cli`. Publishing accepts only that exact pair, targets the public npm
23
- registry, and uses the `next` tag for prereleases or `latest` for stable versions.
24
- It requires npm credentials configured outside the repository.
25
+ `artifacts/cli`. The CLI package version and its compatible initial Docker stack
26
+ version are independent and both are sealed into that receipt. Publishing
27
+ accepts only the exact pair, targets the public npm registry, and uses the
28
+ `next` tag for prereleases or `latest` for stable versions. It requires npm
29
+ credentials configured outside the repository.
25
30
 
26
31
  ```bash
27
32
  bun run ulvia -- start
@@ -33,9 +38,9 @@ bun run ulvia -- instance credentials preview
33
38
  bun run ulvia -- instance stop preview
34
39
  bun run ulvia -- instance delete preview --yes
35
40
  bun run ulvia -- services stop
36
- bun run ulvia -- upgrade kernel --version 0.0.1-alpha.9
37
- bun run ulvia -- upgrade provider --version 0.0.1-alpha.9
38
- bun run ulvia -- upgrade repository --version 0.0.1-alpha.9
41
+ bun run ulvia -- upgrade kernel --version 0.0.1-beta
42
+ bun run ulvia -- upgrade provider --version 0.0.1-beta
43
+ bun run ulvia -- upgrade repository --version 0.0.1-beta
39
44
  bun run ulvia -- reset --yes
40
45
  bun run ulvia -- release packages/official-repository/collections/ulvia-official
41
46
  bun run ulvia -- release /path/to/contract-directory
@@ -80,6 +85,10 @@ after the first instance because its canonical Kernel URL is part of Provider
80
85
  provisioning. Repository and Provider management ports remain loopback-only.
81
86
 
82
87
  `services start` starts only the shared proxy, MongoDB, Repository and Provider.
88
+ On first initialization it uses the exact version embedded by `cli:build`, or
89
+ an explicit `services start --version <version>` override. Later starts reuse
90
+ the persisted digests and reject a conflicting `--version`; component changes
91
+ must go through `upgrade`.
83
92
  `instance create` provisions one isolated Provider tenant and immediately starts
84
93
  its dedicated Kernel. `instance start` restarts only an already-provisioned
85
94
  instance's Kernel. All Kernels use the shared proxy port: an instance named
package/dist/index.js CHANGED
@@ -2002,7 +2002,6 @@ function parseComposeServices(source) {
2002
2002
  }
2003
2003
 
2004
2004
  // packages/runtimes/ulvia-cli/src/runtime/stack/orchestration/images.ts
2005
- var DEFAULT_STACK_VERSION = "0.0.1-alpha.9";
2006
2005
  var SUPPORTED_STACK_API = "1";
2007
2006
  var REPOSITORIES = {
2008
2007
  kernel: "docker.io/cyaxis/ulvia-kernel",
@@ -2139,6 +2138,18 @@ function localKernelEnvironment(instance, config, connection, services, image) {
2139
2138
  };
2140
2139
  }
2141
2140
 
2141
+ // packages/runtimes/ulvia-cli/src/runtime/stack/version.ts
2142
+ var injectedCliVersion = "0.0.3";
2143
+ var injectedStackVersion = "0.0.1-beta";
2144
+ var CLI_VERSION = injectedCliVersion ?? "development";
2145
+ var DEFAULT_STACK_VERSION = injectedStackVersion ?? "unbundled";
2146
+ function defaultStackVersion() {
2147
+ if (!injectedStackVersion) {
2148
+ throw new Error("This development CLI has no bundled stack version. Pass --version <version> on the first start.");
2149
+ }
2150
+ return injectedStackVersion;
2151
+ }
2152
+
2142
2153
  // packages/runtimes/ulvia-cli/src/runtime/stack/orchestration/state.ts
2143
2154
  import { createHash } from "crypto";
2144
2155
  import { chmod as chmod6, readFile as readFile5, writeFile as writeFile5 } from "fs/promises";
@@ -2238,12 +2249,10 @@ function validServiceImages(value) {
2238
2249
  }
2239
2250
 
2240
2251
  // packages/runtimes/ulvia-cli/src/runtime/stack/orchestration/services.ts
2241
- async function startLocalServices(paths, installation, log) {
2252
+ async function startLocalServices(paths, installation, log, requestedVersion) {
2242
2253
  const installed = await loadLocalServicesState(paths);
2243
- const images = installed?.images ?? {
2244
- provider: await pullOfficialImage("provider", DEFAULT_STACK_VERSION, log),
2245
- repository: await pullOfficialImage("repository", DEFAULT_STACK_VERSION, log)
2246
- };
2254
+ assertStartVersion(installed, requestedVersion);
2255
+ const images = installed?.images ?? await pullInitialImages(requestedVersion ?? defaultStackVersion(), log);
2247
2256
  await ensureOfficialImage(images.provider);
2248
2257
  await ensureOfficialImage(images.repository);
2249
2258
  const credentials = await serviceCredentials(paths);
@@ -2259,6 +2268,22 @@ async function startLocalServices(paths, installation, log) {
2259
2268
  await saveLocalServicesState(paths, installation, images);
2260
2269
  log(`Shared services are ready (Provider ${images.provider.version}, Repository ${images.repository.version}).`);
2261
2270
  }
2271
+ async function pullInitialImages(version, log) {
2272
+ const [provider, repository] = await Promise.all([
2273
+ pullOfficialImage("provider", version, log),
2274
+ pullOfficialImage("repository", version, log)
2275
+ ]);
2276
+ return { provider, repository };
2277
+ }
2278
+ function assertStartVersion(state, requestedVersion) {
2279
+ if (!state || !requestedVersion) {
2280
+ return;
2281
+ }
2282
+ const current = new Set([state.images.provider.version, state.images.repository.version]);
2283
+ if (current.size !== 1 || !current.has(requestedVersion)) {
2284
+ throw new Error("Shared services are already initialized with different versions. Use ulvia upgrade provider and ulvia upgrade repository.");
2285
+ }
2286
+ }
2262
2287
  async function upgradeLocalService(paths, component, version, log) {
2263
2288
  const installed = await loadLocalServicesState(paths);
2264
2289
  if (!installed) {
@@ -2339,7 +2364,7 @@ async function startLocalKernel(paths, name, log) {
2339
2364
  const services = await requireServices(paths);
2340
2365
  await requireRunningLocalProvider(paths);
2341
2366
  const installed = await loadLocalKernelState(runtime.paths);
2342
- const image = installed?.image ?? await pullOfficialImage("kernel", DEFAULT_STACK_VERSION, log);
2367
+ const image = installed?.image ?? await pullOfficialImage("kernel", services.images.provider.version, log);
2343
2368
  await ensureOfficialImage(image);
2344
2369
  const projectName = installed?.projectName ?? localKernelProjectName(paths, name);
2345
2370
  await composeUp(kernelProject(runtime.paths, runtime.config, runtime.connection, services, projectName, image));
@@ -3219,11 +3244,28 @@ async function makeTreeOwnerRemovable(path) {
3219
3244
  }
3220
3245
 
3221
3246
  // packages/runtimes/ulvia-cli/src/commands/local/services.ts
3247
+ var SERVICES_HELP = `Usage: ulvia services <start | stop | status | logs>
3248
+
3249
+ Manage the shared proxy, MongoDB, Repository, and Provider.`;
3250
+ var START_HELP = `Usage: ulvia services start [--version <version>]
3251
+
3252
+ Start shared services. On their first start, use the bundled stack version by
3253
+ default or the exact version supplied here. Existing installations keep their
3254
+ pinned image digests; use ulvia upgrade for later changes.
3255
+
3256
+ Bundled initial stack version: ${DEFAULT_STACK_VERSION}`;
3222
3257
  async function servicesCommand(args, paths, installation, log) {
3223
3258
  const [action, ...rest] = args;
3259
+ if (!action || action === "help" || action === "--help" || action === "-h") {
3260
+ log(SERVICES_HELP);
3261
+ return;
3262
+ }
3224
3263
  if (action === "start") {
3225
- expectNone(rest, "Usage: ulvia services start");
3226
- await startLocalServices(paths, installation, log);
3264
+ if (isHelp(rest)) {
3265
+ log(START_HELP);
3266
+ return;
3267
+ }
3268
+ await startLocalServices(paths, installation, log, parseStartVersion(rest));
3227
3269
  return;
3228
3270
  }
3229
3271
  if (action === "stop") {
@@ -3243,6 +3285,19 @@ async function servicesCommand(args, paths, installation, log) {
3243
3285
  }
3244
3286
  throw new Error("Usage: ulvia services <start | stop | status | logs>");
3245
3287
  }
3288
+ function parseStartVersion(args, usage = "Usage: ulvia services start [--version <version>]") {
3289
+ if (args.length === 0) {
3290
+ return;
3291
+ }
3292
+ if (args.length !== 2 || args[0] !== "--version" || !args[1]) {
3293
+ throw new Error(usage);
3294
+ }
3295
+ assertImageVersion(args[1]);
3296
+ return args[1];
3297
+ }
3298
+ function isHelp(args) {
3299
+ return args.length === 1 && (args[0] === "help" || args[0] === "--help" || args[0] === "-h");
3300
+ }
3246
3301
  async function printServicesStatus(paths, log) {
3247
3302
  const { state, services } = await describeLocalServices(paths);
3248
3303
  const expected = ["proxy", "mongo", "provider", "repository"];
@@ -3366,10 +3421,18 @@ async function localCommand(command, args, paths, log, environment) {
3366
3421
  await resetLocalInstallation(paths, log);
3367
3422
  return;
3368
3423
  }
3369
- if (command !== "start" || args.length > 0) {
3370
- throw new Error("Usage: ulvia start");
3424
+ if (command !== "start") {
3425
+ throw new Error("Usage: ulvia start [--version <version>]");
3426
+ }
3427
+ if (args.length === 1 && ["help", "--help", "-h"].includes(args[0] ?? "")) {
3428
+ log(`Usage: ulvia start [--version <version>]
3429
+
3430
+ Start shared services and every existing instance. The exact version only
3431
+ selects Provider and Repository images when shared services are uninitialized.`);
3432
+ return;
3371
3433
  }
3372
- await startLocalServices(paths, installation, log);
3434
+ const requestedVersion = parseStartVersion(args, "Usage: ulvia start [--version <version>]");
3435
+ await startLocalServices(paths, installation, log, requestedVersion);
3373
3436
  const instances = await listLocalInstanceNames(paths);
3374
3437
  if (instances.length === 0) {
3375
3438
  log("Shared services are ready. Create an instance with: ulvia instance create <name>");
@@ -29509,9 +29572,10 @@ function assertDigest(actual, expected) {
29509
29572
  var HELP = `Ulvia CMS CLI
29510
29573
 
29511
29574
  Usage:
29512
- ulvia start
29575
+ ulvia start [--version <version>]
29513
29576
  ulvia configure network [network options]
29514
- ulvia services <start | stop | status | logs>
29577
+ ulvia services start [--version <version>]
29578
+ ulvia services <stop | status | logs>
29515
29579
  ulvia instance create <name> [--label <label>] [--domain <domain>]
29516
29580
  ulvia instance <start | stop | status | credentials | logs> <name>
29517
29581
  ulvia instance list
@@ -29558,7 +29622,7 @@ async function runCli(args, options = {}) {
29558
29622
  return;
29559
29623
  }
29560
29624
  if (command === "--version" || command === "-v") {
29561
- log("0.1.0");
29625
+ log(CLI_VERSION);
29562
29626
  return;
29563
29627
  }
29564
29628
  if (![...LOCAL_COMMANDS, "release", "push", "pull", "yank", "restore", "prune"].includes(command)) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cyaxis/ulvia",
3
- "version": "0.0.1-alpha.9",
3
+ "version": "0.0.3",
4
4
  "description": "Ulvia CMS installation and release CLI.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -10,6 +10,7 @@
10
10
  "files": [
11
11
  "dist/",
12
12
  "README.md",
13
+ "INSTALLATION.md",
13
14
  "LICENSE"
14
15
  ],
15
16
  "engines": {