Upgrade to SpacesOps v1.0.1 and fix v1.0.1:1 startup on StartOS.
Bump the image to spacesops/spacesops:v1.0.1, always inject NODE_EXTRA_CA_CERTS from sdk.getSslCertificate so the upstream entrypoint no longer crashes on unset _SCRIPT_DIR, and document the same-host HTTPS behavior in the README. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -39,7 +39,7 @@ auto-connects to it — see [Installation and First-Run Flow](#installation-and-
|
|||||||
|
|
||||||
| Field | Value |
|
| Field | Value |
|
||||||
| --- | --- |
|
| --- | --- |
|
||||||
| Image | `docker.io/spacesops/spacesops:v1.0.0` |
|
| Image | `docker.io/spacesops/spacesops:v1.0.1` |
|
||||||
| Base | `node:20-alpine` |
|
| Base | `node:20-alpine` |
|
||||||
| Architectures | `x86_64` (linux/amd64), `aarch64` (linux/arm64) |
|
| Architectures | `x86_64` (linux/amd64), `aarch64` (linux/arm64) |
|
||||||
| Entrypoint | The image's `/app/docker-entrypoint.sh` is **kept**. StartOS runs `/app/docker-entrypoint.sh node server.js` as the daemon. |
|
| Entrypoint | The image's `/app/docker-entrypoint.sh` is **kept**. StartOS runs `/app/docker-entrypoint.sh node server.js` as the daemon. |
|
||||||
@@ -139,7 +139,7 @@ volume is **not** part of this package's backup.
|
|||||||
and sync Spaces before (or alongside) SpacesOps; the service restarts until
|
and sync Spaces before (or alongside) SpacesOps; the service restarts until
|
||||||
those credentials are available.
|
those credentials are available.
|
||||||
2. **The admin password is fixed and well-known.** Admin Basic Auth is hardcoded
|
2. **The admin password is fixed and well-known.** Admin Basic Auth is hardcoded
|
||||||
in the v1.0.0 image as `admin` / `Whatever!` with **no environment override**.
|
in the v1.0.1 image as `admin` / `Whatever!` with **no environment override**.
|
||||||
It cannot be changed without rebuilding the image. **Keep this service private
|
It cannot be changed without rebuilding the image. **Keep this service private
|
||||||
(Tor-only) and never expose its admin routes to the public internet** — the
|
(Tor-only) and never expose its admin routes to the public internet** — the
|
||||||
admin area can run SQL and manage tenants. See **Show Admin Credentials**.
|
admin area can run SQL and manage tenants. See **Show Admin Credentials**.
|
||||||
@@ -151,7 +151,11 @@ volume is **not** part of this package's backup.
|
|||||||
5. **The SUBS backend is not auto-wired to the Spaces subs daemon in v1.** The
|
5. **The SUBS backend is not auto-wired to the Spaces subs daemon in v1.** The
|
||||||
Spaces service's subs daemon listens on 7777 with a different API/auth than
|
Spaces service's subs daemon listens on 7777 with a different API/auth than
|
||||||
the SUBS endpoint (port 7244) SpacesOps expects, so SUBS must be configured
|
the SUBS endpoint (port 7244) SpacesOps expects, so SUBS must be configured
|
||||||
manually if used.
|
manually if used. StartOS always sets `NODE_EXTRA_CA_CERTS` to the StartOS
|
||||||
|
root CA (fetched via `sdk.getSslCertificate` for the SUBS `*.startos`
|
||||||
|
hostname when configured, otherwise `spaces.startos`) so outbound HTTPS to
|
||||||
|
same-host StartOS services succeeds and the v1.0.1 image entrypoint does not
|
||||||
|
crash on its broken `_SCRIPT_DIR` default.
|
||||||
|
|
||||||
## What Is Unchanged from Upstream
|
## What Is Unchanged from Upstream
|
||||||
|
|
||||||
@@ -166,8 +170,8 @@ volume is **not** part of this package's backup.
|
|||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
package_id: spacesops
|
package_id: spacesops
|
||||||
upstream_version: 1.0.0
|
upstream_version: 1.0.1
|
||||||
image: docker.io/spacesops/spacesops:v1.0.0
|
image: docker.io/spacesops/spacesops:v1.0.1
|
||||||
architectures: [x86_64, aarch64]
|
architectures: [x86_64, aarch64]
|
||||||
volumes:
|
volumes:
|
||||||
main: /data
|
main: /data
|
||||||
@@ -196,6 +200,7 @@ optional_env_vars: # only set when configured via configure-platform
|
|||||||
- SUBS_URI_VALUE
|
- SUBS_URI_VALUE
|
||||||
- SUBS_RPC_USER
|
- SUBS_RPC_USER
|
||||||
- SUBS_RPC_PASSWORD
|
- SUBS_RPC_PASSWORD
|
||||||
|
- NODE_EXTRA_CA_CERTS # /data/.startos/startos-root-ca.crt (always set)
|
||||||
admin_credentials:
|
admin_credentials:
|
||||||
username: admin
|
username: admin
|
||||||
password: Whatever! # FIXED, baked into image, cannot be changed
|
password: Whatever! # FIXED, baked into image, cannot be changed
|
||||||
|
|||||||
@@ -0,0 +1,64 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
width="1024mm"
|
||||||
|
height="500mm"
|
||||||
|
viewBox="0 0 1024 500"
|
||||||
|
version="1.1"
|
||||||
|
id="svg1"
|
||||||
|
inkscape:version="1.3.2 (091e20e, 2023-11-25)"
|
||||||
|
sodipodi:docname="spaceswallet.svg"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg">
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="namedview1"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#000000"
|
||||||
|
borderopacity="0.25"
|
||||||
|
inkscape:showpageshadow="2"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:pagecheckerboard="0"
|
||||||
|
inkscape:deskcolor="#d1d1d1"
|
||||||
|
inkscape:document-units="mm"
|
||||||
|
inkscape:zoom="0.15"
|
||||||
|
inkscape:cx="2150"
|
||||||
|
inkscape:cy="110"
|
||||||
|
inkscape:window-width="1312"
|
||||||
|
inkscape:window-height="874"
|
||||||
|
inkscape:window-x="184"
|
||||||
|
inkscape:window-y="29"
|
||||||
|
inkscape:window-maximized="0"
|
||||||
|
inkscape:current-layer="layer1" />
|
||||||
|
<defs
|
||||||
|
id="defs1" />
|
||||||
|
<g
|
||||||
|
inkscape:label="Layer 1"
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
id="layer1">
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:108.156px;font-family:Outfit;-inkscape-font-specification:'Outfit, @wght=400';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;font-variation-settings:'wght' 400;fill:#903369;fill-opacity:1;stroke:none;stroke-width:15.3291;stroke-linecap:round;stroke-miterlimit:3;paint-order:fill markers stroke"
|
||||||
|
x="473.026"
|
||||||
|
y="159.67598"
|
||||||
|
id="text1"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan1"
|
||||||
|
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:108.156px;font-family:Outfit;-inkscape-font-specification:'Outfit, @wght=400';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;font-variation-settings:'wght' 400;fill:#903369;fill-opacity:1;stroke:none;stroke-width:15.3291"
|
||||||
|
x="473.026"
|
||||||
|
y="159.67598">@</tspan></text>
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:108.156px;font-family:Outfit;-inkscape-font-specification:'Outfit, @wght=400';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;font-variation-settings:'wght' 400;fill:#903369;fill-opacity:1;stroke:none;stroke-width:15.3291;stroke-linecap:round;stroke-miterlimit:3;paint-order:fill markers stroke"
|
||||||
|
x="96.926056"
|
||||||
|
y="312.17776"
|
||||||
|
id="text1-3"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan1-9"
|
||||||
|
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:141.111px;font-family:Outfit;-inkscape-font-specification:'Outfit, @wght=400';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;font-variation-settings:'wght' 400;fill:#903369;fill-opacity:1;stroke:none;stroke-width:15.3291"
|
||||||
|
x="96.926056"
|
||||||
|
y="312.17776">SpacesWallet</tspan></text>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 3.3 KiB |
@@ -8,7 +8,7 @@
|
|||||||
version="1.1"
|
version="1.1"
|
||||||
id="svg1"
|
id="svg1"
|
||||||
inkscape:version="1.3.2 (091e20e, 2023-11-25)"
|
inkscape:version="1.3.2 (091e20e, 2023-11-25)"
|
||||||
sodipodi:docname="spacesops.svg"
|
sodipodi:docname="icon.svg"
|
||||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
@@ -25,7 +25,7 @@
|
|||||||
inkscape:document-units="mm"
|
inkscape:document-units="mm"
|
||||||
inkscape:zoom="0.5"
|
inkscape:zoom="0.5"
|
||||||
inkscape:cx="365"
|
inkscape:cx="365"
|
||||||
inkscape:cy="260"
|
inkscape:cy="452"
|
||||||
inkscape:window-width="1312"
|
inkscape:window-width="1312"
|
||||||
inkscape:window-height="995"
|
inkscape:window-height="995"
|
||||||
inkscape:window-x="550"
|
inkscape:window-x="550"
|
||||||
@@ -40,14 +40,14 @@
|
|||||||
id="layer1">
|
id="layer1">
|
||||||
<text
|
<text
|
||||||
xml:space="preserve"
|
xml:space="preserve"
|
||||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:139.331px;font-family:Outfit;-inkscape-font-specification:'Outfit, @wght=400';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;font-variation-settings:'wght' 400;fill:#903369;fill-opacity:1;stroke:none;stroke-width:19.7477;stroke-linecap:round;stroke-miterlimit:3;paint-order:fill markers stroke"
|
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:108.156px;font-family:Outfit;-inkscape-font-specification:'Outfit, @wght=400';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;font-variation-settings:'wght' 400;fill:#903369;fill-opacity:1;stroke:none;stroke-width:15.3291;stroke-linecap:round;stroke-miterlimit:3;paint-order:fill markers stroke"
|
||||||
x="-1.9590863"
|
x="10.27656"
|
||||||
y="82.934502"
|
y="75.009308"
|
||||||
id="text1"><tspan
|
id="text1"><tspan
|
||||||
sodipodi:role="line"
|
sodipodi:role="line"
|
||||||
id="tspan1"
|
id="tspan1"
|
||||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:139.331px;font-family:Outfit;-inkscape-font-specification:'Outfit, @wght=400';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;font-variation-settings:'wght' 400;fill:#903369;fill-opacity:1;stroke:none;stroke-width:19.7477"
|
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:108.156px;font-family:Outfit;-inkscape-font-specification:'Outfit, @wght=400';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;font-variation-settings:'wght' 400;fill:#903369;fill-opacity:1;stroke:none;stroke-width:15.3291"
|
||||||
x="-1.9590863"
|
x="10.27656"
|
||||||
y="82.934502">@</tspan></text>
|
y="75.009308">@</tspan></text>
|
||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 2.2 KiB |
+7
-7
@@ -25,7 +25,7 @@
|
|||||||
inkscape:document-units="mm"
|
inkscape:document-units="mm"
|
||||||
inkscape:zoom="0.5"
|
inkscape:zoom="0.5"
|
||||||
inkscape:cx="365"
|
inkscape:cx="365"
|
||||||
inkscape:cy="260"
|
inkscape:cy="452"
|
||||||
inkscape:window-width="1312"
|
inkscape:window-width="1312"
|
||||||
inkscape:window-height="995"
|
inkscape:window-height="995"
|
||||||
inkscape:window-x="550"
|
inkscape:window-x="550"
|
||||||
@@ -40,14 +40,14 @@
|
|||||||
id="layer1">
|
id="layer1">
|
||||||
<text
|
<text
|
||||||
xml:space="preserve"
|
xml:space="preserve"
|
||||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:139.331px;font-family:Outfit;-inkscape-font-specification:'Outfit, @wght=400';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;font-variation-settings:'wght' 400;fill:#903369;fill-opacity:1;stroke:none;stroke-width:19.7477;stroke-linecap:round;stroke-miterlimit:3;paint-order:fill markers stroke"
|
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:108.156px;font-family:Outfit;-inkscape-font-specification:'Outfit, @wght=400';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;font-variation-settings:'wght' 400;fill:#903369;fill-opacity:1;stroke:none;stroke-width:15.3291;stroke-linecap:round;stroke-miterlimit:3;paint-order:fill markers stroke"
|
||||||
x="-1.9590863"
|
x="10.27656"
|
||||||
y="82.934502"
|
y="75.009308"
|
||||||
id="text1"><tspan
|
id="text1"><tspan
|
||||||
sodipodi:role="line"
|
sodipodi:role="line"
|
||||||
id="tspan1"
|
id="tspan1"
|
||||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:139.331px;font-family:Outfit;-inkscape-font-specification:'Outfit, @wght=400';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;font-variation-settings:'wght' 400;fill:#903369;fill-opacity:1;stroke:none;stroke-width:19.7477"
|
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:108.156px;font-family:Outfit;-inkscape-font-specification:'Outfit, @wght=400';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;font-variation-settings:'wght' 400;fill:#903369;fill-opacity:1;stroke:none;stroke-width:15.3291"
|
||||||
x="-1.9590863"
|
x="10.27656"
|
||||||
y="82.934502">@</tspan></text>
|
y="75.009308">@</tspan></text>
|
||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 2.2 KiB |
@@ -0,0 +1,64 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
width="1024mm"
|
||||||
|
height="500mm"
|
||||||
|
viewBox="0 0 1024 500"
|
||||||
|
version="1.1"
|
||||||
|
id="svg1"
|
||||||
|
inkscape:version="1.3.2 (091e20e, 2023-11-25)"
|
||||||
|
sodipodi:docname="spaceswallet.svg"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg">
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="namedview1"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#000000"
|
||||||
|
borderopacity="0.25"
|
||||||
|
inkscape:showpageshadow="2"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:pagecheckerboard="0"
|
||||||
|
inkscape:deskcolor="#d1d1d1"
|
||||||
|
inkscape:document-units="mm"
|
||||||
|
inkscape:zoom="0.15"
|
||||||
|
inkscape:cx="2150"
|
||||||
|
inkscape:cy="1643.3333"
|
||||||
|
inkscape:window-width="1312"
|
||||||
|
inkscape:window-height="874"
|
||||||
|
inkscape:window-x="184"
|
||||||
|
inkscape:window-y="29"
|
||||||
|
inkscape:window-maximized="0"
|
||||||
|
inkscape:current-layer="layer1" />
|
||||||
|
<defs
|
||||||
|
id="defs1" />
|
||||||
|
<g
|
||||||
|
inkscape:label="Layer 1"
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
id="layer1">
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:108.156px;font-family:Outfit;-inkscape-font-specification:'Outfit, @wght=400';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;font-variation-settings:'wght' 400;fill:#903369;fill-opacity:1;stroke:none;stroke-width:15.3291;stroke-linecap:round;stroke-miterlimit:3;paint-order:fill markers stroke"
|
||||||
|
x="473.026"
|
||||||
|
y="159.67598"
|
||||||
|
id="text1"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan1"
|
||||||
|
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:108.156px;font-family:Outfit;-inkscape-font-specification:'Outfit, @wght=400';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;font-variation-settings:'wght' 400;fill:#903369;fill-opacity:1;stroke:none;stroke-width:15.3291"
|
||||||
|
x="473.026"
|
||||||
|
y="159.67598">@</tspan></text>
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:108.156px;font-family:Outfit;-inkscape-font-specification:'Outfit, @wght=400';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;font-variation-settings:'wght' 400;fill:#903369;fill-opacity:1;stroke:none;stroke-width:15.3291;stroke-linecap:round;stroke-miterlimit:3;paint-order:fill markers stroke"
|
||||||
|
x="96.926056"
|
||||||
|
y="312.17776"
|
||||||
|
id="text1-3"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan1-9"
|
||||||
|
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:141.111px;font-family:Outfit;-inkscape-font-specification:'Outfit, @wght=400';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;font-variation-settings:'wght' 400;fill:#903369;fill-opacity:1;stroke:none;stroke-width:15.3291"
|
||||||
|
x="96.926056"
|
||||||
|
y="312.17776">SpacesWallet</tspan></text>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 3.3 KiB |
@@ -1,3 +1,4 @@
|
|||||||
|
import { mkdir, writeFile } from 'fs/promises'
|
||||||
import { storeJson } from './fileModels/storeJson'
|
import { storeJson } from './fileModels/storeJson'
|
||||||
import { i18n } from './i18n'
|
import { i18n } from './i18n'
|
||||||
import { sdk } from './sdk'
|
import { sdk } from './sdk'
|
||||||
@@ -8,6 +9,10 @@ import {
|
|||||||
SPACED_RPC_URL,
|
SPACED_RPC_URL,
|
||||||
SPACED_WALLETLOAD_NAME,
|
SPACED_WALLETLOAD_NAME,
|
||||||
spacesDataDir,
|
spacesDataDir,
|
||||||
|
startOsHostnameFromUrl,
|
||||||
|
nodeExtraCaCertContainerPath,
|
||||||
|
nodeExtraCaCertVolumeSubpath,
|
||||||
|
SPACES_PACKAGE_ID,
|
||||||
uiPort,
|
uiPort,
|
||||||
} from './utils'
|
} from './utils'
|
||||||
|
|
||||||
@@ -106,6 +111,23 @@ export const main = sdk.setupMain(async ({ effects }) => {
|
|||||||
if (store.subsUser) env.SUBS_RPC_USER = store.subsUser
|
if (store.subsUser) env.SUBS_RPC_USER = store.subsUser
|
||||||
if (store.subsPassword) env.SUBS_RPC_PASSWORD = store.subsPassword
|
if (store.subsPassword) env.SUBS_RPC_PASSWORD = store.subsPassword
|
||||||
|
|
||||||
|
// v1.0.1's entrypoint sources setup-spacesops-env.sh with set -u. That file
|
||||||
|
// exports NODE_EXTRA_CA_CERTS using ${_SCRIPT_DIR}, but _SCRIPT_DIR is set on
|
||||||
|
// a separate non-export line the entrypoint never evals — startup crashes
|
||||||
|
// unless NODE_EXTRA_CA_CERTS is already set. Fetch the StartOS root CA for
|
||||||
|
// outbound *.startos HTTPS (SUBS_URI host when configured, else Spaces).
|
||||||
|
const caHostname =
|
||||||
|
(store.subsUrl && startOsHostnameFromUrl(store.subsUrl)) ||
|
||||||
|
`${SPACES_PACKAGE_ID}.startos`
|
||||||
|
const certs = await sdk.getSslCertificate(effects, [caHostname]).const()
|
||||||
|
const [rootCa] = certs.slice(-1)
|
||||||
|
await mkdir(sdk.volumes.main.subpath('.startos'), { recursive: true })
|
||||||
|
await writeFile(
|
||||||
|
sdk.volumes.main.subpath(nodeExtraCaCertVolumeSubpath),
|
||||||
|
rootCa,
|
||||||
|
)
|
||||||
|
env.NODE_EXTRA_CA_CERTS = nodeExtraCaCertContainerPath
|
||||||
|
|
||||||
return sdk.Daemons.of(effects).addDaemon('spacesops', {
|
return sdk.Daemons.of(effects).addDaemon('spacesops', {
|
||||||
subcontainer: sub,
|
subcontainer: sub,
|
||||||
exec: {
|
exec: {
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ export const manifest = setupManifest({
|
|||||||
volumes: ['main'],
|
volumes: ['main'],
|
||||||
images: {
|
images: {
|
||||||
spacesops: {
|
spacesops: {
|
||||||
source: { dockerTag: 'spacesops/spacesops:v1.0.0' },
|
source: { dockerTag: 'spacesops/spacesops:v1.0.1' },
|
||||||
arch: ['x86_64', 'aarch64'],
|
arch: ['x86_64', 'aarch64'],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
+23
-2
@@ -20,13 +20,34 @@ export const SPACES_PACKAGE_ID = 'spaces'
|
|||||||
export const SPACED_RPC_URL = 'http://spaces.startos:7225'
|
export const SPACED_RPC_URL = 'http://spaces.startos:7225'
|
||||||
export const SPACED_WALLETLOAD_NAME = 'main'
|
export const SPACED_WALLETLOAD_NAME = 'main'
|
||||||
|
|
||||||
// Admin Basic Auth is baked into the v1.0.0 image with NO env override. It
|
// Admin Basic Auth is baked into the v1.0.1 image with NO env override. It
|
||||||
// cannot be changed without rebuilding the image. Surfaced (with a warning)
|
// cannot be changed without rebuilding the image. Surfaced (with a warning)
|
||||||
// via the "Show Admin Credentials" action.
|
// via the "Show Admin Credentials" action.
|
||||||
export const ADMIN_USER = 'admin'
|
export const ADMIN_USER = 'admin'
|
||||||
export const ADMIN_PASSWORD = 'Whatever!'
|
export const ADMIN_PASSWORD = 'Whatever!'
|
||||||
|
|
||||||
// Optional-config defaults (see the "Configure Platform" action).
|
// Where StartOS writes the StartOS root CA for outbound *.startos HTTPS (see
|
||||||
|
// main.ts). Always injected as NODE_EXTRA_CA_CERTS — required on v1.0.1+ where
|
||||||
|
// the image entrypoint's setup-spacesops-env.sh references _SCRIPT_DIR without
|
||||||
|
// defining it under set -u.
|
||||||
|
export const nodeExtraCaCertVolumeSubpath = '.startos/startos-root-ca.crt'
|
||||||
|
export const nodeExtraCaCertContainerPath = `${dataDir}/.startos/startos-root-ca.crt`
|
||||||
|
|
||||||
|
// Legacy aliases (same file path after rename).
|
||||||
|
export const subsCaCertVolumeSubpath = nodeExtraCaCertVolumeSubpath
|
||||||
|
export const subsCaCertContainerPath = nodeExtraCaCertContainerPath
|
||||||
|
|
||||||
|
// Returns the hostname when url targets another StartOS service on this server
|
||||||
|
// (e.g. https://spaces.startos:7777), otherwise null.
|
||||||
|
export function startOsHostnameFromUrl(url: string): string | null {
|
||||||
|
try {
|
||||||
|
const hostname = new URL(url).hostname
|
||||||
|
return hostname.endsWith('.startos') ? hostname : null
|
||||||
|
} catch {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export const DEFAULT_OPERATOR_RELAY = 'wss://relay.primal.net'
|
export const DEFAULT_OPERATOR_RELAY = 'wss://relay.primal.net'
|
||||||
export const DEFAULT_PLATFORM_MODE = 'prod'
|
export const DEFAULT_PLATFORM_MODE = 'prod'
|
||||||
export const DEFAULT_COINGECKO_TOKEN_COINS = 'bitcoin'
|
export const DEFAULT_COINGECKO_TOKEN_COINS = 'bitcoin'
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
import { VersionGraph } from '@start9labs/start-sdk'
|
import { VersionGraph } from '@start9labs/start-sdk'
|
||||||
import { v_1_0_0_0 } from './v1.0.0.0'
|
import { v_1_0_1_0 } from './v1.0.1.0'
|
||||||
|
import { v_1_0_1_1 } from './v1.0.1.1'
|
||||||
|
|
||||||
export const versionGraph = VersionGraph.of({
|
export const versionGraph = VersionGraph.of({
|
||||||
current: v_1_0_0_0,
|
current: v_1_0_1_1,
|
||||||
other: [],
|
other: [v_1_0_1_0],
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,17 +0,0 @@
|
|||||||
import { IMPOSSIBLE, VersionInfo } from '@start9labs/start-sdk'
|
|
||||||
|
|
||||||
export const v_1_0_0_0 = VersionInfo.of({
|
|
||||||
version: '1.0.0:0',
|
|
||||||
releaseNotes: {
|
|
||||||
en_US: `Initial StartOS package for SpacesOps (upstream v1.0.0).
|
|
||||||
- Runs the SpacesOps web platform (Express + SQLite) from the prebuilt spacesops/spacesops:v1.0.0 image on x86_64 and aarch64.
|
|
||||||
- Depends on the Spaces service and auto-connects to its spaced JSON-RPC at spaces.startos:7225 by reading the Spaces RPC credentials from the mounted Spaces volume.
|
|
||||||
- Generates a Nostr operator keypair and a strong session secret on first install. "Show Operator Credentials" and "Import Operator Key" actions manage the keypair.
|
|
||||||
- "Show Admin Credentials" surfaces the fixed, well-known admin login baked into the image, with a warning to keep the service private.
|
|
||||||
- "Configure Platform" optionally sets the Nostr relay, theme mode, CoinGecko pricing, and SUBS backend.`,
|
|
||||||
},
|
|
||||||
migrations: {
|
|
||||||
up: async ({ effects }) => {},
|
|
||||||
down: IMPOSSIBLE,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
import { IMPOSSIBLE, VersionInfo } from '@start9labs/start-sdk'
|
||||||
|
|
||||||
|
export const v_1_0_1_0 = VersionInfo.of({
|
||||||
|
version: '1.0.1:0',
|
||||||
|
releaseNotes: {
|
||||||
|
en_US: `Upstream upgrade to SpacesOps v1.0.1.
|
||||||
|
- Bumps the image to spacesops/spacesops:v1.0.1 on x86_64 and aarch64.
|
||||||
|
- No StartOS-side configuration, action, or migration changes; existing operator keypair, session secret, and Configure-Platform settings are preserved.`,
|
||||||
|
},
|
||||||
|
migrations: {
|
||||||
|
up: async ({ effects }) => {},
|
||||||
|
down: IMPOSSIBLE,
|
||||||
|
},
|
||||||
|
})
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
import { IMPOSSIBLE, VersionInfo } from '@start9labs/start-sdk'
|
||||||
|
|
||||||
|
export const v_1_0_1_1 = VersionInfo.of({
|
||||||
|
version: '1.0.1:1',
|
||||||
|
releaseNotes: {
|
||||||
|
en_US: `- Always sets NODE_EXTRA_CA_CERTS before the v1.0.1 image entrypoint runs, fetching the StartOS root CA via sdk.getSslCertificate (SUBS *.startos hostname when configured, otherwise spaces.startos). Fixes startup crash where setup-spacesops-env.sh references unset _SCRIPT_DIR under set -u.
|
||||||
|
- Enables outbound HTTPS to same-host StartOS services from SpacesOps.`,
|
||||||
|
},
|
||||||
|
migrations: {
|
||||||
|
up: async ({ effects }) => {},
|
||||||
|
down: IMPOSSIBLE,
|
||||||
|
},
|
||||||
|
})
|
||||||
Reference in New Issue
Block a user