Compare commits

..

15 Commits
mcp ... fix/a20

Author SHA1 Message Date
Matt Hill
1f6f3dc72d bump sdk 2026-03-06 00:22:01 -07:00
Matt Hill
59155c2e34 remove non option from smtp for better package compat 2026-03-06 00:06:18 -07:00
Matt Hill
7693b0febc multiple bugs, better outbound gateway UX 2026-03-05 23:20:13 -07:00
Matt Hill
3901d38d65 various bug, improve smtp 2026-03-05 18:28:34 -07:00
Aiden McClelland
8fdeeab5bb sdk beta.56 2026-03-05 15:12:50 -07:00
Aiden McClelland
fd1ccc0c8c fix race condition in wan ip check 2026-03-05 15:04:28 -07:00
Aiden McClelland
d31f762d5a preserve usb as top efi boot option 2026-03-05 15:04:06 -07:00
Aiden McClelland
5a0cd302de fix starttls 2026-03-05 09:44:05 -07:00
Matt Hill
e71023a3a7 better shared hostname approach, and improve look-feel of addresses tables 2026-03-04 23:24:08 -07:00
Aiden McClelland
e077b5425b fix: scope public domain to single binding and return single port check
Accept internalPort in AddPublicDomainParams to target a specific
binding. Disable the domain on all other bindings. Return a single
CheckPortRes instead of Vec. Revert multi-port UI to singular port
display from 0f8a66b35.
2026-03-04 21:43:34 -07:00
Aiden McClelland
d982ffa722 feat: add shared host note to private domain dialog with i18n 2026-03-04 17:44:30 -07:00
Aiden McClelland
4005365239 feat: inline domain health checks and improve address UX
- addPublicDomain returns DNS query + port check results (AddPublicDomainRes)
  so frontend skips separate API calls after adding a domain
- addPrivateDomain returns check_dns result for the gateway
- Support multiple ports per domain in validation modal (deduplicated)
- Run port checks concurrently via futures::future::join_all
- Add note to add-domain dialog showing other interfaces on same host
- Add addXForwardedHeaders to knownProtocols in SDK Host.ts
- Add plugin filter kind, pluginId filter, matchesAny, and docs to
  getServiceInterface.ts
- Add PassthroughInfo type and passthroughs field to NetworkInfo
- Pluralize "port forwarding rules" in i18n dictionaries
2026-03-04 17:30:00 -07:00
Aiden McClelland
0f8a66b357 passthrough feature 2026-03-04 16:32:21 -07:00
Aiden McClelland
2ed8402edd fixes for build scripts 2026-03-04 16:31:57 -07:00
Matt Hill
f7f87a4e6a task fix and keyboard fix 2026-03-04 14:02:40 -07:00
917 changed files with 7893 additions and 32768 deletions

View File

@@ -54,11 +54,11 @@ runs:
- name: Set up Python - name: Set up Python
if: inputs.setup-python == 'true' if: inputs.setup-python == 'true'
uses: actions/setup-python@v6 uses: actions/setup-python@v5
with: with:
python-version: "3.x" python-version: "3.x"
- uses: actions/setup-node@v6 - uses: actions/setup-node@v4
with: with:
node-version: ${{ inputs.nodejs-version }} node-version: ${{ inputs.nodejs-version }}
cache: npm cache: npm
@@ -66,15 +66,15 @@ runs:
- name: Set up Docker QEMU - name: Set up Docker QEMU
if: inputs.setup-docker == 'true' if: inputs.setup-docker == 'true'
uses: docker/setup-qemu-action@v4 uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx - name: Set up Docker Buildx
if: inputs.setup-docker == 'true' if: inputs.setup-docker == 'true'
uses: docker/setup-buildx-action@v4 uses: docker/setup-buildx-action@v3
- name: Configure sccache - name: Configure sccache
if: inputs.setup-sccache == 'true' if: inputs.setup-sccache == 'true'
uses: actions/github-script@v8 uses: actions/github-script@v7
with: with:
script: | script: |
core.exportVariable('ACTIONS_RESULTS_URL', process.env.ACTIONS_RESULTS_URL || ''); core.exportVariable('ACTIONS_RESULTS_URL', process.env.ACTIONS_RESULTS_URL || '');

View File

@@ -68,7 +68,7 @@ jobs:
- name: Mount tmpfs - name: Mount tmpfs
if: ${{ github.event.inputs.runner == 'fast' }} if: ${{ github.event.inputs.runner == 'fast' }}
run: sudo mount -t tmpfs tmpfs . run: sudo mount -t tmpfs tmpfs .
- uses: actions/checkout@v6 - uses: actions/checkout@v4
with: with:
submodules: recursive submodules: recursive
- uses: ./.github/actions/setup-build - uses: ./.github/actions/setup-build
@@ -82,7 +82,7 @@ jobs:
SCCACHE_GHA_ENABLED: on SCCACHE_GHA_ENABLED: on
SCCACHE_GHA_VERSION: 0 SCCACHE_GHA_VERSION: 0
- uses: actions/upload-artifact@v7 - uses: actions/upload-artifact@v4
with: with:
name: start-cli_${{ matrix.triple }} name: start-cli_${{ matrix.triple }}
path: core/target/${{ matrix.triple }}/release/start-cli path: core/target/${{ matrix.triple }}/release/start-cli

View File

@@ -64,7 +64,7 @@ jobs:
- name: Mount tmpfs - name: Mount tmpfs
if: ${{ github.event.inputs.runner == 'fast' }} if: ${{ github.event.inputs.runner == 'fast' }}
run: sudo mount -t tmpfs tmpfs . run: sudo mount -t tmpfs tmpfs .
- uses: actions/checkout@v6 - uses: actions/checkout@v4
with: with:
submodules: recursive submodules: recursive
- uses: ./.github/actions/setup-build - uses: ./.github/actions/setup-build
@@ -78,7 +78,7 @@ jobs:
SCCACHE_GHA_ENABLED: on SCCACHE_GHA_ENABLED: on
SCCACHE_GHA_VERSION: 0 SCCACHE_GHA_VERSION: 0
- uses: actions/upload-artifact@v7 - uses: actions/upload-artifact@v4
with: with:
name: start-registry_${{ matrix.arch }}.deb name: start-registry_${{ matrix.arch }}.deb
path: results/start-registry-*_${{ matrix.arch }}.deb path: results/start-registry-*_${{ matrix.arch }}.deb
@@ -102,13 +102,13 @@ jobs:
if: ${{ github.event.inputs.runner == 'fast' }} if: ${{ github.event.inputs.runner == 'fast' }}
- name: Set up docker QEMU - name: Set up docker QEMU
uses: docker/setup-qemu-action@v4 uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx - name: Set up Docker Buildx
uses: docker/setup-buildx-action@v4 uses: docker/setup-buildx-action@v3
- name: "Login to GitHub Container Registry" - name: "Login to GitHub Container Registry"
uses: docker/login-action@v4 uses: docker/login-action@v3
with: with:
registry: ghcr.io registry: ghcr.io
username: ${{github.actor}} username: ${{github.actor}}
@@ -116,14 +116,14 @@ jobs:
- name: Docker meta - name: Docker meta
id: meta id: meta
uses: docker/metadata-action@v6 uses: docker/metadata-action@v5
with: with:
images: ghcr.io/Start9Labs/startos-registry images: ghcr.io/Start9Labs/startos-registry
tags: | tags: |
type=raw,value=${{ github.ref_name }} type=raw,value=${{ github.ref_name }}
- name: Download debian package - name: Download debian package
uses: actions/download-artifact@v8 uses: actions/download-artifact@v4
with: with:
pattern: start-registry_*.deb pattern: start-registry_*.deb
@@ -162,7 +162,7 @@ jobs:
ADD *.deb . ADD *.deb .
RUN apt-get update && apt-get install -y ./*_$(uname -m).deb && rm -rf *.deb /var/lib/apt/lists/* RUN apt-get install -y ./*_$(uname -m).deb && rm *.deb
VOLUME /var/lib/startos VOLUME /var/lib/startos

View File

@@ -64,7 +64,7 @@ jobs:
- name: Mount tmpfs - name: Mount tmpfs
if: ${{ github.event.inputs.runner == 'fast' }} if: ${{ github.event.inputs.runner == 'fast' }}
run: sudo mount -t tmpfs tmpfs . run: sudo mount -t tmpfs tmpfs .
- uses: actions/checkout@v6 - uses: actions/checkout@v4
with: with:
submodules: recursive submodules: recursive
- uses: ./.github/actions/setup-build - uses: ./.github/actions/setup-build
@@ -78,7 +78,7 @@ jobs:
SCCACHE_GHA_ENABLED: on SCCACHE_GHA_ENABLED: on
SCCACHE_GHA_VERSION: 0 SCCACHE_GHA_VERSION: 0
- uses: actions/upload-artifact@v7 - uses: actions/upload-artifact@v4
with: with:
name: start-tunnel_${{ matrix.arch }}.deb name: start-tunnel_${{ matrix.arch }}.deb
path: results/start-tunnel-*_${{ matrix.arch }}.deb path: results/start-tunnel-*_${{ matrix.arch }}.deb

View File

@@ -100,7 +100,7 @@ jobs:
- name: Mount tmpfs - name: Mount tmpfs
if: ${{ github.event.inputs.runner == 'fast' }} if: ${{ github.event.inputs.runner == 'fast' }}
run: sudo mount -t tmpfs tmpfs . run: sudo mount -t tmpfs tmpfs .
- uses: actions/checkout@v6 - uses: actions/checkout@v4
with: with:
submodules: recursive submodules: recursive
- uses: ./.github/actions/setup-build - uses: ./.github/actions/setup-build
@@ -114,7 +114,7 @@ jobs:
SCCACHE_GHA_ENABLED: on SCCACHE_GHA_ENABLED: on
SCCACHE_GHA_VERSION: 0 SCCACHE_GHA_VERSION: 0
- uses: actions/upload-artifact@v7 - uses: actions/upload-artifact@v4
with: with:
name: compiled-${{ matrix.arch }}.tar name: compiled-${{ matrix.arch }}.tar
path: compiled-${{ matrix.arch }}.tar path: compiled-${{ matrix.arch }}.tar
@@ -124,13 +124,14 @@ jobs:
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
# TODO: re-add "raspberrypi" to the platform list below
platform: >- platform: >-
${{ ${{
fromJson( fromJson(
format( format(
'[ '[
["{0}"], ["{0}"],
["x86_64", "x86_64-nonfree", "x86_64-nvidia", "aarch64", "aarch64-nonfree", "aarch64-nvidia", "raspberrypi", "riscv64", "riscv64-nonfree"] ["x86_64", "x86_64-nonfree", "x86_64-nvidia", "aarch64", "aarch64-nonfree", "aarch64-nvidia", "riscv64", "riscv64-nonfree"]
]', ]',
github.event.inputs.platform || 'ALL' github.event.inputs.platform || 'ALL'
) )
@@ -208,14 +209,14 @@ jobs:
run: sudo mkdir -p /opt/hostedtoolcache && sudo chown $USER:$USER /opt/hostedtoolcache run: sudo mkdir -p /opt/hostedtoolcache && sudo chown $USER:$USER /opt/hostedtoolcache
- name: Set up docker QEMU - name: Set up docker QEMU
uses: docker/setup-qemu-action@v4 uses: docker/setup-qemu-action@v3
- uses: actions/checkout@v6 - uses: actions/checkout@v4
with: with:
submodules: recursive submodules: recursive
- name: Download compiled artifacts - name: Download compiled artifacts
uses: actions/download-artifact@v8 uses: actions/download-artifact@v4
with: with:
name: compiled-${{ env.ARCH }}.tar name: compiled-${{ env.ARCH }}.tar
@@ -252,18 +253,18 @@ jobs:
run: PLATFORM=${{ matrix.platform }} make img run: PLATFORM=${{ matrix.platform }} make img
if: ${{ matrix.platform == 'raspberrypi' }} if: ${{ matrix.platform == 'raspberrypi' }}
- uses: actions/upload-artifact@v7 - uses: actions/upload-artifact@v4
with: with:
name: ${{ matrix.platform }}.squashfs name: ${{ matrix.platform }}.squashfs
path: results/*.squashfs path: results/*.squashfs
- uses: actions/upload-artifact@v7 - uses: actions/upload-artifact@v4
with: with:
name: ${{ matrix.platform }}.iso name: ${{ matrix.platform }}.iso
path: results/*.iso path: results/*.iso
if: ${{ matrix.platform != 'raspberrypi' }} if: ${{ matrix.platform != 'raspberrypi' }}
- uses: actions/upload-artifact@v7 - uses: actions/upload-artifact@v4
with: with:
name: ${{ matrix.platform }}.img name: ${{ matrix.platform }}.img
path: results/*.img path: results/*.img

View File

@@ -24,7 +24,7 @@ jobs:
if: github.event.pull_request.draft != true if: github.event.pull_request.draft != true
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v6 - uses: actions/checkout@v4
with: with:
submodules: recursive submodules: recursive
- uses: ./.github/actions/setup-build - uses: ./.github/actions/setup-build

1
.gitignore vendored
View File

@@ -22,4 +22,3 @@ secrets.db
tmp tmp
web/.i18n-checked web/.i18n-checked
docs/USER.md docs/USER.md
*.s9pk

View File

@@ -5,10 +5,10 @@ StartOS is an open-source Linux distribution for running personal servers. It ma
## Tech Stack ## Tech Stack
- Backend: Rust (async/Tokio, Axum web framework) - Backend: Rust (async/Tokio, Axum web framework)
- Frontend: Angular 21 + TypeScript + Taiga UI 5 - Frontend: Angular 20 + TypeScript + TaigaUI
- Container runtime: Node.js/TypeScript with LXC - Container runtime: Node.js/TypeScript with LXC
- Database/State: Patch-DB (git submodule) - storage layer with reactive frontend sync - Database/State: Patch-DB (git submodule) - storage layer with reactive frontend sync
- API: JSON-RPC via rpc-toolkit (see `core/rpc-toolkit.md`), MCP for LLM agents (see `core/mcp/ARCHITECTURE.md`) - API: JSON-RPC via rpc-toolkit (see `core/rpc-toolkit.md`)
- Auth: Password + session cookie, public/private key signatures, local authcookie (see `core/src/middleware/auth/`) - Auth: Password + session cookie, public/private key signatures, local authcookie (see `core/src/middleware/auth/`)
## Project Structure ## Project Structure
@@ -28,9 +28,9 @@ StartOS is an open-source Linux distribution for running personal servers. It ma
## Components ## Components
- **`core/`** — Rust backend daemon. Produces a single binary `startbox` that is symlinked as `startd` (main daemon), `start-cli` (CLI), `start-container` (runs inside LXC containers), `registrybox` (package registry), and `tunnelbox` (VPN/tunnel). Handles all backend logic: RPC API, MCP server for LLM agents, service lifecycle, networking (DNS, ACME, WiFi, Tor, WireGuard), backups, and database state management. See [core/ARCHITECTURE.md](core/ARCHITECTURE.md). - **`core/`** — Rust backend daemon. Produces a single binary `startbox` that is symlinked as `startd` (main daemon), `start-cli` (CLI), `start-container` (runs inside LXC containers), `registrybox` (package registry), and `tunnelbox` (VPN/tunnel). Handles all backend logic: RPC API, service lifecycle, networking (DNS, ACME, WiFi, Tor, WireGuard), backups, and database state management. See [core/ARCHITECTURE.md](core/ARCHITECTURE.md).
- **`web/`** — Angular 21 + TypeScript workspace using Taiga UI 5. Contains three applications (admin UI, setup wizard, VPN management) and two shared libraries (common components/services, marketplace). Communicates with the backend exclusively via JSON-RPC. See [web/ARCHITECTURE.md](web/ARCHITECTURE.md). - **`web/`** — Angular 20 + TypeScript workspace using Taiga UI. Contains three applications (admin UI, setup wizard, VPN management) and two shared libraries (common components/services, marketplace). Communicates with the backend exclusively via JSON-RPC. See [web/ARCHITECTURE.md](web/ARCHITECTURE.md).
- **`container-runtime/`** — Node.js runtime that runs inside each service's LXC container. Loads the service's JavaScript from its S9PK package and manages subcontainers. Communicates with the host daemon via JSON-RPC over Unix socket. See [container-runtime/CLAUDE.md](container-runtime/CLAUDE.md). - **`container-runtime/`** — Node.js runtime that runs inside each service's LXC container. Loads the service's JavaScript from its S9PK package and manages subcontainers. Communicates with the host daemon via JSON-RPC over Unix socket. See [container-runtime/CLAUDE.md](container-runtime/CLAUDE.md).
@@ -53,13 +53,13 @@ Rust (core/)
Key make targets along this chain: Key make targets along this chain:
| Step | Command | What it does | | Step | Command | What it does |
| ---- | --------------------------------------- | --------------------------------- | |---|---|---|
| 1 | `cargo check -p start-os` | Verify Rust compiles | | 1 | `cargo check -p start-os` | Verify Rust compiles |
| 2 | `make ts-bindings` | Export ts-rs types → rsync to SDK | | 2 | `make ts-bindings` | Export ts-rs types → rsync to SDK |
| 3 | `cd sdk && make baseDist dist` | Build SDK packages | | 3 | `cd sdk && make baseDist dist` | Build SDK packages |
| 4 | `cd web && npm run check` | Type-check Angular projects | | 4 | `cd web && npm run check` | Type-check Angular projects |
| 5 | `cd container-runtime && npm run check` | Type-check runtime | | 5 | `cd container-runtime && npm run check` | Type-check runtime |
**Important**: Editing `sdk/base/lib/osBindings/*.ts` alone is NOT sufficient — you must rebuild the SDK bundle (step 3) before web/container-runtime can see the changes. **Important**: Editing `sdk/base/lib/osBindings/*.ts` alone is NOT sufficient — you must rebuild the SDK bundle (step 3) before web/container-runtime can see the changes.
@@ -90,17 +90,6 @@ StartOS uses Patch-DB for reactive state synchronization:
This means the UI is always eventually consistent with the backend — after any mutating API call, the frontend waits for the corresponding PatchDB diff before resolving, so the UI reflects the result immediately. This means the UI is always eventually consistent with the backend — after any mutating API call, the frontend waits for the corresponding PatchDB diff before resolving, so the UI reflects the result immediately.
## MCP Server (LLM Agent Interface)
StartOS includes an [MCP](https://modelcontextprotocol.io/) (Model Context Protocol) server at `/mcp`, enabling LLM agents to discover and invoke the same operations available through the UI and CLI. The MCP server runs inside the StartOS server process alongside the RPC API.
- **Tools**: Every RPC method is exposed as an MCP tool with LLM-optimized descriptions and JSON Schema inputs. Agents call `tools/list` to discover what's available and `tools/call` to invoke operations.
- **Resources**: System state is exposed via MCP resources backed by Patch-DB. Agents subscribe to `startos:///public` and receive debounced revision diffs over SSE, maintaining a local state cache without polling.
- **Auth**: Same session cookie auth as the UI — no separate credentials.
- **Transport**: MCP Streamable HTTP — POST for requests, GET for SSE notification stream, DELETE for session teardown.
See [core/ARCHITECTURE.md](core/ARCHITECTURE.md#mcp-server) for implementation details.
## Further Reading ## Further Reading
- [core/ARCHITECTURE.md](core/ARCHITECTURE.md) — Rust backend architecture - [core/ARCHITECTURE.md](core/ARCHITECTURE.md) — Rust backend architecture

View File

@@ -31,7 +31,6 @@ make test-core # Run Rust tests
- Check component-level CLAUDE.md files for component-specific conventions. ALWAYS read it before operating on that component. - Check component-level CLAUDE.md files for component-specific conventions. ALWAYS read it before operating on that component.
- Follow existing patterns before inventing new ones - Follow existing patterns before inventing new ones
- Always use `make` recipes when they exist for testing builds rather than manually invoking build commands - Always use `make` recipes when they exist for testing builds rather than manually invoking build commands
- **Commit signing:** Never push unsigned commits. Before pushing, check all unpushed commits for signatures with `git log --show-signature @{upstream}..HEAD`. If any are unsigned, prompt the user to sign them with `git rebase --exec 'git commit --amend -S --no-edit' @{upstream}`.
## Supplementary Documentation ## Supplementary Documentation
@@ -51,6 +50,7 @@ On startup:
1. **Check for `docs/USER.md`** - If it doesn't exist, prompt the user for their name/identifier and create it. This file is gitignored since it varies per developer. 1. **Check for `docs/USER.md`** - If it doesn't exist, prompt the user for their name/identifier and create it. This file is gitignored since it varies per developer.
2. **Check `docs/TODO.md` for relevant tasks** - Show TODOs that either: 2. **Check `docs/TODO.md` for relevant tasks** - Show TODOs that either:
- Have no `@username` tag (relevant to everyone) - Have no `@username` tag (relevant to everyone)
- Are tagged with the current user's identifier - Are tagged with the current user's identifier

View File

@@ -155,7 +155,7 @@ results/$(BASENAME).deb: debian/dpkg-build.sh $(call ls-files,debian/startos) $(
registry-deb: results/$(REGISTRY_BASENAME).deb registry-deb: results/$(REGISTRY_BASENAME).deb
results/$(REGISTRY_BASENAME).deb: debian/dpkg-build.sh $(call ls-files,debian/start-registry) $(REGISTRY_TARGETS) results/$(REGISTRY_BASENAME).deb: debian/dpkg-build.sh $(call ls-files,debian/start-registry) $(REGISTRY_TARGETS)
PROJECT=start-registry PLATFORM=$(ARCH) REQUIRES=debian DEPENDS=ca-certificates ./build/os-compat/run-compat.sh ./debian/dpkg-build.sh PROJECT=start-registry PLATFORM=$(ARCH) REQUIRES=debian ./build/os-compat/run-compat.sh ./debian/dpkg-build.sh
tunnel-deb: results/$(TUNNEL_BASENAME).deb tunnel-deb: results/$(TUNNEL_BASENAME).deb
@@ -188,9 +188,6 @@ install: $(STARTOS_TARGETS)
$(call mkdir,$(DESTDIR)/lib/systemd/system) $(call mkdir,$(DESTDIR)/lib/systemd/system)
$(call cp,core/startd.service,$(DESTDIR)/lib/systemd/system/startd.service) $(call cp,core/startd.service,$(DESTDIR)/lib/systemd/system/startd.service)
if /bin/bash -c '[[ "${ENVIRONMENT}" =~ (^|-)unstable($$|-) ]]'; then \
sed -i '/^Environment=/a Environment=RUST_BACKTRACE=full' $(DESTDIR)/lib/systemd/system/startd.service; \
fi
$(call mkdir,$(DESTDIR)/usr/lib) $(call mkdir,$(DESTDIR)/usr/lib)
$(call rm,$(DESTDIR)/usr/lib/startos) $(call rm,$(DESTDIR)/usr/lib/startos)
@@ -250,10 +247,10 @@ update-deb: results/$(BASENAME).deb # better than update, but only available fro
update-squashfs: results/$(BASENAME).squashfs update-squashfs: results/$(BASENAME).squashfs
@if [ -z "$(REMOTE)" ]; then >&2 echo "Must specify REMOTE" && false; fi @if [ -z "$(REMOTE)" ]; then >&2 echo "Must specify REMOTE" && false; fi
$(eval SQFS_SUM := $(shell b3sum results/$(BASENAME).squashfs | head -c 32)) $(eval SQFS_SUM := $(shell b3sum results/$(BASENAME).squashfs))
$(eval SQFS_SIZE := $(shell du -s --bytes results/$(BASENAME).squashfs | awk '{print $$1}')) $(eval SQFS_SIZE := $(shell du -s --bytes results/$(BASENAME).squashfs | awk '{print $$1}'))
$(call ssh,'sudo /usr/lib/startos/scripts/prune-images $(SQFS_SIZE)') $(call ssh,'/usr/lib/startos/scripts/prune-images $(SQFS_SIZE)')
$(call ssh,'sudo /usr/lib/startos/scripts/prune-boot') $(call ssh,'/usr/lib/startos/scripts/prune-boot')
$(call cp,results/$(BASENAME).squashfs,/media/startos/images/next.rootfs) $(call cp,results/$(BASENAME).squashfs,/media/startos/images/next.rootfs)
$(call ssh,'sudo CHECKSUM=$(SQFS_SUM) /usr/lib/startos/scripts/upgrade /media/startos/images/next.rootfs') $(call ssh,'sudo CHECKSUM=$(SQFS_SUM) /usr/lib/startos/scripts/upgrade /media/startos/images/next.rootfs')
@@ -286,10 +283,6 @@ core/bindings/index.ts: $(call ls-files, core) $(ENVIRONMENT_FILE)
rm -rf core/bindings rm -rf core/bindings
./core/build/build-ts.sh ./core/build/build-ts.sh
ls core/bindings/*.ts | sed 's/core\/bindings\/\([^.]*\)\.ts/export { \1 } from ".\/\1";/g' | grep -v '"./index"' | tee core/bindings/index.ts ls core/bindings/*.ts | sed 's/core\/bindings\/\([^.]*\)\.ts/export { \1 } from ".\/\1";/g' | grep -v '"./index"' | tee core/bindings/index.ts
if [ -d core/bindings/tunnel ]; then \
ls core/bindings/tunnel/*.ts | sed 's/core\/bindings\/tunnel\/\([^.]*\)\.ts/export { \1 } from ".\/\1";/g' | grep -v '"./index"' > core/bindings/tunnel/index.ts; \
echo 'export * as Tunnel from "./tunnel";' >> core/bindings/index.ts; \
fi
npm --prefix sdk/base exec -- prettier --config=./sdk/base/package.json -w './core/bindings/**/*.ts' npm --prefix sdk/base exec -- prettier --config=./sdk/base/package.json -w './core/bindings/**/*.ts'
touch core/bindings/index.ts touch core/bindings/index.ts

View File

@@ -23,7 +23,6 @@ fi
BUCKET="${S3_BUCKET:-start9-debs}" BUCKET="${S3_BUCKET:-start9-debs}"
ENDPOINT="${S3_ENDPOINT:-https://nyc3.digitaloceanspaces.com}" ENDPOINT="${S3_ENDPOINT:-https://nyc3.digitaloceanspaces.com}"
GPG_KEY_ID="${GPG_KEY_ID:-5259ADFC2D63C217}"
SUITE="${SUITE:-stable}" SUITE="${SUITE:-stable}"
COMPONENT="${COMPONENT:-main}" COMPONENT="${COMPONENT:-main}"
REPO_DIR="$(mktemp -d)" REPO_DIR="$(mktemp -d)"
@@ -99,7 +98,7 @@ for arch in amd64 arm64 riscv64; do
mkdir -p "$BINARY_DIR" mkdir -p "$BINARY_DIR"
( (
cd "$REPO_DIR" cd "$REPO_DIR"
dpkg-scanpackages --multiversion --arch "$arch" pool/ > "$BINARY_DIR/Packages" dpkg-scanpackages --arch "$arch" pool/ > "$BINARY_DIR/Packages"
gzip -k -f "$BINARY_DIR/Packages" gzip -k -f "$BINARY_DIR/Packages"
) )
echo "Generated Packages index for ${arch}" echo "Generated Packages index for ${arch}"

View File

@@ -11,7 +11,6 @@ cifs-utils
conntrack conntrack
cryptsetup cryptsetup
curl curl
dkms
dmidecode dmidecode
dnsutils dnsutils
dosfstools dosfstools
@@ -37,7 +36,6 @@ lvm2
lxc lxc
magic-wormhole magic-wormhole
man-db man-db
mokutil
ncdu ncdu
net-tools net-tools
network-manager network-manager

View File

@@ -1,6 +1,5 @@
+ gdisk - grub-efi
+ parted + parted
+ u-boot-rpi
+ raspberrypi-net-mods + raspberrypi-net-mods
+ raspberrypi-sys-mods + raspberrypi-sys-mods
+ raspi-config + raspi-config

View File

@@ -23,8 +23,6 @@ RUN apt-get update && \
squashfs-tools \ squashfs-tools \
rsync \ rsync \
b3sum \ b3sum \
btrfs-progs \
gdisk \
dpkg-dev dpkg-dev

View File

@@ -1,6 +1,7 @@
#!/bin/bash #!/bin/bash
set -e set -e
MAX_IMG_LEN=$((4 * 1024 * 1024 * 1024)) # 4GB
echo "==== StartOS Image Build ====" echo "==== StartOS Image Build ===="
@@ -131,15 +132,6 @@ ff02::1 ip6-allnodes
ff02::2 ip6-allrouters ff02::2 ip6-allrouters
EOT EOT
if [[ "${IB_OS_ENV}" =~ (^|-)dev($|-) ]]; then
mkdir -p config/includes.chroot/etc/ssh/sshd_config.d
echo "PasswordAuthentication yes" > config/includes.chroot/etc/ssh/sshd_config.d/dev-password-auth.conf
fi
# Installer marker file (used by installed GRUB to detect the live USB)
mkdir -p config/includes.binary
touch config/includes.binary/.startos-installer
if [ "${IB_TARGET_PLATFORM}" = "raspberrypi" ]; then if [ "${IB_TARGET_PLATFORM}" = "raspberrypi" ]; then
mkdir -p config/includes.chroot mkdir -p config/includes.chroot
git clone --depth=1 --branch=stable https://github.com/raspberrypi/rpi-firmware.git config/includes.chroot/boot git clone --depth=1 --branch=stable https://github.com/raspberrypi/rpi-firmware.git config/includes.chroot/boot
@@ -180,13 +172,7 @@ sed -i -e '2i set timeout=5' config/bootloaders/grub-pc/config.cfg
mkdir -p config/archives mkdir -p config/archives
if [ "${IB_TARGET_PLATFORM}" = "raspberrypi" ]; then if [ "${IB_TARGET_PLATFORM}" = "raspberrypi" ]; then
# Fetch the keyring package (not the old raspberrypi.gpg.key, which has curl -fsSL https://archive.raspberrypi.com/debian/raspberrypi.gpg.key | gpg --dearmor -o config/archives/raspi.key
# SHA1-only binding signatures that sqv on Trixie rejects).
KEYRING_DEB=$(mktemp)
curl -fsSL -o "$KEYRING_DEB" https://archive.raspberrypi.com/debian/pool/main/r/raspberrypi-archive-keyring/raspberrypi-archive-keyring_2025.1+rpt1_all.deb
dpkg-deb -x "$KEYRING_DEB" "$KEYRING_DEB.d"
cp "$KEYRING_DEB.d/usr/share/keyrings/raspberrypi-archive-keyring.gpg" config/archives/raspi.key
rm -rf "$KEYRING_DEB" "$KEYRING_DEB.d"
echo "deb [arch=${IB_TARGET_ARCH} signed-by=/etc/apt/trusted.gpg.d/raspi.key.gpg] https://archive.raspberrypi.com/debian/ ${IB_SUITE} main" > config/archives/raspi.list echo "deb [arch=${IB_TARGET_ARCH} signed-by=/etc/apt/trusted.gpg.d/raspi.key.gpg] https://archive.raspberrypi.com/debian/ ${IB_SUITE} main" > config/archives/raspi.list
fi fi
@@ -223,10 +209,6 @@ cat > config/hooks/normal/9000-install-startos.hook.chroot << EOF
set -e set -e
if [ "${IB_TARGET_PLATFORM}" != "raspberrypi" ]; then
/usr/lib/startos/scripts/enable-kiosk
fi
if [ "${NVIDIA}" = "1" ]; then if [ "${NVIDIA}" = "1" ]; then
# install a specific NVIDIA driver version # install a specific NVIDIA driver version
@@ -254,7 +236,7 @@ if [ "${NVIDIA}" = "1" ]; then
echo "[nvidia-hook] Target kernel version: \${KVER}" >&2 echo "[nvidia-hook] Target kernel version: \${KVER}" >&2
# Ensure kernel headers are present # Ensure kernel headers are present
TEMP_APT_DEPS=(build-essential pkg-config) TEMP_APT_DEPS=(build-essential)
if [ ! -e "/lib/modules/\${KVER}/build" ]; then if [ ! -e "/lib/modules/\${KVER}/build" ]; then
TEMP_APT_DEPS+=(linux-headers-\${KVER}) TEMP_APT_DEPS+=(linux-headers-\${KVER})
fi fi
@@ -297,32 +279,12 @@ if [ "${NVIDIA}" = "1" ]; then
echo "[nvidia-hook] NVIDIA \${NVIDIA_DRIVER_VERSION} installation complete for kernel \${KVER}" >&2 echo "[nvidia-hook] NVIDIA \${NVIDIA_DRIVER_VERSION} installation complete for kernel \${KVER}" >&2
echo "[nvidia-hook] Removing .run installer..." >&2
rm -f "\${RUN_PATH}"
echo "[nvidia-hook] Blacklisting nouveau..." >&2
echo "blacklist nouveau" > /etc/modprobe.d/blacklist-nouveau.conf
echo "options nouveau modeset=0" >> /etc/modprobe.d/blacklist-nouveau.conf
echo "[nvidia-hook] Rebuilding initramfs..." >&2
update-initramfs -u -k "\${KVER}"
echo "[nvidia-hook] Removing build dependencies..." >&2 echo "[nvidia-hook] Removing build dependencies..." >&2
apt-get purge -y nvidia-depends apt-get purge -y nvidia-depends
apt-get autoremove -y apt-get autoremove -y
echo "[nvidia-hook] Removed build dependencies." >&2 echo "[nvidia-hook] Removed build dependencies." >&2
fi fi
# Install linux-kbuild for sign-file (Secure Boot module signing)
KVER_ALL="\$(ls -1t /boot/vmlinuz-* 2>/dev/null | head -n1 | sed 's|.*/vmlinuz-||')"
if [ -n "\${KVER_ALL}" ]; then
KBUILD_VER="\$(echo "\${KVER_ALL}" | grep -oP '^\d+\.\d+')"
if [ -n "\${KBUILD_VER}" ]; then
echo "[build] Installing linux-kbuild-\${KBUILD_VER} for Secure Boot support" >&2
apt-get install -y "linux-kbuild-\${KBUILD_VER}" || echo "[build] WARNING: linux-kbuild-\${KBUILD_VER} not available" >&2
fi
fi
cp /etc/resolv.conf /etc/resolv.conf.bak cp /etc/resolv.conf /etc/resolv.conf.bak
if [ "${IB_SUITE}" = trixie ] && [ "${IB_TARGET_ARCH}" != riscv64 ]; then if [ "${IB_SUITE}" = trixie ] && [ "${IB_TARGET_ARCH}" != riscv64 ]; then
@@ -336,10 +298,9 @@ fi
if [ "${IB_TARGET_PLATFORM}" = "raspberrypi" ]; then if [ "${IB_TARGET_PLATFORM}" = "raspberrypi" ]; then
ln -sf /usr/bin/pi-beep /usr/local/bin/beep ln -sf /usr/bin/pi-beep /usr/local/bin/beep
sh /boot/firmware/config.sh > /boot/firmware/config.txt KERNEL_VERSION=${RPI_KERNEL_VERSION} sh /boot/config.sh > /boot/config.txt
mkinitramfs -c gzip -o /boot/initrd.img-${RPI_KERNEL_VERSION}-rpi-v8 ${RPI_KERNEL_VERSION}-rpi-v8 mkinitramfs -c gzip -o /boot/initrd.img-${RPI_KERNEL_VERSION}-rpi-v8 ${RPI_KERNEL_VERSION}-rpi-v8
mkinitramfs -c gzip -o /boot/initrd.img-${RPI_KERNEL_VERSION}-rpi-2712 ${RPI_KERNEL_VERSION}-rpi-2712 mkinitramfs -c gzip -o /boot/initrd.img-${RPI_KERNEL_VERSION}-rpi-2712 ${RPI_KERNEL_VERSION}-rpi-2712
cp /usr/lib/u-boot/rpi_arm64/u-boot.bin /boot/firmware/u-boot.bin
fi fi
useradd --shell /bin/bash -G startos -m start9 useradd --shell /bin/bash -G startos -m start9
@@ -349,16 +310,14 @@ usermod -aG systemd-journal start9
echo "start9 ALL=(ALL:ALL) NOPASSWD: ALL" | sudo tee "/etc/sudoers.d/010_start9-nopasswd" echo "start9 ALL=(ALL:ALL) NOPASSWD: ALL" | sudo tee "/etc/sudoers.d/010_start9-nopasswd"
if [ "${IB_TARGET_PLATFORM}" != "raspberrypi" ]; then
/usr/lib/startos/scripts/enable-kiosk
fi
if ! [[ "${IB_OS_ENV}" =~ (^|-)dev($|-) ]]; then if ! [[ "${IB_OS_ENV}" =~ (^|-)dev($|-) ]]; then
passwd -l start9 passwd -l start9
fi fi
mkdir -p /media/startos
chmod 750 /media/startos
chown root:startos /media/startos
start-cli --registry=https://alpha-registry-x.start9.com registry package download tor -d /usr/lib/startos/tor_${QEMU_ARCH}.s9pk -a "${QEMU_ARCH}"
EOF EOF
SOURCE_DATE_EPOCH="${SOURCE_DATE_EPOCH:-$(date '+%s')}" SOURCE_DATE_EPOCH="${SOURCE_DATE_EPOCH:-$(date '+%s')}"
@@ -411,85 +370,38 @@ if [ "${IMAGE_TYPE}" = iso ]; then
elif [ "${IMAGE_TYPE}" = img ]; then elif [ "${IMAGE_TYPE}" = img ]; then
SECTOR_LEN=512 SECTOR_LEN=512
FW_START=$((1024 * 1024)) # 1MiB (sector 2048) — Pi-specific BOOT_START=$((1024 * 1024)) # 1MiB
FW_LEN=$((128 * 1024 * 1024)) # 128MiB (Pi firmware + U-Boot + DTBs) BOOT_LEN=$((512 * 1024 * 1024)) # 512MiB
FW_END=$((FW_START + FW_LEN - 1))
ESP_START=$((FW_END + 1)) # 100MB EFI System Partition (matches os_install)
ESP_LEN=$((100 * 1024 * 1024))
ESP_END=$((ESP_START + ESP_LEN - 1))
BOOT_START=$((ESP_END + 1)) # 2GB /boot (matches os_install)
BOOT_LEN=$((2 * 1024 * 1024 * 1024))
BOOT_END=$((BOOT_START + BOOT_LEN - 1)) BOOT_END=$((BOOT_START + BOOT_LEN - 1))
ROOT_START=$((BOOT_END + 1)) ROOT_START=$((BOOT_END + 1))
ROOT_LEN=$((MAX_IMG_LEN - ROOT_START))
# Size root partition to fit the squashfs + 256MB overhead for btrfs ROOT_END=$((MAX_IMG_LEN - 1))
# metadata and config overlay, avoiding the need for btrfs resize
SQUASHFS_SIZE=$(stat -c %s $prep_results_dir/binary/live/filesystem.squashfs)
ROOT_LEN=$(( SQUASHFS_SIZE + 256 * 1024 * 1024 ))
# Align to sector boundary
ROOT_LEN=$(( (ROOT_LEN + SECTOR_LEN - 1) / SECTOR_LEN * SECTOR_LEN ))
# Total image: partitions + GPT backup header (34 sectors)
IMG_LEN=$((ROOT_START + ROOT_LEN + 34 * SECTOR_LEN))
# Fixed GPT partition UUIDs (deterministic, based on old MBR disk ID cb15ae4d)
FW_UUID=cb15ae4d-0001-4000-8000-000000000001
ESP_UUID=cb15ae4d-0002-4000-8000-000000000002
BOOT_UUID=cb15ae4d-0003-4000-8000-000000000003
ROOT_UUID=cb15ae4d-0004-4000-8000-000000000004
TARGET_NAME=$prep_results_dir/${IMAGE_BASENAME}.img TARGET_NAME=$prep_results_dir/${IMAGE_BASENAME}.img
truncate -s $IMG_LEN $TARGET_NAME truncate -s $MAX_IMG_LEN $TARGET_NAME
sfdisk $TARGET_NAME <<-EOF sfdisk $TARGET_NAME <<-EOF
label: gpt label: dos
label-id: 0xcb15ae4d
unit: sectors
sector-size: 512
${TARGET_NAME}1 : start=$((FW_START / SECTOR_LEN)), size=$((FW_LEN / SECTOR_LEN)), type=EBD0A0A2-B9E5-4433-87C0-68B6B72699C7, uuid=${FW_UUID}, name="firmware" ${TARGET_NAME}1 : start=$((BOOT_START / SECTOR_LEN)), size=$((BOOT_LEN / SECTOR_LEN)), type=c, bootable
${TARGET_NAME}2 : start=$((ESP_START / SECTOR_LEN)), size=$((ESP_LEN / SECTOR_LEN)), type=C12A7328-F81F-11D2-BA4B-00A0C93EC93B, uuid=${ESP_UUID}, name="efi" ${TARGET_NAME}2 : start=$((ROOT_START / SECTOR_LEN)), size=$((ROOT_LEN / SECTOR_LEN)), type=83
${TARGET_NAME}3 : start=$((BOOT_START / SECTOR_LEN)), size=$((BOOT_LEN / SECTOR_LEN)), type=0FC63DAF-8483-4772-8E79-3D69D8477DE4, uuid=${BOOT_UUID}, name="boot"
${TARGET_NAME}4 : start=$((ROOT_START / SECTOR_LEN)), size=$((ROOT_LEN / SECTOR_LEN)), type=B921B045-1DF0-41C3-AF44-4C6F280D3FAE, uuid=${ROOT_UUID}, name="root"
EOF EOF
# Create named loop device nodes (high minor numbers to avoid conflicts) BOOT_DEV=$(losetup --show -f --offset $BOOT_START --sizelimit $BOOT_LEN $TARGET_NAME)
# and detach any stale ones from previous failed builds ROOT_DEV=$(losetup --show -f --offset $ROOT_START --sizelimit $ROOT_LEN $TARGET_NAME)
FW_DEV=/dev/startos-loop-fw
ESP_DEV=/dev/startos-loop-esp
BOOT_DEV=/dev/startos-loop-boot
ROOT_DEV=/dev/startos-loop-root
for dev in $FW_DEV:200 $ESP_DEV:201 $BOOT_DEV:202 $ROOT_DEV:203; do
name=${dev%:*}
minor=${dev#*:}
[ -e $name ] || mknod $name b 7 $minor
losetup -d $name 2>/dev/null || true
done
losetup $FW_DEV --offset $FW_START --sizelimit $FW_LEN $TARGET_NAME mkfs.vfat -F32 $BOOT_DEV
losetup $ESP_DEV --offset $ESP_START --sizelimit $ESP_LEN $TARGET_NAME mkfs.ext4 $ROOT_DEV
losetup $BOOT_DEV --offset $BOOT_START --sizelimit $BOOT_LEN $TARGET_NAME
losetup $ROOT_DEV --offset $ROOT_START --sizelimit $ROOT_LEN $TARGET_NAME
mkfs.vfat -F32 -n firmware $FW_DEV
mkfs.vfat -F32 -n efi $ESP_DEV
mkfs.vfat -F32 -n boot $BOOT_DEV
mkfs.btrfs -f -L rootfs $ROOT_DEV
TMPDIR=$(mktemp -d) TMPDIR=$(mktemp -d)
# Extract boot files from squashfs to staging area
BOOT_STAGING=$(mktemp -d)
unsquashfs -n -f -d $BOOT_STAGING $prep_results_dir/binary/live/filesystem.squashfs boot
# Mount partitions (nested: firmware and efi inside boot)
mkdir -p $TMPDIR/boot $TMPDIR/root mkdir -p $TMPDIR/boot $TMPDIR/root
mount $BOOT_DEV $TMPDIR/boot
mkdir -p $TMPDIR/boot/firmware $TMPDIR/boot/efi
mount $FW_DEV $TMPDIR/boot/firmware
mount $ESP_DEV $TMPDIR/boot/efi
mount $ROOT_DEV $TMPDIR/root mount $ROOT_DEV $TMPDIR/root
mount $BOOT_DEV $TMPDIR/boot
# Copy boot files — nested mounts route firmware/* to the firmware partition unsquashfs -n -f -d $TMPDIR $prep_results_dir/binary/live/filesystem.squashfs boot
cp -a $BOOT_STAGING/boot/. $TMPDIR/boot/
rm -rf $BOOT_STAGING
mkdir $TMPDIR/root/images $TMPDIR/root/config mkdir $TMPDIR/root/images $TMPDIR/root/config
B3SUM=$(b3sum $prep_results_dir/binary/live/filesystem.squashfs | head -c 16) B3SUM=$(b3sum $prep_results_dir/binary/live/filesystem.squashfs | head -c 16)
@@ -502,46 +414,40 @@ elif [ "${IMAGE_TYPE}" = img ]; then
mount -t overlay -o lowerdir=$TMPDIR/lower,workdir=$TMPDIR/root/config/work,upperdir=$TMPDIR/root/config/overlay overlay $TMPDIR/next mount -t overlay -o lowerdir=$TMPDIR/lower,workdir=$TMPDIR/root/config/work,upperdir=$TMPDIR/root/config/overlay overlay $TMPDIR/next
if [ "${IB_TARGET_PLATFORM}" = "raspberrypi" ]; then if [ "${IB_TARGET_PLATFORM}" = "raspberrypi" ]; then
sed -i 's| boot=startos| boot=startos init=/usr/lib/startos/scripts/init_resize\.sh|' $TMPDIR/boot/cmdline.txt
rsync -a $SOURCE_DIR/raspberrypi/img/ $TMPDIR/next/ rsync -a $SOURCE_DIR/raspberrypi/img/ $TMPDIR/next/
# Install GRUB: ESP at /boot/efi (Part 2), /boot (Part 3)
mkdir -p $TMPDIR/next/boot \
$TMPDIR/next/dev $TMPDIR/next/proc $TMPDIR/next/sys $TMPDIR/next/media/startos/root
mount --rbind $TMPDIR/boot $TMPDIR/next/boot
mount --bind /dev $TMPDIR/next/dev
mount -t proc proc $TMPDIR/next/proc
mount -t sysfs sysfs $TMPDIR/next/sys
mount --bind $TMPDIR/root $TMPDIR/next/media/startos/root
chroot $TMPDIR/next grub-install --target=arm64-efi --removable --efi-directory=/boot/efi --boot-directory=/boot --no-nvram
chroot $TMPDIR/next update-grub
umount $TMPDIR/next/media/startos/root
umount $TMPDIR/next/sys
umount $TMPDIR/next/proc
umount $TMPDIR/next/dev
umount -l $TMPDIR/next/boot
# Fix root= in grub.cfg: update-grub sees loop devices, but the
# real device uses a fixed GPT PARTUUID for root (Part 4).
sed -i "s|root=[^ ]*|root=PARTUUID=${ROOT_UUID}|g" $TMPDIR/boot/grub/grub.cfg
# Inject first-boot resize script into GRUB config
sed -i 's| boot=startos| boot=startos init=/usr/lib/startos/scripts/init_resize\.sh|' $TMPDIR/boot/grub/grub.cfg
fi fi
umount $TMPDIR/next umount $TMPDIR/next
umount $TMPDIR/lower umount $TMPDIR/lower
umount $TMPDIR/boot/firmware
umount $TMPDIR/boot/efi
umount $TMPDIR/boot umount $TMPDIR/boot
umount $TMPDIR/root umount $TMPDIR/root
e2fsck -fy $ROOT_DEV
resize2fs -M $ROOT_DEV
BLOCK_COUNT=$(dumpe2fs -h $ROOT_DEV | awk '/^Block count:/ { print $3 }')
BLOCK_SIZE=$(dumpe2fs -h $ROOT_DEV | awk '/^Block size:/ { print $3 }')
ROOT_LEN=$((BLOCK_COUNT * BLOCK_SIZE))
losetup -d $ROOT_DEV losetup -d $ROOT_DEV
losetup -d $BOOT_DEV losetup -d $BOOT_DEV
losetup -d $ESP_DEV
losetup -d $FW_DEV # Recreate partition 2 with the new size using sfdisk
sfdisk $TARGET_NAME <<-EOF
label: dos
label-id: 0xcb15ae4d
unit: sectors
sector-size: 512
${TARGET_NAME}1 : start=$((BOOT_START / SECTOR_LEN)), size=$((BOOT_LEN / SECTOR_LEN)), type=c, bootable
${TARGET_NAME}2 : start=$((ROOT_START / SECTOR_LEN)), size=$((ROOT_LEN / SECTOR_LEN)), type=83
EOF
TARGET_SIZE=$((ROOT_START + ROOT_LEN))
truncate -s $TARGET_SIZE $TARGET_NAME
mv $TARGET_NAME $RESULTS_DIR/$IMAGE_BASENAME.img mv $TARGET_NAME $RESULTS_DIR/$IMAGE_BASENAME.img

View File

@@ -1,4 +1,2 @@
PARTUUID=cb15ae4d-0001-4000-8000-000000000001 /boot/firmware vfat umask=0077 0 2 /dev/mmcblk0p1 /boot vfat umask=0077 0 2
PARTUUID=cb15ae4d-0002-4000-8000-000000000002 /boot/efi vfat umask=0077 0 1 /dev/mmcblk0p2 / ext4 defaults 0 1
PARTUUID=cb15ae4d-0003-4000-8000-000000000003 /boot vfat umask=0077 0 2
PARTUUID=cb15ae4d-0004-4000-8000-000000000004 / btrfs defaults 0 1

View File

@@ -12,16 +12,15 @@ get_variables () {
BOOT_DEV_NAME=$(echo /sys/block/*/"${BOOT_PART_NAME}" | cut -d "/" -f 4) BOOT_DEV_NAME=$(echo /sys/block/*/"${BOOT_PART_NAME}" | cut -d "/" -f 4)
BOOT_PART_NUM=$(cat "/sys/block/${BOOT_DEV_NAME}/${BOOT_PART_NAME}/partition") BOOT_PART_NUM=$(cat "/sys/block/${BOOT_DEV_NAME}/${BOOT_PART_NAME}/partition")
ROOT_DEV_SIZE=$(cat "/sys/block/${ROOT_DEV_NAME}/size") OLD_DISKID=$(fdisk -l "$ROOT_DEV" | sed -n 's/Disk identifier: 0x\([^ ]*\)/\1/p')
# GPT backup header/entries occupy last 33 sectors
USABLE_END=$((ROOT_DEV_SIZE - 34))
if [ "$USABLE_END" -le 67108864 ]; then ROOT_DEV_SIZE=$(cat "/sys/block/${ROOT_DEV_NAME}/size")
TARGET_END=$USABLE_END if [ "$ROOT_DEV_SIZE" -le 67108864 ]; then
TARGET_END=$((ROOT_DEV_SIZE - 1))
else else
TARGET_END=$((33554432 - 1)) TARGET_END=$((33554432 - 1))
DATA_PART_START=33554432 DATA_PART_START=33554432
DATA_PART_END=$USABLE_END DATA_PART_END=$((ROOT_DEV_SIZE - 1))
fi fi
PARTITION_TABLE=$(parted -m "$ROOT_DEV" unit s print | tr -d 's') PARTITION_TABLE=$(parted -m "$ROOT_DEV" unit s print | tr -d 's')
@@ -58,30 +57,37 @@ check_variables () {
main () { main () {
get_variables get_variables
# Fix GPT backup header first — the image was built with a tight root
# partition, so the backup GPT is not at the end of the SD card. parted
# will prompt interactively if this isn't fixed before we use it.
sgdisk -e "$ROOT_DEV" 2>/dev/null || true
if ! check_variables; then if ! check_variables; then
return 1 return 1
fi fi
# if [ "$ROOT_PART_END" -eq "$TARGET_END" ]; then
# reboot_pi
# fi
if ! echo Yes | parted -m --align=optimal "$ROOT_DEV" ---pretend-input-tty u s resizepart "$ROOT_PART_NUM" "$TARGET_END" ; then if ! echo Yes | parted -m --align=optimal "$ROOT_DEV" ---pretend-input-tty u s resizepart "$ROOT_PART_NUM" "$TARGET_END" ; then
FAIL_REASON="Root partition resize failed" FAIL_REASON="Root partition resize failed"
return 1 return 1
fi fi
if [ -n "$DATA_PART_START" ]; then if [ -n "$DATA_PART_START" ]; then
if ! parted -ms --align=optimal "$ROOT_DEV" u s mkpart data "$DATA_PART_START" "$DATA_PART_END"; then if ! parted -ms --align=optimal "$ROOT_DEV" u s mkpart primary "$DATA_PART_START" "$DATA_PART_END"; then
FAIL_REASON="Data partition creation failed" FAIL_REASON="Data partition creation failed"
return 1 return 1
fi fi
fi fi
(
echo x
echo i
echo "0xcb15ae4d"
echo r
echo w
) | fdisk $ROOT_DEV
mount / -o remount,rw mount / -o remount,rw
btrfs filesystem resize max /media/startos/root resize2fs $ROOT_PART_DEV
if ! systemd-machine-id-setup --root=/media/startos/config/overlay/; then if ! systemd-machine-id-setup --root=/media/startos/config/overlay/; then
FAIL_REASON="systemd-machine-id-setup failed" FAIL_REASON="systemd-machine-id-setup failed"
@@ -105,7 +111,7 @@ mount / -o remount,ro
beep beep
if main; then if main; then
sed -i 's| init=/usr/lib/startos/scripts/init_resize\.sh||' /boot/grub/grub.cfg sed -i 's| init=/usr/lib/startos/scripts/init_resize\.sh||' /boot/cmdline.txt
echo "Resized root filesystem. Rebooting in 5 seconds..." echo "Resized root filesystem. Rebooting in 5 seconds..."
sleep 5 sleep 5
else else

View File

@@ -0,0 +1 @@
usb-storage.quirks=152d:0562:u,14cd:121c:u,0781:cfcb:u console=serial0,115200 console=tty1 root=PARTUUID=cb15ae4d-02 rootfstype=ext4 fsck.repair=yes rootwait cgroup_enable=cpuset cgroup_memory=1 cgroup_enable=memory boot=startos

View File

@@ -27,18 +27,20 @@ disable_overscan=1
# (e.g. for USB device mode) or if USB support is not required. # (e.g. for USB device mode) or if USB support is not required.
otg_mode=1 otg_mode=1
[all]
[pi4] [pi4]
# Run as fast as firmware / board allows # Run as fast as firmware / board allows
arm_boost=1 arm_boost=1
kernel=vmlinuz-${KERNEL_VERSION}-rpi-v8
initramfs initrd.img-${KERNEL_VERSION}-rpi-v8 followkernel
[pi5]
kernel=vmlinuz-${KERNEL_VERSION}-rpi-2712
initramfs initrd.img-${KERNEL_VERSION}-rpi-2712 followkernel
[all] [all]
gpu_mem=16 gpu_mem=16
dtoverlay=pwm-2chan,disable-bt dtoverlay=pwm-2chan,disable-bt
# Enable UART for U-Boot and serial console EOF
enable_uart=1
# Load U-Boot as the bootloader (GRUB is chainloaded from U-Boot)
kernel=u-boot.bin
EOF

View File

@@ -84,8 +84,4 @@ arm_boost=1
gpu_mem=16 gpu_mem=16
dtoverlay=pwm-2chan,disable-bt dtoverlay=pwm-2chan,disable-bt
# Enable UART for U-Boot and serial console auto_initramfs=1
enable_uart=1
# Load U-Boot as the bootloader (GRUB is chainloaded from U-Boot)
kernel=u-boot.bin

View File

@@ -1,4 +0,0 @@
# Raspberry Pi-specific GRUB overrides
# Overrides GRUB_CMDLINE_LINUX from /etc/default/grub with Pi-specific
# console devices and hardware quirks.
GRUB_CMDLINE_LINUX="boot=startos console=serial0,115200 console=tty1 usb-storage.quirks=152d:0562:u,14cd:121c:u,0781:cfcb:u cgroup_enable=cpuset cgroup_memory=1 cgroup_enable=memory"

View File

@@ -1,3 +1,6 @@
os-partitions:
boot: /dev/mmcblk0p1
root: /dev/mmcblk0p2
ethernet-interface: end0 ethernet-interface: end0
wifi-interface: wlan0 wifi-interface: wlan0
disable-encryption: true disable-encryption: true

View File

@@ -118,6 +118,6 @@ else
fi fi
printf "\n \033[1;37m┌──────────────────────────────────────────────────── QUICK ACCESS ─┐\033[0m\n" printf "\n \033[1;37m┌──────────────────────────────────────────────────── QUICK ACCESS ─┐\033[0m\n"
printf " \033[1;37m│\033[0m Web Interface: \033[0;36m%-50s\033[0m \033[1;37m│\033[0m\n" "$web_url" printf " \033[1;37m│\033[0m Web Interface: \033[0;36m%-50s\033[0m \033[1;37m│\033[0m\n" "$web_url"
printf " \033[1;37m│\033[0m Documentation: \033[0;36m%-50s\033[0m \033[1;37m│\033[0m\n" "https://docs.start9.com" printf " \033[1;37m│\033[0m Documentation: \033[0;36m%-50s\033[0m \033[1;37m│\033[0m\n" "https://staging.docs.start9.com"
printf " \033[1;37m│\033[0m Support: \033[0;36m%-50s\033[0m \033[1;37m│\033[0m\n" "https://start9.com/contact" printf " \033[1;37m│\033[0m Support: \033[0;36m%-50s\033[0m \033[1;37m│\033[0m\n" "https://start9.com/contact"
printf " \033[1;37m└───────────────────────────────────────────────────────────────────┘\033[0m\n\n" printf " \033[1;37m└───────────────────────────────────────────────────────────────────┘\033[0m\n\n"

View File

@@ -34,7 +34,7 @@ set -- "${POSITIONAL_ARGS[@]}" # restore positional parameters
if [ -z "$NO_SYNC" ]; then if [ -z "$NO_SYNC" ]; then
echo 'Syncing...' echo 'Syncing...'
umount -l /media/startos/next 2> /dev/null umount -R /media/startos/next 2> /dev/null
umount /media/startos/upper 2> /dev/null umount /media/startos/upper 2> /dev/null
rm -rf /media/startos/upper /media/startos/next rm -rf /media/startos/upper /media/startos/next
mkdir /media/startos/upper mkdir /media/startos/upper
@@ -55,16 +55,16 @@ mkdir -p /media/startos/next/sys
mkdir -p /media/startos/next/proc mkdir -p /media/startos/next/proc
mkdir -p /media/startos/next/boot mkdir -p /media/startos/next/boot
mkdir -p /media/startos/next/media/startos/root mkdir -p /media/startos/next/media/startos/root
mount -t tmpfs tmpfs /media/startos/next/run mount --bind /run /media/startos/next/run
mount -t tmpfs tmpfs /media/startos/next/tmp mount --bind /tmp /media/startos/next/tmp
mount --bind /dev /media/startos/next/dev mount --bind /dev /media/startos/next/dev
mount -t sysfs sysfs /media/startos/next/sys mount --bind /sys /media/startos/next/sys
mount -t proc proc /media/startos/next/proc mount --bind /proc /media/startos/next/proc
mount --bind /boot /media/startos/next/boot mount --bind /boot /media/startos/next/boot
mount --bind /media/startos/root /media/startos/next/media/startos/root mount --bind /media/startos/root /media/startos/next/media/startos/root
if mountpoint /sys/firmware/efi/efivars 2>&1 > /dev/null; then if mountpoint /sys/firmware/efi/efivars 2>&1 > /dev/null; then
mount -t efivarfs efivarfs /media/startos/next/sys/firmware/efi/efivars mount --bind /sys/firmware/efi/efivars /media/startos/next/sys/firmware/efi/efivars
fi fi
if [ -z "$*" ]; then if [ -z "$*" ]; then
@@ -79,13 +79,13 @@ if mountpoint /media/startos/next/sys/firmware/efi/efivars 2>&1 > /dev/null; the
umount /media/startos/next/sys/firmware/efi/efivars umount /media/startos/next/sys/firmware/efi/efivars
fi fi
umount -l /media/startos/next/run umount /media/startos/next/run
umount -l /media/startos/next/tmp umount /media/startos/next/tmp
umount -l /media/startos/next/dev umount /media/startos/next/dev
umount -l /media/startos/next/sys umount /media/startos/next/sys
umount -l /media/startos/next/proc umount /media/startos/next/proc
umount -l /media/startos/next/boot umount /media/startos/next/boot
umount -l /media/startos/next/media/startos/root umount /media/startos/next/media/startos/root
if [ "$CHROOT_RES" -eq 0 ]; then if [ "$CHROOT_RES" -eq 0 ]; then
@@ -111,6 +111,6 @@ if [ "$CHROOT_RES" -eq 0 ]; then
reboot reboot
fi fi
umount -l /media/startos/next umount /media/startos/next
umount -l /media/startos/upper umount /media/startos/upper
rm -rf /media/startos/upper /media/startos/next rm -rf /media/startos/upper /media/startos/next

View File

@@ -1,76 +0,0 @@
#!/bin/bash
# sign-unsigned-modules [--source <dir> --dest <dir>] [--sign-file <path>]
# [--mok-key <path>] [--mok-pub <path>]
#
# Signs all unsigned kernel modules using the DKMS MOK key.
#
# Default (install) mode:
# Run inside a chroot. Finds and signs unsigned modules in /lib/modules in-place.
# sign-file and MOK key are auto-detected from standard paths.
#
# Overlay mode (--source/--dest):
# Finds unsigned modules in <source>, copies to <dest>, signs the copies.
# Clears old signed modules in <dest> first. Used during upgrades where the
# overlay upper is tmpfs and writes would be lost.
set -e
SOURCE=""
DEST=""
SIGN_FILE=""
MOK_KEY="/var/lib/dkms/mok.key"
MOK_PUB="/var/lib/dkms/mok.pub"
while [[ $# -gt 0 ]]; do
case $1 in
--source) SOURCE="$2"; shift 2;;
--dest) DEST="$2"; shift 2;;
--sign-file) SIGN_FILE="$2"; shift 2;;
--mok-key) MOK_KEY="$2"; shift 2;;
--mok-pub) MOK_PUB="$2"; shift 2;;
*) echo "Unknown option: $1" >&2; exit 1;;
esac
done
# Auto-detect sign-file if not specified
if [ -z "$SIGN_FILE" ]; then
SIGN_FILE="$(ls -1 /usr/lib/linux-kbuild-*/scripts/sign-file 2>/dev/null | head -1)"
fi
if [ -z "$SIGN_FILE" ] || [ ! -x "$SIGN_FILE" ]; then
exit 0
fi
if [ ! -f "$MOK_KEY" ] || [ ! -f "$MOK_PUB" ]; then
exit 0
fi
COUNT=0
if [ -n "$SOURCE" ] && [ -n "$DEST" ]; then
# Overlay mode: find unsigned in source, copy to dest, sign in dest
rm -rf "${DEST}"/lib/modules
for ko in $(find "${SOURCE}"/lib/modules -name '*.ko' 2>/dev/null); do
if ! modinfo "$ko" 2>/dev/null | grep -q '^sig_id:'; then
rel_path="${ko#${SOURCE}}"
mkdir -p "${DEST}$(dirname "$rel_path")"
cp "$ko" "${DEST}${rel_path}"
"$SIGN_FILE" sha256 "$MOK_KEY" "$MOK_PUB" "${DEST}${rel_path}"
COUNT=$((COUNT + 1))
fi
done
else
# In-place mode: sign modules directly
for ko in $(find /lib/modules -name '*.ko' 2>/dev/null); do
if ! modinfo "$ko" 2>/dev/null | grep -q '^sig_id:'; then
"$SIGN_FILE" sha256 "$MOK_KEY" "$MOK_PUB" "$ko"
COUNT=$((COUNT + 1))
fi
done
fi
if [ $COUNT -gt 0 ]; then
echo "[sign-modules] Signed $COUNT unsigned kernel modules"
fi

View File

@@ -104,7 +104,6 @@ local_mount_root()
-olowerdir=/startos/config/overlay:/lower,upperdir=/upper/data,workdir=/upper/work \ -olowerdir=/startos/config/overlay:/lower,upperdir=/upper/data,workdir=/upper/work \
overlay ${rootmnt} overlay ${rootmnt}
mkdir -m 750 -p ${rootmnt}/media/startos
mkdir -p ${rootmnt}/media/startos/config mkdir -p ${rootmnt}/media/startos/config
mount --bind /startos/config ${rootmnt}/media/startos/config mount --bind /startos/config ${rootmnt}/media/startos/config
mkdir -p ${rootmnt}/media/startos/images mkdir -p ${rootmnt}/media/startos/images

View File

@@ -24,7 +24,7 @@ fi
unsquashfs -f -d / $1 boot unsquashfs -f -d / $1 boot
umount -l /media/startos/next 2> /dev/null || true umount -R /media/startos/next 2> /dev/null || true
umount /media/startos/upper 2> /dev/null || true umount /media/startos/upper 2> /dev/null || true
umount /media/startos/lower 2> /dev/null || true umount /media/startos/lower 2> /dev/null || true
@@ -45,13 +45,18 @@ mkdir -p /media/startos/next/media/startos/root
mount --bind /run /media/startos/next/run mount --bind /run /media/startos/next/run
mount --bind /tmp /media/startos/next/tmp mount --bind /tmp /media/startos/next/tmp
mount --bind /dev /media/startos/next/dev mount --bind /dev /media/startos/next/dev
mount -t sysfs sysfs /media/startos/next/sys mount --bind /sys /media/startos/next/sys
mount -t proc proc /media/startos/next/proc mount --bind /proc /media/startos/next/proc
mount --rbind /boot /media/startos/next/boot mount --bind /boot /media/startos/next/boot
mount --bind /media/startos/root /media/startos/next/media/startos/root mount --bind /media/startos/root /media/startos/next/media/startos/root
if mountpoint /boot/efi 2>&1 > /dev/null; then
mkdir -p /media/startos/next/boot/efi
mount --bind /boot/efi /media/startos/next/boot/efi
fi
if mountpoint /sys/firmware/efi/efivars 2>&1 > /dev/null; then if mountpoint /sys/firmware/efi/efivars 2>&1 > /dev/null; then
mount -t efivarfs efivarfs /media/startos/next/sys/firmware/efi/efivars mount --bind /sys/firmware/efi/efivars /media/startos/next/sys/firmware/efi/efivars
fi fi
chroot /media/startos/next bash -e << "EOF" chroot /media/startos/next bash -e << "EOF"
@@ -63,18 +68,24 @@ fi
EOF EOF
# Sign unsigned kernel modules for Secure Boot # Promote the USB installer boot entry back to first in EFI boot order.
SIGN_FILE="$(ls -1 /media/startos/next/usr/lib/linux-kbuild-*/scripts/sign-file 2>/dev/null | head -1)" # The entry number was saved during initial OS install.
/media/startos/next/usr/lib/startos/scripts/sign-unsigned-modules \ if [ -d /sys/firmware/efi ] && [ -f /media/startos/config/efi-installer-entry ]; then
--source /media/startos/lower \ USB_ENTRY=$(cat /media/startos/config/efi-installer-entry)
--dest /media/startos/config/overlay \ if [ -n "$USB_ENTRY" ]; then
--sign-file "$SIGN_FILE" \ CURRENT_ORDER=$(efibootmgr | grep BootOrder | sed 's/BootOrder: //')
--mok-key /media/startos/config/overlay/var/lib/dkms/mok.key \ OTHER_ENTRIES=$(echo "$CURRENT_ORDER" | tr ',' '\n' | grep -v "$USB_ENTRY" | tr '\n' ',' | sed 's/,$//')
--mok-pub /media/startos/config/overlay/var/lib/dkms/mok.pub if [ -n "$OTHER_ENTRIES" ]; then
efibootmgr -o "$USB_ENTRY,$OTHER_ENTRIES"
else
efibootmgr -o "$USB_ENTRY"
fi
fi
fi
sync sync
umount -l /media/startos/next umount -Rl /media/startos/next
umount /media/startos/upper umount /media/startos/upper
umount /media/startos/lower umount /media/startos/lower

View File

@@ -198,22 +198,20 @@ cmd_sign() {
enter_release_dir enter_release_dir
resolve_gh_user resolve_gh_user
mkdir -p signatures
for file in $(release_files); do for file in $(release_files); do
gpg -u $START9_GPG_KEY --detach-sign --armor -o "signatures/${file}.start9.asc" "$file" gpg -u $START9_GPG_KEY --detach-sign --armor -o "${file}.start9.asc" "$file"
if [ -n "$GH_USER" ] && [ -n "$GH_GPG_KEY" ]; then if [ -n "$GH_USER" ] && [ -n "$GH_GPG_KEY" ]; then
gpg -u "$GH_GPG_KEY" --detach-sign --armor -o "signatures/${file}.${GH_USER}.asc" "$file" gpg -u "$GH_GPG_KEY" --detach-sign --armor -o "${file}.${GH_USER}.asc" "$file"
fi fi
done done
gpg --export -a $START9_GPG_KEY > signatures/start9.key.asc gpg --export -a $START9_GPG_KEY > start9.key.asc
if [ -n "$GH_USER" ] && [ -n "$GH_GPG_KEY" ]; then if [ -n "$GH_USER" ] && [ -n "$GH_GPG_KEY" ]; then
gpg --export -a "$GH_GPG_KEY" > "signatures/${GH_USER}.key.asc" gpg --export -a "$GH_GPG_KEY" > "${GH_USER}.key.asc"
else else
>&2 echo 'Warning: could not determine GitHub user or GPG signing key, skipping personal signature' >&2 echo 'Warning: could not determine GitHub user or GPG signing key, skipping personal signature'
fi fi
tar -czvf signatures.tar.gz -C signatures . tar -czvf signatures.tar.gz *.asc
gh release upload -R $REPO "v$VERSION" signatures.tar.gz --clobber gh release upload -R $REPO "v$VERSION" signatures.tar.gz --clobber
} }
@@ -231,18 +229,17 @@ cmd_cosign() {
echo "Downloading existing signatures..." echo "Downloading existing signatures..."
gh release download -R $REPO "v$VERSION" -p "signatures.tar.gz" -D "$(pwd)" --clobber gh release download -R $REPO "v$VERSION" -p "signatures.tar.gz" -D "$(pwd)" --clobber
mkdir -p signatures tar -xzf signatures.tar.gz
tar -xzf signatures.tar.gz -C signatures
echo "Adding personal signatures as $GH_USER..." echo "Adding personal signatures as $GH_USER..."
for file in $(release_files); do for file in $(release_files); do
gpg -u "$GH_GPG_KEY" --detach-sign --armor -o "signatures/${file}.${GH_USER}.asc" "$file" gpg -u "$GH_GPG_KEY" --detach-sign --armor -o "${file}.${GH_USER}.asc" "$file"
done done
gpg --export -a "$GH_GPG_KEY" > "signatures/${GH_USER}.key.asc" gpg --export -a "$GH_GPG_KEY" > "${GH_USER}.key.asc"
echo "Re-packing signatures..." echo "Re-packing signatures..."
tar -czvf signatures.tar.gz -C signatures . tar -czvf signatures.tar.gz *.asc
gh release upload -R $REPO "v$VERSION" signatures.tar.gz --clobber gh release upload -R $REPO "v$VERSION" signatures.tar.gz --clobber
echo "Done. Personal signatures for $GH_USER added to v$VERSION." echo "Done. Personal signatures for $GH_USER added to v$VERSION."

View File

@@ -5,7 +5,7 @@ OnFailure=container-runtime-failure.service
[Service] [Service]
Type=simple Type=simple
Environment=RUST_LOG=startos=debug Environment=RUST_LOG=startos=debug
ExecStart=/usr/bin/start-container pipe-wrap /usr/bin/node --experimental-detect-module --trace-warnings /usr/lib/startos/init/index.js ExecStart=/usr/bin/node --experimental-detect-module --trace-warnings --unhandled-rejections=warn /usr/lib/startos/init/index.js
Restart=no Restart=no
[Install] [Install]

View File

@@ -37,7 +37,7 @@
}, },
"../sdk/dist": { "../sdk/dist": {
"name": "@start9labs/start-sdk", "name": "@start9labs/start-sdk",
"version": "0.4.0-beta.64", "version": "0.4.0-beta.58",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@iarna/toml": "^3.0.0", "@iarna/toml": "^3.0.0",
@@ -45,7 +45,6 @@
"@noble/hashes": "^1.7.2", "@noble/hashes": "^1.7.2",
"@types/ini": "^4.1.1", "@types/ini": "^4.1.1",
"deep-equality-data-structures": "^2.0.0", "deep-equality-data-structures": "^2.0.0",
"fast-xml-parser": "^5.5.6",
"ini": "^5.0.0", "ini": "^5.0.0",
"isomorphic-fetch": "^3.0.0", "isomorphic-fetch": "^3.0.0",
"mime": "^4.0.7", "mime": "^4.0.7",

View File

@@ -187,10 +187,9 @@ export function makeEffects(context: EffectContext): Effects {
getServiceManifest( getServiceManifest(
...[options]: Parameters<T.Effects["getServiceManifest"]> ...[options]: Parameters<T.Effects["getServiceManifest"]>
) { ) {
return rpcRound("get-service-manifest", { return rpcRound("get-service-manifest", options) as ReturnType<
...options, T.Effects["getServiceManifest"]
callback: context.callbacks?.addCallback(options.callback) || null, >
}) as ReturnType<T.Effects["getServiceManifest"]>
}, },
subcontainer: { subcontainer: {
createFs(options: { imageId: string; name: string }) { createFs(options: { imageId: string; name: string }) {
@@ -212,10 +211,9 @@ export function makeEffects(context: EffectContext): Effects {
> >
}) as Effects["exportServiceInterface"], }) as Effects["exportServiceInterface"],
getContainerIp(...[options]: Parameters<T.Effects["getContainerIp"]>) { getContainerIp(...[options]: Parameters<T.Effects["getContainerIp"]>) {
return rpcRound("get-container-ip", { return rpcRound("get-container-ip", options) as ReturnType<
...options, T.Effects["getContainerIp"]
callback: context.callbacks?.addCallback(options.callback) || null, >
}) as ReturnType<T.Effects["getContainerIp"]>
}, },
getOsIp(...[]: Parameters<T.Effects["getOsIp"]>) { getOsIp(...[]: Parameters<T.Effects["getOsIp"]>) {
return rpcRound("get-os-ip", {}) as ReturnType<T.Effects["getOsIp"]> return rpcRound("get-os-ip", {}) as ReturnType<T.Effects["getOsIp"]>
@@ -246,10 +244,9 @@ export function makeEffects(context: EffectContext): Effects {
> >
}, },
getSslCertificate(options: Parameters<T.Effects["getSslCertificate"]>[0]) { getSslCertificate(options: Parameters<T.Effects["getSslCertificate"]>[0]) {
return rpcRound("get-ssl-certificate", { return rpcRound("get-ssl-certificate", options) as ReturnType<
...options, T.Effects["getSslCertificate"]
callback: context.callbacks?.addCallback(options.callback) || null, >
}) as ReturnType<T.Effects["getSslCertificate"]>
}, },
getSslKey(options: Parameters<T.Effects["getSslKey"]>[0]) { getSslKey(options: Parameters<T.Effects["getSslKey"]>[0]) {
return rpcRound("get-ssl-key", options) as ReturnType< return rpcRound("get-ssl-key", options) as ReturnType<
@@ -311,10 +308,7 @@ export function makeEffects(context: EffectContext): Effects {
}, },
getStatus(...[o]: Parameters<T.Effects["getStatus"]>) { getStatus(...[o]: Parameters<T.Effects["getStatus"]>) {
return rpcRound("get-status", { return rpcRound("get-status", o) as ReturnType<T.Effects["getStatus"]>
...o,
callback: context.callbacks?.addCallback(o.callback) || null,
}) as ReturnType<T.Effects["getStatus"]>
}, },
/// DEPRECATED /// DEPRECATED
setMainStatus(o: { status: "running" | "stopped" }): Promise<null> { setMainStatus(o: { status: "running" | "stopped" }): Promise<null> {

View File

@@ -298,10 +298,13 @@ export class RpcListener {
} }
case "stop": { case "stop": {
const { id } = stopType.parse(input) const { id } = stopType.parse(input)
this.callbacks?.removeChild("main")
return handleRpc( return handleRpc(
id, id,
this.system.stop().then((result) => ({ result })), this.system.stop().then((result) => {
this.callbacks?.removeChild("main")
return { result }
}),
) )
} }
case "exit": { case "exit": {

View File

@@ -42,74 +42,6 @@ function todo(): never {
throw new Error("Not implemented") throw new Error("Not implemented")
} }
function getStatus(
effects: Effects,
options: Omit<Parameters<Effects["getStatus"]>[0], "callback"> = {},
) {
async function* watch(abort?: AbortSignal) {
const resolveCell = { resolve: () => {} }
effects.onLeaveContext(() => {
resolveCell.resolve()
})
abort?.addEventListener("abort", () => resolveCell.resolve())
while (effects.isInContext && !abort?.aborted) {
let callback: () => void = () => {}
const waitForNext = new Promise<void>((resolve) => {
callback = resolve
resolveCell.resolve = resolve
})
yield await effects.getStatus({ ...options, callback })
await waitForNext
}
}
return {
const: () =>
effects.getStatus({
...options,
callback:
effects.constRetry &&
(() => effects.constRetry && effects.constRetry()),
}),
once: () => effects.getStatus(options),
watch: (abort?: AbortSignal) => {
const ctrl = new AbortController()
abort?.addEventListener("abort", () => ctrl.abort())
return watch(ctrl.signal)
},
onChange: (
callback: (
value: T.StatusInfo | null,
error?: Error,
) => { cancel: boolean } | Promise<{ cancel: boolean }>,
) => {
;(async () => {
const ctrl = new AbortController()
for await (const value of watch(ctrl.signal)) {
try {
const res = await callback(value)
if (res.cancel) {
ctrl.abort()
break
}
} catch (e) {
console.error(
"callback function threw an error @ getStatus.onChange",
e,
)
}
}
})()
.catch((e) => callback(null, e as Error))
.catch((e) =>
console.error(
"callback function threw an error @ getStatus.onChange",
e,
),
)
},
}
}
/** /**
* Local type for procedure values from the manifest. * Local type for procedure values from the manifest.
* The manifest's zod schemas use ZodTypeAny casts that produce `unknown` in zod v4. * The manifest's zod schemas use ZodTypeAny casts that produce `unknown` in zod v4.
@@ -445,14 +377,15 @@ export class SystemForEmbassy implements System {
} }
callCallback(_callback: number, _args: any[]): void {} callCallback(_callback: number, _args: any[]): void {}
async stop(): Promise<void> { async stop(): Promise<void> {
const clean = this.currentRunning?.clean({ const { currentRunning } = this
timeout: fromDuration( this.currentRunning?.clean()
(this.manifest.main["sigterm-timeout"] as any) || "30s",
),
})
delete this.currentRunning delete this.currentRunning
if (clean) { if (currentRunning) {
await clean await currentRunning.clean({
timeout: fromDuration(
(this.manifest.main["sigterm-timeout"] as any) || "30s",
),
})
} }
} }
@@ -1113,26 +1046,16 @@ export class SystemForEmbassy implements System {
timeoutMs: number | null, timeoutMs: number | null,
): Promise<void> { ): Promise<void> {
// TODO: docker // TODO: docker
const status = await getStatus(effects, { packageId: id }).const() await effects.mount({
if (!status) return location: `/media/embassy/${id}`,
try { target: {
await effects.mount({ packageId: id,
location: `/media/embassy/${id}`, volumeId: "embassy",
target: { subpath: null,
packageId: id, readonly: true,
volumeId: "embassy", idmap: [],
subpath: null, },
readonly: true, })
idmap: [],
},
})
} catch (e) {
console.error(
`Failed to mount dependency volume for ${id}, skipping autoconfig:`,
e,
)
return
}
configFile configFile
.withPath(`/media/embassy/${id}/config.json`) .withPath(`/media/embassy/${id}/config.json`)
.read() .read()
@@ -1281,11 +1204,6 @@ async function updateConfig(
if (specValue.target === "config") { if (specValue.target === "config") {
const jp = require("jsonpath") const jp = require("jsonpath")
const depId = specValue["package-id"] const depId = specValue["package-id"]
const depStatus = await getStatus(effects, { packageId: depId }).const()
if (!depStatus) {
mutConfigValue[key] = null
continue
}
await effects.mount({ await effects.mount({
location: `/media/embassy/${depId}`, location: `/media/embassy/${depId}`,
target: { target: {

View File

@@ -10,11 +10,6 @@ const matchJsProcedure = z.object({
const matchProcedure = z.union([matchDockerProcedure, matchJsProcedure]) const matchProcedure = z.union([matchDockerProcedure, matchJsProcedure])
export type Procedure = z.infer<typeof matchProcedure> export type Procedure = z.infer<typeof matchProcedure>
const healthCheckFields = {
name: z.string(),
"success-message": z.string().nullable().optional(),
}
const matchAction = z.object({ const matchAction = z.object({
name: z.string(), name: z.string(),
description: z.string(), description: z.string(),
@@ -37,10 +32,13 @@ export const matchManifest = z.object({
.optional(), .optional(),
"health-checks": z.record( "health-checks": z.record(
z.string(), z.string(),
z.union([ z.intersection(
matchDockerProcedure.extend(healthCheckFields), matchProcedure,
matchJsProcedure.extend(healthCheckFields), z.object({
]), name: z.string(),
"success-message": z.string().nullable().optional(),
}),
),
), ),
config: z config: z
.object({ .object({

View File

@@ -71,7 +71,7 @@ export class SystemForStartOs implements System {
this.starting = true this.starting = true
effects.constRetry = utils.once(() => { effects.constRetry = utils.once(() => {
console.debug(".const() triggered") console.debug(".const() triggered")
if (effects.isInContext) effects.restart() effects.restart()
}) })
let mainOnTerm: () => Promise<void> | undefined let mainOnTerm: () => Promise<void> | undefined
const daemons = await ( const daemons = await (

View File

@@ -23,7 +23,6 @@ The crate produces a single binary `startbox` that is symlinked under different
- `src/context/` — Context types (RpcContext, CliContext, InitContext, DiagnosticContext) - `src/context/` — Context types (RpcContext, CliContext, InitContext, DiagnosticContext)
- `src/service/` — Service lifecycle management with actor pattern (`service_actor.rs`) - `src/service/` — Service lifecycle management with actor pattern (`service_actor.rs`)
- `src/db/model/` — Patch-DB models (`public.rs` synced to frontend, `private.rs` backend-only) - `src/db/model/` — Patch-DB models (`public.rs` synced to frontend, `private.rs` backend-only)
- `src/mcp/` — MCP server for LLM agents (see [MCP Server](#mcp-server) below)
- `src/net/` — Networking (DNS, ACME, WiFi, Tor via Arti, WireGuard) - `src/net/` — Networking (DNS, ACME, WiFi, Tor via Arti, WireGuard)
- `src/s9pk/` — S9PK package format (merkle archive) - `src/s9pk/` — S9PK package format (merkle archive)
- `src/registry/` — Package registry management - `src/registry/` — Package registry management
@@ -39,19 +38,16 @@ See [rpc-toolkit.md](rpc-toolkit.md) for full handler patterns and configuration
Patch-DB provides diff-based state synchronization. Changes to `db/model/public.rs` automatically sync to the frontend. Patch-DB provides diff-based state synchronization. Changes to `db/model/public.rs` automatically sync to the frontend.
**Key patterns:** **Key patterns:**
- `db.peek().await` — Get a read-only snapshot of the database state - `db.peek().await` — Get a read-only snapshot of the database state
- `db.mutate(|db| { ... }).await` — Apply mutations atomically, returns `MutateResult` - `db.mutate(|db| { ... }).await` — Apply mutations atomically, returns `MutateResult`
- `#[derive(HasModel)]` — Derive macro for types stored in the database, generates typed accessors - `#[derive(HasModel)]` — Derive macro for types stored in the database, generates typed accessors
**Generated accessor types** (from `HasModel` derive): **Generated accessor types** (from `HasModel` derive):
- `as_field()` — Immutable reference: `&Model<T>` - `as_field()` — Immutable reference: `&Model<T>`
- `as_field_mut()` — Mutable reference: `&mut Model<T>` - `as_field_mut()` — Mutable reference: `&mut Model<T>`
- `into_field()` — Owned value: `Model<T>` - `into_field()` — Owned value: `Model<T>`
**`Model<T>` APIs** (from `db/prelude.rs`): **`Model<T>` APIs** (from `db/prelude.rs`):
- `.de()` — Deserialize to `T` - `.de()` — Deserialize to `T`
- `.ser(&value)` — Serialize from `T` - `.ser(&value)` — Serialize from `T`
- `.mutate(|v| ...)` — Deserialize, mutate, reserialize - `.mutate(|v| ...)` — Deserialize, mutate, reserialize
@@ -67,12 +63,6 @@ See [i18n-patterns.md](i18n-patterns.md) for internationalization key convention
See [core-rust-patterns.md](core-rust-patterns.md) for common utilities (Invoke trait, Guard pattern, mount guards, Apply trait, etc.). See [core-rust-patterns.md](core-rust-patterns.md) for common utilities (Invoke trait, Guard pattern, mount guards, Apply trait, etc.).
## MCP Server
The MCP (Model Context Protocol) server at `src/mcp/` exposes the StartOS RPC API to LLM agents via the Streamable HTTP transport at `/mcp`. Tools wrap the existing RPC handlers; resources expose Patch-DB state with debounced SSE subscriptions; auth reuses the UI session cookie.
See [src/mcp/ARCHITECTURE.md](src/mcp/ARCHITECTURE.md) for transport details, session lifecycle, tool dispatch, resource subscriptions, CORS, and body size limits.
## Related Documentation ## Related Documentation
- [rpc-toolkit.md](rpc-toolkit.md) — JSON-RPC handler patterns - [rpc-toolkit.md](rpc-toolkit.md) — JSON-RPC handler patterns

View File

@@ -22,7 +22,7 @@ cd sdk && make baseDist dist # Rebuild SDK after ts-bindings
- Always run `cargo check -p start-os` after modifying Rust code - Always run `cargo check -p start-os` after modifying Rust code
- When adding RPC endpoints, follow the patterns in [rpc-toolkit.md](rpc-toolkit.md) - When adding RPC endpoints, follow the patterns in [rpc-toolkit.md](rpc-toolkit.md)
- When modifying `#[ts(export)]` types, regenerate bindings and rebuild the SDK (see [ARCHITECTURE.md](../ARCHITECTURE.md#build-pipeline)) - When modifying `#[ts(export)]` types, regenerate bindings and rebuild the SDK (see [ARCHITECTURE.md](../ARCHITECTURE.md#build-pipeline))
- **i18n is mandatory** — any user-facing string must go in `core/locales/i18n.yaml` with all 5 locales (`en_US`, `de_DE`, `es_ES`, `fr_FR`, `pl_PL`). This includes CLI subcommand descriptions (`about.<name>`), CLI arg help (`help.arg.<name>`), error messages (`error.<name>`), notifications, setup messages, and any other text shown to users. Entries are alphabetically ordered within their section. See [i18n-patterns.md](i18n-patterns.md) - When adding i18n keys, add all 5 locales in `core/locales/i18n.yaml` (see [i18n-patterns.md](i18n-patterns.md))
- When using DB watches, follow the `TypedDbWatch<T>` patterns in [patchdb.md](patchdb.md) - When using DB watches, follow the `TypedDbWatch<T>` patterns in [patchdb.md](patchdb.md)
- **Always use `.invoke(ErrorKind::...)` instead of `.status()` when running CLI commands** via `tokio::process::Command`. The `Invoke` trait (from `crate::util::Invoke`) captures stdout/stderr and checks exit codes properly. Using `.status()` leaks stderr directly to system logs, creating noise. For check-then-act patterns (e.g. `iptables -C`), use `.invoke(...).await.is_ok()` / `.is_err()` instead of `.status().await.map_or(false, |s| s.success())`. - **Always use `.invoke(ErrorKind::...)` instead of `.status()` when running CLI commands** via `tokio::process::Command`. The `Invoke` trait (from `crate::util::Invoke`) captures stdout/stderr and checks exit codes properly. Using `.status()` leaks stderr directly to system logs, creating noise. For check-then-act patterns (e.g. `iptables -C`), use `.invoke(...).await.is_ok()` / `.is_err()` instead of `.status().await.map_or(false, |s| s.success())`.
- Always use file utils in util::io instead of tokio::fs when available - Always use file utils in util::io instead of tokio::fs when available

751
core/Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -15,7 +15,7 @@ license = "MIT"
name = "start-os" name = "start-os"
readme = "README.md" readme = "README.md"
repository = "https://github.com/Start9Labs/start-os" repository = "https://github.com/Start9Labs/start-os"
version = "0.4.0-alpha.22" # VERSION_BUMP version = "0.4.0-alpha.20" # VERSION_BUMP
[lib] [lib]
name = "startos" name = "startos"
@@ -63,7 +63,7 @@ async-compression = { version = "0.4.32", features = [
] } ] }
async-stream = "0.3.5" async-stream = "0.3.5"
async-trait = "0.1.74" async-trait = "0.1.74"
axum = { version = "0.8.4", features = ["http2", "ws"] } axum = { version = "0.8.4", features = ["ws", "http2"] }
backtrace-on-stack-overflow = { version = "0.3.0", optional = true } backtrace-on-stack-overflow = { version = "0.3.0", optional = true }
base32 = "0.5.0" base32 = "0.5.0"
base64 = "0.22.1" base64 = "0.22.1"
@@ -100,7 +100,6 @@ fd-lock-rs = "0.1.4"
form_urlencoded = "1.2.1" form_urlencoded = "1.2.1"
futures = "0.3.28" futures = "0.3.28"
gpt = "4.1.0" gpt = "4.1.0"
hashing-serializer = "0.1.1"
hex = "0.4.3" hex = "0.4.3"
hickory-server = { version = "0.25.2", features = ["resolver"] } hickory-server = { version = "0.25.2", features = ["resolver"] }
hmac = "0.12.1" hmac = "0.12.1"
@@ -171,7 +170,9 @@ once_cell = "1.19.0"
openssh-keys = "0.6.2" openssh-keys = "0.6.2"
openssl = { version = "0.10.57", features = ["vendored"] } openssl = { version = "0.10.57", features = ["vendored"] }
p256 = { version = "0.13.2", features = ["pem"] } p256 = { version = "0.13.2", features = ["pem"] }
patch-db = { version = "*", path = "../patch-db/core", features = ["trace"] } patch-db = { version = "*", path = "../patch-db/patch-db", features = [
"trace",
] }
pbkdf2 = "0.12.2" pbkdf2 = "0.12.2"
pin-project = "1.1.3" pin-project = "1.1.3"
pkcs8 = { version = "0.10.2", features = ["std"] } pkcs8 = { version = "0.10.2", features = ["std"] }
@@ -183,16 +184,16 @@ r3bl_tui = "0.7.6"
rand = "0.9.2" rand = "0.9.2"
regex = "1.10.2" regex = "1.10.2"
reqwest = { version = "0.12.25", features = [ reqwest = { version = "0.12.25", features = [
"http2",
"json", "json",
"socks", "socks",
"stream", "stream",
"http2",
] } ] }
reqwest_cookie_store = "0.9.0" reqwest_cookie_store = "0.9.0"
rpassword = "7.2.0" rpassword = "7.2.0"
rpc-toolkit = { git = "https://github.com/Start9Labs/rpc-toolkit.git" }
rust-argon2 = "3.0.0" rust-argon2 = "3.0.0"
rust-i18n = "3.1.5" rust-i18n = "3.1.5"
rpc-toolkit = { git = "https://github.com/Start9Labs/rpc-toolkit.git" }
semver = { version = "1.0.20", features = ["serde"] } semver = { version = "1.0.20", features = ["serde"] }
serde = { version = "1.0", features = ["derive", "rc"] } serde = { version = "1.0", features = ["derive", "rc"] }
serde_cbor = { package = "ciborium", version = "0.2.1" } serde_cbor = { package = "ciborium", version = "0.2.1" }
@@ -201,7 +202,6 @@ serde_toml = { package = "toml", version = "0.9.9+spec-1.0.0" }
serde_yaml = { package = "serde_yml", version = "0.0.12" } serde_yaml = { package = "serde_yml", version = "0.0.12" }
sha-crypt = "0.5.0" sha-crypt = "0.5.0"
sha2 = "0.10.2" sha2 = "0.10.2"
sha3 = "0.10"
signal-hook = "0.3.17" signal-hook = "0.3.17"
socket2 = { version = "0.6.0", features = ["all"] } socket2 = { version = "0.6.0", features = ["all"] }
socks5-impl = { version = "0.7.2", features = ["client", "server"] } socks5-impl = { version = "0.7.2", features = ["client", "server"] }
@@ -233,9 +233,7 @@ uuid = { version = "1.4.1", features = ["v4"] }
visit-rs = "0.1.1" visit-rs = "0.1.1"
x25519-dalek = { version = "2.0.1", features = ["static_secrets"] } x25519-dalek = { version = "2.0.1", features = ["static_secrets"] }
zbus = "5.1.1" zbus = "5.1.1"
hashing-serializer = "0.1.1"
[dev-dependencies]
clap_mangen = "0.2.33"
[target.'cfg(target_os = "linux")'.dependencies] [target.'cfg(target_os = "linux")'.dependencies]
procfs = "0.18.0" procfs = "0.18.0"

View File

@@ -67,10 +67,6 @@ if [[ "${ENVIRONMENT:-}" =~ (^|-)console($|-) ]]; then
RUSTFLAGS="--cfg tokio_unstable" RUSTFLAGS="--cfg tokio_unstable"
fi fi
if [[ "${ENVIRONMENT:-}" =~ (^|-)unstable($|-) ]]; then
RUSTFLAGS="$RUSTFLAGS -C debuginfo=1"
fi
echo "FEATURES=\"$FEATURES\"" echo "FEATURES=\"$FEATURES\""
echo "RUSTFLAGS=\"$RUSTFLAGS\"" echo "RUSTFLAGS=\"$RUSTFLAGS\""
rust-zig-builder cargo zigbuild --manifest-path=./core/Cargo.toml $BUILD_FLAGS --features=$FEATURES --locked --bin start-cli --target=$TARGET rust-zig-builder cargo zigbuild --manifest-path=./core/Cargo.toml $BUILD_FLAGS --features=$FEATURES --locked --bin start-cli --target=$TARGET

View File

@@ -1,44 +0,0 @@
#!/bin/bash
cd "$(dirname "${BASH_SOURCE[0]}")"
source ./builder-alias.sh
set -ea
shopt -s expand_aliases
PROFILE=${PROFILE:-debug}
if [ "${PROFILE}" = "release" ]; then
BUILD_FLAGS="--release"
else
if [ "$PROFILE" != "debug" ]; then
>&2 echo "Unknown profile $PROFILE: falling back to debug..."
PROFILE=debug
fi
fi
if [ -z "$ARCH" ]; then
ARCH=$(uname -m)
fi
if [ "$ARCH" = "arm64" ]; then
ARCH="aarch64"
fi
RUST_ARCH="$ARCH"
if [ "$ARCH" = "riscv64" ]; then
RUST_ARCH="riscv64gc"
fi
cd ../..
FEATURES="$(echo $ENVIRONMENT | sed 's/-/,/g')"
RUSTFLAGS=""
if [[ "${ENVIRONMENT}" =~ (^|-)console($|-) ]]; then
RUSTFLAGS="--cfg tokio_unstable"
fi
echo "FEATURES=\"$FEATURES\""
echo "RUSTFLAGS=\"$RUSTFLAGS\""
rust-zig-builder cargo test --manifest-path=./core/Cargo.toml --lib $BUILD_FLAGS --features test,$FEATURES --locked 'export_manpage_'
if [ "$(ls -nd "core/man" | awk '{ print $3 }')" != "$UID" ]; then
rust-zig-builder sh -c "chown -R $UID:$UID core/target && chown -R $UID:$UID core/man && chown -R $UID:$UID /usr/local/cargo"
fi

View File

@@ -38,10 +38,6 @@ if [[ "${ENVIRONMENT}" =~ (^|-)console($|-) ]]; then
RUSTFLAGS="--cfg tokio_unstable" RUSTFLAGS="--cfg tokio_unstable"
fi fi
if [[ "${ENVIRONMENT}" =~ (^|-)unstable($|-) ]]; then
RUSTFLAGS="$RUSTFLAGS -C debuginfo=1"
fi
echo "FEATURES=\"$FEATURES\"" echo "FEATURES=\"$FEATURES\""
echo "RUSTFLAGS=\"$RUSTFLAGS\"" echo "RUSTFLAGS=\"$RUSTFLAGS\""
rust-zig-builder cargo zigbuild --manifest-path=./core/Cargo.toml $BUILD_FLAGS --features=$FEATURES --locked --bin registrybox --target=$RUST_ARCH-unknown-linux-musl rust-zig-builder cargo zigbuild --manifest-path=./core/Cargo.toml $BUILD_FLAGS --features=$FEATURES --locked --bin registrybox --target=$RUST_ARCH-unknown-linux-musl

View File

@@ -38,10 +38,6 @@ if [[ "${ENVIRONMENT}" =~ (^|-)console($|-) ]]; then
RUSTFLAGS="--cfg tokio_unstable" RUSTFLAGS="--cfg tokio_unstable"
fi fi
if [[ "${ENVIRONMENT}" =~ (^|-)unstable($|-) ]]; then
RUSTFLAGS="$RUSTFLAGS -C debuginfo=1"
fi
echo "FEATURES=\"$FEATURES\"" echo "FEATURES=\"$FEATURES\""
echo "RUSTFLAGS=\"$RUSTFLAGS\"" echo "RUSTFLAGS=\"$RUSTFLAGS\""
rust-zig-builder cargo zigbuild --manifest-path=./core/Cargo.toml $BUILD_FLAGS --features=$FEATURES --locked --bin start-container --target=$RUST_ARCH-unknown-linux-musl rust-zig-builder cargo zigbuild --manifest-path=./core/Cargo.toml $BUILD_FLAGS --features=$FEATURES --locked --bin start-container --target=$RUST_ARCH-unknown-linux-musl

View File

@@ -38,10 +38,6 @@ if [[ "${ENVIRONMENT}" =~ (^|-)console($|-) ]]; then
RUSTFLAGS="--cfg tokio_unstable" RUSTFLAGS="--cfg tokio_unstable"
fi fi
if [[ "${ENVIRONMENT}" =~ (^|-)unstable($|-) ]]; then
RUSTFLAGS="$RUSTFLAGS -C debuginfo=1"
fi
echo "FEATURES=\"$FEATURES\"" echo "FEATURES=\"$FEATURES\""
echo "RUSTFLAGS=\"$RUSTFLAGS\"" echo "RUSTFLAGS=\"$RUSTFLAGS\""
rust-zig-builder cargo zigbuild --manifest-path=./core/Cargo.toml $BUILD_FLAGS --features=$FEATURES --locked --bin startbox --target=$RUST_ARCH-unknown-linux-musl rust-zig-builder cargo zigbuild --manifest-path=./core/Cargo.toml $BUILD_FLAGS --features=$FEATURES --locked --bin startbox --target=$RUST_ARCH-unknown-linux-musl

View File

@@ -38,10 +38,6 @@ if [[ "${ENVIRONMENT}" =~ (^|-)console($|-) ]]; then
RUSTFLAGS="--cfg tokio_unstable" RUSTFLAGS="--cfg tokio_unstable"
fi fi
if [[ "${ENVIRONMENT}" =~ (^|-)unstable($|-) ]]; then
RUSTFLAGS="$RUSTFLAGS -C debuginfo=1"
fi
echo "FEATURES=\"$FEATURES\"" echo "FEATURES=\"$FEATURES\""
echo "RUSTFLAGS=\"$RUSTFLAGS\"" echo "RUSTFLAGS=\"$RUSTFLAGS\""
rust-zig-builder cargo zigbuild --manifest-path=./core/Cargo.toml $BUILD_FLAGS --features=$FEATURES --locked --bin tunnelbox --target=$RUST_ARCH-unknown-linux-musl rust-zig-builder cargo zigbuild --manifest-path=./core/Cargo.toml $BUILD_FLAGS --features=$FEATURES --locked --bin tunnelbox --target=$RUST_ARCH-unknown-linux-musl

View File

@@ -857,13 +857,6 @@ error.set-sys-info:
fr_FR: "Erreur de Définition des Infos Système" fr_FR: "Erreur de Définition des Infos Système"
pl_PL: "Błąd Ustawiania Informacji o Systemie" pl_PL: "Błąd Ustawiania Informacji o Systemie"
error.bios:
en_US: "BIOS/UEFI Error"
de_DE: "BIOS/UEFI-Fehler"
es_ES: "Error de BIOS/UEFI"
fr_FR: "Erreur BIOS/UEFI"
pl_PL: "Błąd BIOS/UEFI"
# disk/main.rs # disk/main.rs
disk.main.disk-not-found: disk.main.disk-not-found:
en_US: "StartOS disk not found." en_US: "StartOS disk not found."
@@ -872,13 +865,6 @@ disk.main.disk-not-found:
fr_FR: "Disque StartOS non trouvé." fr_FR: "Disque StartOS non trouvé."
pl_PL: "Nie znaleziono dysku StartOS." pl_PL: "Nie znaleziono dysku StartOS."
disk.main.converting-to-btrfs:
en_US: "Performing file system conversion to btrfs. This can take many hours, please be patient and DO NOT unplug the server."
de_DE: "Dateisystemkonvertierung zu btrfs wird durchgeführt. Dies kann viele Stunden dauern, bitte haben Sie Geduld und trennen Sie den Server NICHT vom Strom."
es_ES: "Realizando conversión del sistema de archivos a btrfs. Esto puede tardar muchas horas, tenga paciencia y NO desconecte el servidor."
fr_FR: "Conversion du système de fichiers vers btrfs en cours. Cela peut prendre de nombreuses heures, soyez patient et NE débranchez PAS le serveur."
pl_PL: "Wykonywanie konwersji systemu plików na btrfs. To może potrwać wiele godzin, prosimy o cierpliwość i NIE odłączaj serwera od zasilania."
disk.main.incorrect-disk: disk.main.incorrect-disk:
en_US: "A StartOS disk was found, but it is not the correct disk for this device." en_US: "A StartOS disk was found, but it is not the correct disk for this device."
de_DE: "Eine StartOS-Festplatte wurde gefunden, aber es ist nicht die richtige Festplatte für dieses Gerät." de_DE: "Eine StartOS-Festplatte wurde gefunden, aber es ist nicht die richtige Festplatte für dieses Gerät."
@@ -1262,13 +1248,6 @@ backup.bulk.leaked-reference:
fr_FR: "référence fuitée vers BackupMountGuard" fr_FR: "référence fuitée vers BackupMountGuard"
pl_PL: "wyciekła referencja do BackupMountGuard" pl_PL: "wyciekła referencja do BackupMountGuard"
backup.bulk.service-not-ready:
en_US: "Cannot create a backup of a service that is still initializing or in an error state"
de_DE: "Es kann keine Sicherung eines Dienstes erstellt werden, der noch initialisiert wird oder sich im Fehlerzustand befindet"
es_ES: "No se puede crear una copia de seguridad de un servicio que aún se está inicializando o está en estado de error"
fr_FR: "Impossible de créer une sauvegarde d'un service encore en cours d'initialisation ou en état d'erreur"
pl_PL: "Nie można utworzyć kopii zapasowej usługi, która jest jeszcze inicjalizowana lub znajduje się w stanie błędu"
# backup/restore.rs # backup/restore.rs
backup.restore.package-error: backup.restore.package-error:
en_US: "Error restoring package %{id}: %{error}" en_US: "Error restoring package %{id}: %{error}"
@@ -1393,21 +1372,6 @@ net.tor.client-error:
fr_FR: "Erreur du client Tor : %{error}" fr_FR: "Erreur du client Tor : %{error}"
pl_PL: "Błąd klienta Tor: %{error}" pl_PL: "Błąd klienta Tor: %{error}"
# net/tunnel.rs
net.tunnel.timeout-waiting-for-add:
en_US: "timed out waiting for gateway %{gateway} to appear in database"
de_DE: "Zeitüberschreitung beim Warten auf das Erscheinen von Gateway %{gateway} in der Datenbank"
es_ES: "se agotó el tiempo esperando que la puerta de enlace %{gateway} aparezca en la base de datos"
fr_FR: "délai d'attente dépassé pour l'apparition de la passerelle %{gateway} dans la base de données"
pl_PL: "upłynął limit czasu oczekiwania na pojawienie się bramy %{gateway} w bazie danych"
net.tunnel.timeout-waiting-for-remove:
en_US: "timed out waiting for gateway %{gateway} to be removed from database"
de_DE: "Zeitüberschreitung beim Warten auf das Entfernen von Gateway %{gateway} aus der Datenbank"
es_ES: "se agotó el tiempo esperando que la puerta de enlace %{gateway} sea eliminada de la base de datos"
fr_FR: "délai d'attente dépassé pour la suppression de la passerelle %{gateway} de la base de données"
pl_PL: "upłynął limit czasu oczekiwania na usunięcie bramy %{gateway} z bazy danych"
# net/wifi.rs # net/wifi.rs
net.wifi.ssid-no-special-characters: net.wifi.ssid-no-special-characters:
en_US: "SSID may not have special characters" en_US: "SSID may not have special characters"
@@ -1621,13 +1585,6 @@ net.gateway.cannot-delete-without-connection:
fr_FR: "Impossible de supprimer l'appareil sans connexion active" fr_FR: "Impossible de supprimer l'appareil sans connexion active"
pl_PL: "Nie można usunąć urządzenia bez aktywnego połączenia" pl_PL: "Nie można usunąć urządzenia bez aktywnego połączenia"
net.gateway.no-configured-echoip-urls:
en_US: "No configured echoip URLs"
de_DE: "Keine konfigurierten EchoIP-URLs"
es_ES: "No hay URLs de echoip configuradas"
fr_FR: "Aucune URL echoip configurée"
pl_PL: "Brak skonfigurowanych adresów URL echoip"
# net/dns.rs # net/dns.rs
net.dns.timeout-updating-catalog: net.dns.timeout-updating-catalog:
en_US: "timed out waiting to update dns catalog" en_US: "timed out waiting to update dns catalog"
@@ -2663,13 +2620,6 @@ help.arg.allow-partial-backup:
fr_FR: "Laisser le média monté même si backupfs échoue à monter" fr_FR: "Laisser le média monté même si backupfs échoue à monter"
pl_PL: "Pozostaw nośnik zamontowany nawet jeśli backupfs nie może się zamontować" pl_PL: "Pozostaw nośnik zamontowany nawet jeśli backupfs nie może się zamontować"
help.arg.architecture:
en_US: "Target CPU architecture (e.g. x86_64, aarch64)"
de_DE: "Ziel-CPU-Architektur (z.B. x86_64, aarch64)"
es_ES: "Arquitectura de CPU objetivo (ej. x86_64, aarch64)"
fr_FR: "Architecture CPU cible (ex. x86_64, aarch64)"
pl_PL: "Docelowa architektura CPU (np. x86_64, aarch64)"
help.arg.architecture-mask: help.arg.architecture-mask:
en_US: "Filter by CPU architecture" en_US: "Filter by CPU architecture"
de_DE: "Nach CPU-Architektur filtern" de_DE: "Nach CPU-Architektur filtern"
@@ -2796,13 +2746,6 @@ help.arg.download-directory:
fr_FR: "Chemin du répertoire de téléchargement" fr_FR: "Chemin du répertoire de téléchargement"
pl_PL: "Ścieżka katalogu do pobrania" pl_PL: "Ścieżka katalogu do pobrania"
help.arg.echoip-urls:
en_US: "Echo IP service URLs for external IP detection"
de_DE: "Echo-IP-Dienst-URLs zur externen IP-Erkennung"
es_ES: "URLs del servicio Echo IP para detección de IP externa"
fr_FR: "URLs du service Echo IP pour la détection d'IP externe"
pl_PL: "Adresy URL usługi Echo IP do wykrywania zewnętrznego IP"
help.arg.emulate-missing-arch: help.arg.emulate-missing-arch:
en_US: "Emulate missing architecture using this one" en_US: "Emulate missing architecture using this one"
de_DE: "Fehlende Architektur mit dieser emulieren" de_DE: "Fehlende Architektur mit dieser emulieren"
@@ -2971,13 +2914,6 @@ help.arg.log-limit:
fr_FR: "Nombre maximum d'entrées de journal" fr_FR: "Nombre maximum d'entrées de journal"
pl_PL: "Maksymalna liczba wpisów logu" pl_PL: "Maksymalna liczba wpisów logu"
help.arg.merge:
en_US: "Merge with existing version range instead of replacing"
de_DE: "Mit vorhandenem Versionsbereich zusammenführen statt ersetzen"
es_ES: "Combinar con el rango de versiones existente en lugar de reemplazar"
fr_FR: "Fusionner avec la plage de versions existante au lieu de remplacer"
pl_PL: "Połącz z istniejącym zakresem wersji zamiast zastępować"
help.arg.mirror-url: help.arg.mirror-url:
en_US: "URL of the mirror" en_US: "URL of the mirror"
de_DE: "URL des Spiegels" de_DE: "URL des Spiegels"
@@ -5268,12 +5204,12 @@ about.reset-user-interface-password:
fr_FR: "Réinitialiser le mot de passe de l'interface utilisateur" fr_FR: "Réinitialiser le mot de passe de l'interface utilisateur"
pl_PL: "Zresetuj hasło interfejsu użytkownika" pl_PL: "Zresetuj hasło interfejsu użytkownika"
about.uninitialize-webserver: about.reset-webserver:
en_US: "Uninitialize the webserver" en_US: "Reset the webserver"
de_DE: "Den Webserver deinitialisieren" de_DE: "Den Webserver zurücksetzen"
es_ES: "Desinicializar el servidor web" es_ES: "Restablecer el servidor web"
fr_FR: "Désinitialiser le serveur web" fr_FR: "initialiser le serveur web"
pl_PL: "Zdezinicjalizuj serwer internetowy" pl_PL: "Zresetuj serwer internetowy"
about.restart-server: about.restart-server:
en_US: "Restart the server" en_US: "Restart the server"
@@ -5289,13 +5225,6 @@ about.restart-service:
fr_FR: "Redémarrer un service" fr_FR: "Redémarrer un service"
pl_PL: "Uruchom ponownie usługę" pl_PL: "Uruchom ponownie usługę"
about.restart-tunnel:
en_US: "Reboot the tunnel server"
de_DE: "Den Tunnel-Server neu starten"
es_ES: "Reiniciar el servidor del túnel"
fr_FR: "Redémarrer le serveur tunnel"
pl_PL: "Uruchom ponownie serwer tunelu"
about.restore-packages-from-backup: about.restore-packages-from-backup:
en_US: "Restore packages from backup" en_US: "Restore packages from backup"
de_DE: "Pakete aus Backup wiederherstellen" de_DE: "Pakete aus Backup wiederherstellen"
@@ -5317,13 +5246,6 @@ about.set-country:
fr_FR: "Définir le pays" fr_FR: "Définir le pays"
pl_PL: "Ustaw kraj" pl_PL: "Ustaw kraj"
about.set-echoip-urls:
en_US: "Set the Echo IP service URLs"
de_DE: "Die Echo-IP-Dienst-URLs festlegen"
es_ES: "Establecer las URLs del servicio Echo IP"
fr_FR: "Définir les URLs du service Echo IP"
pl_PL: "Ustaw adresy URL usługi Echo IP"
about.set-hostname: about.set-hostname:
en_US: "Set the server hostname" en_US: "Set the server hostname"
de_DE: "Den Server-Hostnamen festlegen" de_DE: "Den Server-Hostnamen festlegen"

View File

@@ -1,13 +0,0 @@
.ie \n(.g .ds Aq \(aq
.el .ds Aq '
.TH start-cli-auth-get-pubkey 1 "get-pubkey "
.SH NAME
start\-cli\-auth\-get\-pubkey \- Get the public key from the server
.SH SYNOPSIS
\fBstart\-cli auth get\-pubkey\fR [\fB\-h\fR|\fB\-\-help\fR]
.SH DESCRIPTION
Get the public key from the server
.SH OPTIONS
.TP
\fB\-h\fR, \fB\-\-help\fR
Print help

View File

@@ -1,13 +0,0 @@
.ie \n(.g .ds Aq \(aq
.el .ds Aq '
.TH start-cli-auth-login 1 "login "
.SH NAME
start\-cli\-auth\-login \- Login to a new auth session
.SH SYNOPSIS
\fBstart\-cli auth login\fR [\fB\-h\fR|\fB\-\-help\fR]
.SH DESCRIPTION
Login to a new auth session
.SH OPTIONS
.TP
\fB\-h\fR, \fB\-\-help\fR
Print help

View File

@@ -1,16 +0,0 @@
.ie \n(.g .ds Aq \(aq
.el .ds Aq '
.TH start-cli-auth-logout 1 "logout "
.SH NAME
start\-cli\-auth\-logout \- Logout from current auth session
.SH SYNOPSIS
\fBstart\-cli auth logout\fR [\fB\-h\fR|\fB\-\-help\fR] <\fISESSION\fR>
.SH DESCRIPTION
Logout from current auth session
.SH OPTIONS
.TP
\fB\-h\fR, \fB\-\-help\fR
Print help
.TP
<\fISESSION\fR>

View File

@@ -1,13 +0,0 @@
.ie \n(.g .ds Aq \(aq
.el .ds Aq '
.TH start-cli-auth-reset-password 1 "reset-password "
.SH NAME
start\-cli\-auth\-reset\-password \- Reset the password
.SH SYNOPSIS
\fBstart\-cli auth reset\-password\fR [\fB\-h\fR|\fB\-\-help\fR]
.SH DESCRIPTION
Reset the password
.SH OPTIONS
.TP
\fB\-h\fR, \fB\-\-help\fR
Print help

View File

@@ -1,16 +0,0 @@
.ie \n(.g .ds Aq \(aq
.el .ds Aq '
.TH start-cli-auth-session-kill 1 "kill "
.SH NAME
start\-cli\-auth\-session\-kill \- Terminate auth sessions
.SH SYNOPSIS
\fBstart\-cli auth session kill\fR [\fB\-h\fR|\fB\-\-help\fR] [\fIIDS\fR]
.SH DESCRIPTION
Terminate auth sessions
.SH OPTIONS
.TP
\fB\-h\fR, \fB\-\-help\fR
Print help
.TP
[\fIIDS\fR]
Session identifiers

View File

@@ -1,16 +0,0 @@
.ie \n(.g .ds Aq \(aq
.el .ds Aq '
.TH start-cli-auth-session-list 1 "list "
.SH NAME
start\-cli\-auth\-session\-list \- Display all auth sessions
.SH SYNOPSIS
\fBstart\-cli auth session list\fR [\fB\-\-format\fR] [\fB\-h\fR|\fB\-\-help\fR]
.SH DESCRIPTION
Display all auth sessions
.SH OPTIONS
.TP
\fB\-\-format\fR
.TP
\fB\-h\fR, \fB\-\-help\fR
Print help

View File

@@ -1,20 +0,0 @@
.ie \n(.g .ds Aq \(aq
.el .ds Aq '
.TH start-cli-auth-session 1 "session "
.SH NAME
start\-cli\-auth\-session \- List or kill auth sessions
.SH SYNOPSIS
\fBstart\-cli auth session\fR [\fB\-h\fR|\fB\-\-help\fR] <\fIsubcommands\fR>
.SH DESCRIPTION
List or kill auth sessions
.SH OPTIONS
.TP
\fB\-h\fR, \fB\-\-help\fR
Print help
.SH SUBCOMMANDS
.TP
start\-cli\-auth\-session\-kill(1)
Terminate auth sessions
.TP
start\-cli\-auth\-session\-list(1)
Display all auth sessions

View File

@@ -1,29 +0,0 @@
.ie \n(.g .ds Aq \(aq
.el .ds Aq '
.TH start-cli-auth 1 "auth "
.SH NAME
start\-cli\-auth \- Commands related to Authentication i.e. login, logout
.SH SYNOPSIS
\fBstart\-cli auth\fR [\fB\-h\fR|\fB\-\-help\fR] <\fIsubcommands\fR>
.SH DESCRIPTION
Commands related to Authentication i.e. login, logout
.SH OPTIONS
.TP
\fB\-h\fR, \fB\-\-help\fR
Print help
.SH SUBCOMMANDS
.TP
start\-cli\-auth\-get\-pubkey(1)
Get the public key from the server
.TP
start\-cli\-auth\-login(1)
Login to a new auth session
.TP
start\-cli\-auth\-logout(1)
Logout from current auth session
.TP
start\-cli\-auth\-reset\-password(1)
Reset the password
.TP
start\-cli\-auth\-session(1)
List or kill auth sessions

View File

@@ -1,25 +0,0 @@
.ie \n(.g .ds Aq \(aq
.el .ds Aq '
.TH start-cli-backup-create 1 "create "
.SH NAME
start\-cli\-backup\-create \- Create a backup for all packages
.SH SYNOPSIS
\fBstart\-cli backup create\fR [\fB\-\-old\-password\fR] [\fB\-\-package\-ids\fR] [\fB\-h\fR|\fB\-\-help\fR] <\fITARGET_ID\fR> <\fIPASSWORD\fR>
.SH DESCRIPTION
Create a backup for all packages
.SH OPTIONS
.TP
\fB\-\-old\-password\fR \fI<OLD_PASSWORD>\fR
Previous backup password
.TP
\fB\-\-package\-ids\fR \fI<PACKAGE_IDS>\fR
Package IDs to include in backup
.TP
\fB\-h\fR, \fB\-\-help\fR
Print help
.TP
<\fITARGET_ID\fR>
Backup target identifier
.TP
<\fIPASSWORD\fR>
Password for backup encryption

View File

@@ -1,25 +0,0 @@
.ie \n(.g .ds Aq \(aq
.el .ds Aq '
.TH start-cli-backup-target-cifs-add 1 "add "
.SH NAME
start\-cli\-backup\-target\-cifs\-add \- Add a new backup target
.SH SYNOPSIS
\fBstart\-cli backup target cifs add\fR [\fB\-h\fR|\fB\-\-help\fR] <\fIHOSTNAME\fR> <\fIPATH\fR> <\fIUSERNAME\fR> [\fIPASSWORD\fR]
.SH DESCRIPTION
Add a new backup target
.SH OPTIONS
.TP
\fB\-h\fR, \fB\-\-help\fR
Print help
.TP
<\fIHOSTNAME\fR>
CIFS server hostname
.TP
<\fIPATH\fR>
Path on the CIFS share
.TP
<\fIUSERNAME\fR>
CIFS authentication username
.TP
[\fIPASSWORD\fR]
CIFS authentication password

View File

@@ -1,16 +0,0 @@
.ie \n(.g .ds Aq \(aq
.el .ds Aq '
.TH start-cli-backup-target-cifs-remove 1 "remove "
.SH NAME
start\-cli\-backup\-target\-cifs\-remove \- Remove existing backup target
.SH SYNOPSIS
\fBstart\-cli backup target cifs remove\fR [\fB\-h\fR|\fB\-\-help\fR] <\fIID\fR>
.SH DESCRIPTION
Remove existing backup target
.SH OPTIONS
.TP
\fB\-h\fR, \fB\-\-help\fR
Print help
.TP
<\fIID\fR>
Backup target identifier

View File

@@ -1,28 +0,0 @@
.ie \n(.g .ds Aq \(aq
.el .ds Aq '
.TH start-cli-backup-target-cifs-update 1 "update "
.SH NAME
start\-cli\-backup\-target\-cifs\-update \- Update an existing backup target
.SH SYNOPSIS
\fBstart\-cli backup target cifs update\fR [\fB\-h\fR|\fB\-\-help\fR] <\fIID\fR> <\fIHOSTNAME\fR> <\fIPATH\fR> <\fIUSERNAME\fR> [\fIPASSWORD\fR]
.SH DESCRIPTION
Update an existing backup target
.SH OPTIONS
.TP
\fB\-h\fR, \fB\-\-help\fR
Print help
.TP
<\fIID\fR>
Backup target identifier
.TP
<\fIHOSTNAME\fR>
CIFS server hostname
.TP
<\fIPATH\fR>
Path on the CIFS share
.TP
<\fIUSERNAME\fR>
CIFS authentication username
.TP
[\fIPASSWORD\fR]
CIFS authentication password

View File

@@ -1,23 +0,0 @@
.ie \n(.g .ds Aq \(aq
.el .ds Aq '
.TH start-cli-backup-target-cifs 1 "cifs "
.SH NAME
start\-cli\-backup\-target\-cifs \- Add, remove, or update a backup target
.SH SYNOPSIS
\fBstart\-cli backup target cifs\fR [\fB\-h\fR|\fB\-\-help\fR] <\fIsubcommands\fR>
.SH DESCRIPTION
Add, remove, or update a backup target
.SH OPTIONS
.TP
\fB\-h\fR, \fB\-\-help\fR
Print help
.SH SUBCOMMANDS
.TP
start\-cli\-backup\-target\-cifs\-add(1)
Add a new backup target
.TP
start\-cli\-backup\-target\-cifs\-remove(1)
Remove existing backup target
.TP
start\-cli\-backup\-target\-cifs\-update(1)
Update an existing backup target

View File

@@ -1,25 +0,0 @@
.ie \n(.g .ds Aq \(aq
.el .ds Aq '
.TH start-cli-backup-target-info 1 "info "
.SH NAME
start\-cli\-backup\-target\-info \- Display backup information for a package
.SH SYNOPSIS
\fBstart\-cli backup target info\fR [\fB\-\-format\fR] [\fB\-h\fR|\fB\-\-help\fR] <\fITARGET_ID\fR> <\fISERVER_ID\fR> <\fIPASSWORD\fR>
.SH DESCRIPTION
Display backup information for a package
.SH OPTIONS
.TP
\fB\-\-format\fR
.TP
\fB\-h\fR, \fB\-\-help\fR
Print help
.TP
<\fITARGET_ID\fR>
Backup target identifier
.TP
<\fISERVER_ID\fR>
Unique server identifier
.TP
<\fIPASSWORD\fR>
Password for backup encryption

View File

@@ -1,16 +0,0 @@
.ie \n(.g .ds Aq \(aq
.el .ds Aq '
.TH start-cli-backup-target-list 1 "list "
.SH NAME
start\-cli\-backup\-target\-list \- List existing backup targets
.SH SYNOPSIS
\fBstart\-cli backup target list\fR [\fB\-\-format\fR] [\fB\-h\fR|\fB\-\-help\fR]
.SH DESCRIPTION
List existing backup targets
.SH OPTIONS
.TP
\fB\-\-format\fR
.TP
\fB\-h\fR, \fB\-\-help\fR
Print help

View File

@@ -1,25 +0,0 @@
.ie \n(.g .ds Aq \(aq
.el .ds Aq '
.TH start-cli-backup-target-mount 1 "mount "
.SH NAME
start\-cli\-backup\-target\-mount \- Mount a backup target
.SH SYNOPSIS
\fBstart\-cli backup target mount\fR [\fB\-\-server\-id\fR] [\fB\-\-allow\-partial\fR] [\fB\-h\fR|\fB\-\-help\fR] <\fITARGET_ID\fR> <\fIPASSWORD\fR>
.SH DESCRIPTION
Mount a backup target
.SH OPTIONS
.TP
\fB\-\-server\-id\fR \fI<SERVER_ID>\fR
Unique server identifier
.TP
\fB\-\-allow\-partial\fR
Leave media mounted even if backupfs fails to mount
.TP
\fB\-h\fR, \fB\-\-help\fR
Print help
.TP
<\fITARGET_ID\fR>
Backup target identifier
.TP
<\fIPASSWORD\fR>
Password for backup encryption

View File

@@ -1,16 +0,0 @@
.ie \n(.g .ds Aq \(aq
.el .ds Aq '
.TH start-cli-backup-target-umount 1 "umount "
.SH NAME
start\-cli\-backup\-target\-umount \- Unmount a backup target
.SH SYNOPSIS
\fBstart\-cli backup target umount\fR [\fB\-h\fR|\fB\-\-help\fR] [\fITARGET_ID\fR]
.SH DESCRIPTION
Unmount a backup target
.SH OPTIONS
.TP
\fB\-h\fR, \fB\-\-help\fR
Print help
.TP
[\fITARGET_ID\fR]
Backup target identifier

View File

@@ -1,29 +0,0 @@
.ie \n(.g .ds Aq \(aq
.el .ds Aq '
.TH start-cli-backup-target 1 "target "
.SH NAME
start\-cli\-backup\-target \- Commands related to a backup target
.SH SYNOPSIS
\fBstart\-cli backup target\fR [\fB\-h\fR|\fB\-\-help\fR] <\fIsubcommands\fR>
.SH DESCRIPTION
Commands related to a backup target
.SH OPTIONS
.TP
\fB\-h\fR, \fB\-\-help\fR
Print help
.SH SUBCOMMANDS
.TP
start\-cli\-backup\-target\-cifs(1)
Add, remove, or update a backup target
.TP
start\-cli\-backup\-target\-info(1)
Display backup information for a package
.TP
start\-cli\-backup\-target\-list(1)
List existing backup targets
.TP
start\-cli\-backup\-target\-mount(1)
Mount a backup target
.TP
start\-cli\-backup\-target\-umount(1)
Unmount a backup target

View File

@@ -1,20 +0,0 @@
.ie \n(.g .ds Aq \(aq
.el .ds Aq '
.TH start-cli-backup 1 "backup "
.SH NAME
start\-cli\-backup \- Commands related to backup creation and backup targets
.SH SYNOPSIS
\fBstart\-cli backup\fR [\fB\-h\fR|\fB\-\-help\fR] <\fIsubcommands\fR>
.SH DESCRIPTION
Commands related to backup creation and backup targets
.SH OPTIONS
.TP
\fB\-h\fR, \fB\-\-help\fR
Print help
.SH SUBCOMMANDS
.TP
start\-cli\-backup\-create(1)
Create a backup for all packages
.TP
start\-cli\-backup\-target(1)
Commands related to a backup target

View File

@@ -1,22 +0,0 @@
.ie \n(.g .ds Aq \(aq
.el .ds Aq '
.TH start-cli-db-apply 1 "apply "
.SH NAME
start\-cli\-db\-apply \- Update a database record
.SH SYNOPSIS
\fBstart\-cli db apply\fR [\fB\-\-allow\-model\-mismatch\fR] [\fB\-h\fR|\fB\-\-help\fR] <\fIEXPR\fR> [\fIPATH\fR]
.SH DESCRIPTION
Update a database record
.SH OPTIONS
.TP
\fB\-\-allow\-model\-mismatch\fR
Allow database model mismatch
.TP
\fB\-h\fR, \fB\-\-help\fR
Print help
.TP
<\fIEXPR\fR>
Database patch expression to apply
.TP
[\fIPATH\fR]
Path to the database

View File

@@ -1,22 +0,0 @@
.ie \n(.g .ds Aq \(aq
.el .ds Aq '
.TH start-cli-db-dump 1 "dump "
.SH NAME
start\-cli\-db\-dump \- Filter and query the database
.SH SYNOPSIS
\fBstart\-cli db dump\fR [\fB\-p\fR|\fB\-\-include\-private\fR] [\fB\-\-format\fR] [\fB\-h\fR|\fB\-\-help\fR] [\fIPATH\fR]
.SH DESCRIPTION
Filter and query the database
.SH OPTIONS
.TP
\fB\-p\fR, \fB\-\-include\-private\fR
Include private data in output
.TP
\fB\-\-format\fR
.TP
\fB\-h\fR, \fB\-\-help\fR
Print help
.TP
[\fIPATH\fR]
Path to the database

View File

@@ -1,22 +0,0 @@
.ie \n(.g .ds Aq \(aq
.el .ds Aq '
.TH start-cli-db-put-ui 1 "ui "
.SH NAME
start\-cli\-db\-put\-ui \- Add path and value to db
.SH SYNOPSIS
\fBstart\-cli db put ui\fR [\fB\-\-format\fR] [\fB\-h\fR|\fB\-\-help\fR] <\fIPOINTER\fR> <\fIVALUE\fR>
.SH DESCRIPTION
Add path and value to db
.SH OPTIONS
.TP
\fB\-\-format\fR
.TP
\fB\-h\fR, \fB\-\-help\fR
Print help
.TP
<\fIPOINTER\fR>
JSON pointer to specific value
.TP
<\fIVALUE\fR>
JSON value to set

View File

@@ -1,17 +0,0 @@
.ie \n(.g .ds Aq \(aq
.el .ds Aq '
.TH start-cli-db-put 1 "put "
.SH NAME
start\-cli\-db\-put \- Command for adding UI record to db
.SH SYNOPSIS
\fBstart\-cli db put\fR [\fB\-h\fR|\fB\-\-help\fR] <\fIsubcommands\fR>
.SH DESCRIPTION
Command for adding UI record to db
.SH OPTIONS
.TP
\fB\-h\fR, \fB\-\-help\fR
Print help
.SH SUBCOMMANDS
.TP
start\-cli\-db\-put\-ui(1)
Add path and value to db

View File

@@ -1,23 +0,0 @@
.ie \n(.g .ds Aq \(aq
.el .ds Aq '
.TH start-cli-db 1 "db "
.SH NAME
start\-cli\-db \- Commands to interact with the db i.e. dump, put, apply
.SH SYNOPSIS
\fBstart\-cli db\fR [\fB\-h\fR|\fB\-\-help\fR] <\fIsubcommands\fR>
.SH DESCRIPTION
Commands to interact with the db i.e. dump, put, apply
.SH OPTIONS
.TP
\fB\-h\fR, \fB\-\-help\fR
Print help
.SH SUBCOMMANDS
.TP
start\-cli\-db\-apply(1)
Update a database record
.TP
start\-cli\-db\-dump(1)
Filter and query the database
.TP
start\-cli\-db\-put(1)
Command for adding UI record to db

View File

@@ -1,13 +0,0 @@
.ie \n(.g .ds Aq \(aq
.el .ds Aq '
.TH start-cli-diagnostic-disk-forget 1 "forget "
.SH NAME
start\-cli\-diagnostic\-disk\-forget \- Remove disk filesystem
.SH SYNOPSIS
\fBstart\-cli diagnostic disk forget\fR [\fB\-h\fR|\fB\-\-help\fR]
.SH DESCRIPTION
Remove disk filesystem
.SH OPTIONS
.TP
\fB\-h\fR, \fB\-\-help\fR
Print help

View File

@@ -1,13 +0,0 @@
.ie \n(.g .ds Aq \(aq
.el .ds Aq '
.TH start-cli-diagnostic-disk-repair 1 "repair "
.SH NAME
start\-cli\-diagnostic\-disk\-repair \- Repair disk corruption
.SH SYNOPSIS
\fBstart\-cli diagnostic disk repair\fR [\fB\-h\fR|\fB\-\-help\fR]
.SH DESCRIPTION
Repair disk corruption
.SH OPTIONS
.TP
\fB\-h\fR, \fB\-\-help\fR
Print help

View File

@@ -1,20 +0,0 @@
.ie \n(.g .ds Aq \(aq
.el .ds Aq '
.TH start-cli-diagnostic-disk 1 "disk "
.SH NAME
start\-cli\-diagnostic\-disk \- Command to remove disk from filesystem
.SH SYNOPSIS
\fBstart\-cli diagnostic disk\fR [\fB\-h\fR|\fB\-\-help\fR] <\fIsubcommands\fR>
.SH DESCRIPTION
Command to remove disk from filesystem
.SH OPTIONS
.TP
\fB\-h\fR, \fB\-\-help\fR
Print help
.SH SUBCOMMANDS
.TP
start\-cli\-diagnostic\-disk\-forget(1)
Remove disk filesystem
.TP
start\-cli\-diagnostic\-disk\-repair(1)
Repair disk corruption

View File

@@ -1,13 +0,0 @@
.ie \n(.g .ds Aq \(aq
.el .ds Aq '
.TH start-cli-diagnostic-error 1 "error "
.SH NAME
start\-cli\-diagnostic\-error \- Display diagnostic error
.SH SYNOPSIS
\fBstart\-cli diagnostic error\fR [\fB\-h\fR|\fB\-\-help\fR]
.SH DESCRIPTION
Display diagnostic error
.SH OPTIONS
.TP
\fB\-h\fR, \fB\-\-help\fR
Print help

View File

@@ -1,28 +0,0 @@
.ie \n(.g .ds Aq \(aq
.el .ds Aq '
.TH start-cli-diagnostic-kernel-logs 1 "kernel-logs "
.SH NAME
start\-cli\-diagnostic\-kernel\-logs \- Display kernel logs
.SH SYNOPSIS
\fBstart\-cli diagnostic kernel\-logs\fR [\fB\-l\fR|\fB\-\-limit\fR] [\fB\-c\fR|\fB\-\-cursor\fR] [\fB\-b\fR|\fB\-\-boot\fR] [\fB\-B\fR|\fB\-\-before\fR] [\fB\-f\fR|\fB\-\-follow\fR] [\fB\-h\fR|\fB\-\-help\fR]
.SH DESCRIPTION
Display kernel logs
.SH OPTIONS
.TP
\fB\-l\fR, \fB\-\-limit\fR \fI<LIMIT>\fR
Maximum number of log entries
.TP
\fB\-c\fR, \fB\-\-cursor\fR \fI<CURSOR>\fR
Start from this cursor position
.TP
\fB\-b\fR, \fB\-\-boot\fR \fI<BOOT>\fR
Filter logs by boot ID
.TP
\fB\-B\fR, \fB\-\-before\fR
Show logs before the cursor position
.TP
\fB\-f\fR, \fB\-\-follow\fR
Follow log output in real\-time
.TP
\fB\-h\fR, \fB\-\-help\fR
Print help

View File

@@ -1,28 +0,0 @@
.ie \n(.g .ds Aq \(aq
.el .ds Aq '
.TH start-cli-diagnostic-logs 1 "logs "
.SH NAME
start\-cli\-diagnostic\-logs \- Display OS logs
.SH SYNOPSIS
\fBstart\-cli diagnostic logs\fR [\fB\-l\fR|\fB\-\-limit\fR] [\fB\-c\fR|\fB\-\-cursor\fR] [\fB\-b\fR|\fB\-\-boot\fR] [\fB\-B\fR|\fB\-\-before\fR] [\fB\-f\fR|\fB\-\-follow\fR] [\fB\-h\fR|\fB\-\-help\fR]
.SH DESCRIPTION
Display OS logs
.SH OPTIONS
.TP
\fB\-l\fR, \fB\-\-limit\fR \fI<LIMIT>\fR
Maximum number of log entries
.TP
\fB\-c\fR, \fB\-\-cursor\fR \fI<CURSOR>\fR
Start from this cursor position
.TP
\fB\-b\fR, \fB\-\-boot\fR \fI<BOOT>\fR
Filter logs by boot ID
.TP
\fB\-B\fR, \fB\-\-before\fR
Show logs before the cursor position
.TP
\fB\-f\fR, \fB\-\-follow\fR
Follow log output in real\-time
.TP
\fB\-h\fR, \fB\-\-help\fR
Print help

View File

@@ -1,13 +0,0 @@
.ie \n(.g .ds Aq \(aq
.el .ds Aq '
.TH start-cli-diagnostic-rebuild 1 "rebuild "
.SH NAME
start\-cli\-diagnostic\-rebuild \- Teardown and rebuild containers
.SH SYNOPSIS
\fBstart\-cli diagnostic rebuild\fR [\fB\-h\fR|\fB\-\-help\fR]
.SH DESCRIPTION
Teardown and rebuild containers
.SH OPTIONS
.TP
\fB\-h\fR, \fB\-\-help\fR
Print help

View File

@@ -1,13 +0,0 @@
.ie \n(.g .ds Aq \(aq
.el .ds Aq '
.TH start-cli-diagnostic-restart 1 "restart "
.SH NAME
start\-cli\-diagnostic\-restart \- Restart the server
.SH SYNOPSIS
\fBstart\-cli diagnostic restart\fR [\fB\-h\fR|\fB\-\-help\fR]
.SH DESCRIPTION
Restart the server
.SH OPTIONS
.TP
\fB\-h\fR, \fB\-\-help\fR
Print help

View File

@@ -1,32 +0,0 @@
.ie \n(.g .ds Aq \(aq
.el .ds Aq '
.TH start-cli-diagnostic 1 "diagnostic "
.SH NAME
start\-cli\-diagnostic \- Commands to display logs, restart the server, etc
.SH SYNOPSIS
\fBstart\-cli diagnostic\fR [\fB\-h\fR|\fB\-\-help\fR] <\fIsubcommands\fR>
.SH DESCRIPTION
Commands to display logs, restart the server, etc
.SH OPTIONS
.TP
\fB\-h\fR, \fB\-\-help\fR
Print help
.SH SUBCOMMANDS
.TP
start\-cli\-diagnostic\-disk(1)
Command to remove disk from filesystem
.TP
start\-cli\-diagnostic\-error(1)
Display diagnostic error
.TP
start\-cli\-diagnostic\-kernel\-logs(1)
Display kernel logs
.TP
start\-cli\-diagnostic\-logs(1)
Display OS logs
.TP
start\-cli\-diagnostic\-rebuild(1)
Teardown and rebuild containers
.TP
start\-cli\-diagnostic\-restart(1)
Restart the server

View File

@@ -1,16 +0,0 @@
.ie \n(.g .ds Aq \(aq
.el .ds Aq '
.TH start-cli-disk-list 1 "list "
.SH NAME
start\-cli\-disk\-list \- List disk information
.SH SYNOPSIS
\fBstart\-cli disk list\fR [\fB\-\-format\fR] [\fB\-h\fR|\fB\-\-help\fR]
.SH DESCRIPTION
List disk information
.SH OPTIONS
.TP
\fB\-\-format\fR
.TP
\fB\-h\fR, \fB\-\-help\fR
Print help

View File

@@ -1,13 +0,0 @@
.ie \n(.g .ds Aq \(aq
.el .ds Aq '
.TH start-cli-disk-repair 1 "repair "
.SH NAME
start\-cli\-disk\-repair \- Repair disk corruption
.SH SYNOPSIS
\fBstart\-cli disk repair\fR [\fB\-h\fR|\fB\-\-help\fR]
.SH DESCRIPTION
Repair disk corruption
.SH OPTIONS
.TP
\fB\-h\fR, \fB\-\-help\fR
Print help

View File

@@ -1,20 +0,0 @@
.ie \n(.g .ds Aq \(aq
.el .ds Aq '
.TH start-cli-disk 1 "disk "
.SH NAME
start\-cli\-disk \- Commands for listing disk info and repairing
.SH SYNOPSIS
\fBstart\-cli disk\fR [\fB\-h\fR|\fB\-\-help\fR] <\fIsubcommands\fR>
.SH DESCRIPTION
Commands for listing disk info and repairing
.SH OPTIONS
.TP
\fB\-h\fR, \fB\-\-help\fR
Print help
.SH SUBCOMMANDS
.TP
start\-cli\-disk\-list(1)
List disk information
.TP
start\-cli\-disk\-repair(1)
Repair disk corruption

View File

@@ -1,16 +0,0 @@
.ie \n(.g .ds Aq \(aq
.el .ds Aq '
.TH start-cli-echo 1 "echo "
.SH NAME
start\-cli\-echo \- Echo a message back
.SH SYNOPSIS
\fBstart\-cli echo\fR [\fB\-h\fR|\fB\-\-help\fR] <\fIMESSAGE\fR>
.SH DESCRIPTION
Echo a message back
.SH OPTIONS
.TP
\fB\-h\fR, \fB\-\-help\fR
Print help
.TP
<\fIMESSAGE\fR>
Message to echo back

View File

@@ -1,32 +0,0 @@
.ie \n(.g .ds Aq \(aq
.el .ds Aq '
.TH start-cli-flash-os 1 "flash-os "
.SH NAME
start\-cli\-flash\-os \- Flash StartOS to a drive
.SH SYNOPSIS
\fBstart\-cli flash\-os\fR [\fB\-\-efi\fR] [\fB\-h\fR|\fB\-\-help\fR] <\fISQUASHFS\fR> <\fIDISK\fR>
.SH DESCRIPTION
Flash StartOS to a drive
.SH OPTIONS
.TP
\fB\-\-efi\fR \fI<EFI>\fR
Use EFI boot mode
.br
.br
\fIPossible values:\fR
.RS 14
.IP \(bu 2
true
.IP \(bu 2
false
.RE
.TP
\fB\-h\fR, \fB\-\-help\fR
Print help
.TP
<\fISQUASHFS\fR>
Path to squashfs image file
.TP
<\fIDISK\fR>
Target disk for installation

View File

@@ -1,13 +0,0 @@
.ie \n(.g .ds Aq \(aq
.el .ds Aq '
.TH start-cli-git-info 1 "git-info "
.SH NAME
start\-cli\-git\-info \- Display the git hash of this build
.SH SYNOPSIS
\fBstart\-cli git\-info\fR [\fB\-h\fR|\fB\-\-help\fR]
.SH DESCRIPTION
Display the git hash of this build
.SH OPTIONS
.TP
\fB\-h\fR, \fB\-\-help\fR
Print help

View File

@@ -1,28 +0,0 @@
.ie \n(.g .ds Aq \(aq
.el .ds Aq '
.TH start-cli-init-kernel-logs 1 "kernel-logs "
.SH NAME
start\-cli\-init\-kernel\-logs \- Display kernel logs
.SH SYNOPSIS
\fBstart\-cli init kernel\-logs\fR [\fB\-l\fR|\fB\-\-limit\fR] [\fB\-c\fR|\fB\-\-cursor\fR] [\fB\-b\fR|\fB\-\-boot\fR] [\fB\-B\fR|\fB\-\-before\fR] [\fB\-f\fR|\fB\-\-follow\fR] [\fB\-h\fR|\fB\-\-help\fR]
.SH DESCRIPTION
Display kernel logs
.SH OPTIONS
.TP
\fB\-l\fR, \fB\-\-limit\fR \fI<LIMIT>\fR
Maximum number of log entries
.TP
\fB\-c\fR, \fB\-\-cursor\fR \fI<CURSOR>\fR
Start from this cursor position
.TP
\fB\-b\fR, \fB\-\-boot\fR \fI<BOOT>\fR
Filter logs by boot ID
.TP
\fB\-B\fR, \fB\-\-before\fR
Show logs before the cursor position
.TP
\fB\-f\fR, \fB\-\-follow\fR
Follow log output in real\-time
.TP
\fB\-h\fR, \fB\-\-help\fR
Print help

View File

@@ -1,13 +0,0 @@
.ie \n(.g .ds Aq \(aq
.el .ds Aq '
.TH start-cli-init-key 1 "init-key "
.SH NAME
start\-cli\-init\-key \- Create a new developer key
.SH SYNOPSIS
\fBstart\-cli init\-key\fR [\fB\-h\fR|\fB\-\-help\fR]
.SH DESCRIPTION
Create a new developer key
.SH OPTIONS
.TP
\fB\-h\fR, \fB\-\-help\fR
Print help

View File

@@ -1,28 +0,0 @@
.ie \n(.g .ds Aq \(aq
.el .ds Aq '
.TH start-cli-init-logs 1 "logs "
.SH NAME
start\-cli\-init\-logs \- Display OS logs
.SH SYNOPSIS
\fBstart\-cli init logs\fR [\fB\-l\fR|\fB\-\-limit\fR] [\fB\-c\fR|\fB\-\-cursor\fR] [\fB\-b\fR|\fB\-\-boot\fR] [\fB\-B\fR|\fB\-\-before\fR] [\fB\-f\fR|\fB\-\-follow\fR] [\fB\-h\fR|\fB\-\-help\fR]
.SH DESCRIPTION
Display OS logs
.SH OPTIONS
.TP
\fB\-l\fR, \fB\-\-limit\fR \fI<LIMIT>\fR
Maximum number of log entries
.TP
\fB\-c\fR, \fB\-\-cursor\fR \fI<CURSOR>\fR
Start from this cursor position
.TP
\fB\-b\fR, \fB\-\-boot\fR \fI<BOOT>\fR
Filter logs by boot ID
.TP
\fB\-B\fR, \fB\-\-before\fR
Show logs before the cursor position
.TP
\fB\-f\fR, \fB\-\-follow\fR
Follow log output in real\-time
.TP
\fB\-h\fR, \fB\-\-help\fR
Print help

View File

@@ -1,13 +0,0 @@
.ie \n(.g .ds Aq \(aq
.el .ds Aq '
.TH start-cli-init-subscribe 1 "subscribe "
.SH NAME
start\-cli\-init\-subscribe \- Get initialization progress
.SH SYNOPSIS
\fBstart\-cli init subscribe\fR [\fB\-h\fR|\fB\-\-help\fR]
.SH DESCRIPTION
Get initialization progress
.SH OPTIONS
.TP
\fB\-h\fR, \fB\-\-help\fR
Print help

View File

@@ -1,23 +0,0 @@
.ie \n(.g .ds Aq \(aq
.el .ds Aq '
.TH start-cli-init 1 "init "
.SH NAME
start\-cli\-init \- Commands for initialization
.SH SYNOPSIS
\fBstart\-cli init\fR [\fB\-h\fR|\fB\-\-help\fR] <\fIsubcommands\fR>
.SH DESCRIPTION
Commands for initialization
.SH OPTIONS
.TP
\fB\-h\fR, \fB\-\-help\fR
Print help
.SH SUBCOMMANDS
.TP
start\-cli\-init\-kernel\-logs(1)
Display kernel logs
.TP
start\-cli\-init\-logs(1)
Display OS logs
.TP
start\-cli\-init\-subscribe(1)
Get initialization progress

View File

@@ -1,13 +0,0 @@
.ie \n(.g .ds Aq \(aq
.el .ds Aq '
.TH start-cli-kiosk-disable 1 "disable "
.SH NAME
start\-cli\-kiosk\-disable \- Disable kiosk mode
.SH SYNOPSIS
\fBstart\-cli kiosk disable\fR [\fB\-h\fR|\fB\-\-help\fR]
.SH DESCRIPTION
Disable kiosk mode
.SH OPTIONS
.TP
\fB\-h\fR, \fB\-\-help\fR
Print help

View File

@@ -1,13 +0,0 @@
.ie \n(.g .ds Aq \(aq
.el .ds Aq '
.TH start-cli-kiosk-enable 1 "enable "
.SH NAME
start\-cli\-kiosk\-enable \- Enable kiosk mode
.SH SYNOPSIS
\fBstart\-cli kiosk enable\fR [\fB\-h\fR|\fB\-\-help\fR]
.SH DESCRIPTION
Enable kiosk mode
.SH OPTIONS
.TP
\fB\-h\fR, \fB\-\-help\fR
Print help

View File

@@ -1,20 +0,0 @@
.ie \n(.g .ds Aq \(aq
.el .ds Aq '
.TH start-cli-kiosk 1 "kiosk "
.SH NAME
start\-cli\-kiosk \- Commands for kiosk mode
.SH SYNOPSIS
\fBstart\-cli kiosk\fR [\fB\-h\fR|\fB\-\-help\fR] <\fIsubcommands\fR>
.SH DESCRIPTION
Commands for kiosk mode
.SH OPTIONS
.TP
\fB\-h\fR, \fB\-\-help\fR
Print help
.SH SUBCOMMANDS
.TP
start\-cli\-kiosk\-disable(1)
Disable kiosk mode
.TP
start\-cli\-kiosk\-enable(1)
Enable kiosk mode

View File

@@ -1,19 +0,0 @@
.ie \n(.g .ds Aq \(aq
.el .ds Aq '
.TH start-cli-net-acme-init 1 "init "
.SH NAME
start\-cli\-net\-acme\-init \- Setup ACME certificate acquisition
.SH SYNOPSIS
\fBstart\-cli net acme init\fR <\fB\-\-provider\fR> [\fB\-\-contact\fR] [\fB\-h\fR|\fB\-\-help\fR]
.SH DESCRIPTION
Setup ACME certificate acquisition
.SH OPTIONS
.TP
\fB\-\-provider\fR \fI<PROVIDER>\fR
ACME provider identifier or url
.TP
\fB\-\-contact\fR \fI<CONTACT>\fR
Contact email for ACME certificate authority
.TP
\fB\-h\fR, \fB\-\-help\fR
Print help

View File

@@ -1,16 +0,0 @@
.ie \n(.g .ds Aq \(aq
.el .ds Aq '
.TH start-cli-net-acme-remove 1 "remove "
.SH NAME
start\-cli\-net\-acme\-remove \- Remove ACME certificate acquisition configuration
.SH SYNOPSIS
\fBstart\-cli net acme remove\fR <\fB\-\-provider\fR> [\fB\-h\fR|\fB\-\-help\fR]
.SH DESCRIPTION
Remove ACME certificate acquisition configuration
.SH OPTIONS
.TP
\fB\-\-provider\fR \fI<PROVIDER>\fR
ACME provider identifier or url
.TP
\fB\-h\fR, \fB\-\-help\fR
Print help

View File

@@ -1,20 +0,0 @@
.ie \n(.g .ds Aq \(aq
.el .ds Aq '
.TH start-cli-net-acme 1 "acme "
.SH NAME
start\-cli\-net\-acme \- Setup ACME certificate
.SH SYNOPSIS
\fBstart\-cli net acme\fR [\fB\-h\fR|\fB\-\-help\fR] <\fIsubcommands\fR>
.SH DESCRIPTION
Setup ACME certificate
.SH OPTIONS
.TP
\fB\-h\fR, \fB\-\-help\fR
Print help
.SH SUBCOMMANDS
.TP
start\-cli\-net\-acme\-init(1)
Setup ACME certificate acquisition
.TP
start\-cli\-net\-acme\-remove(1)
Remove ACME certificate acquisition configuration

View File

@@ -1,16 +0,0 @@
.ie \n(.g .ds Aq \(aq
.el .ds Aq '
.TH start-cli-net-dns-dump-table 1 "dump-table "
.SH NAME
start\-cli\-net\-dns\-dump\-table \- Dump address resolution table
.SH SYNOPSIS
\fBstart\-cli net dns dump\-table\fR [\fB\-\-format\fR] [\fB\-h\fR|\fB\-\-help\fR]
.SH DESCRIPTION
Dump address resolution table
.SH OPTIONS
.TP
\fB\-\-format\fR
.TP
\fB\-h\fR, \fB\-\-help\fR
Print help

View File

@@ -1,19 +0,0 @@
.ie \n(.g .ds Aq \(aq
.el .ds Aq '
.TH start-cli-net-dns-query 1 "query "
.SH NAME
start\-cli\-net\-dns\-query \- Test DNS configuration for a domain
.SH SYNOPSIS
\fBstart\-cli net dns query\fR [\fB\-\-format\fR] [\fB\-h\fR|\fB\-\-help\fR] <\fIFQDN\fR>
.SH DESCRIPTION
Test DNS configuration for a domain
.SH OPTIONS
.TP
\fB\-\-format\fR
.TP
\fB\-h\fR, \fB\-\-help\fR
Print help
.TP
<\fIFQDN\fR>
Fully qualified domain name

View File

@@ -1,16 +0,0 @@
.ie \n(.g .ds Aq \(aq
.el .ds Aq '
.TH start-cli-net-dns-set-static 1 "set-static "
.SH NAME
start\-cli\-net\-dns\-set\-static \- Set static DNS servers
.SH SYNOPSIS
\fBstart\-cli net dns set\-static\fR [\fB\-h\fR|\fB\-\-help\fR] [\fISERVERS\fR]
.SH DESCRIPTION
Set static DNS servers
.SH OPTIONS
.TP
\fB\-h\fR, \fB\-\-help\fR
Print help
.TP
[\fISERVERS\fR]
DNS servers to use

View File

@@ -1,23 +0,0 @@
.ie \n(.g .ds Aq \(aq
.el .ds Aq '
.TH start-cli-net-dns 1 "dns "
.SH NAME
start\-cli\-net\-dns \- Manage and query DNS
.SH SYNOPSIS
\fBstart\-cli net dns\fR [\fB\-h\fR|\fB\-\-help\fR] <\fIsubcommands\fR>
.SH DESCRIPTION
Manage and query DNS
.SH OPTIONS
.TP
\fB\-h\fR, \fB\-\-help\fR
Print help
.SH SUBCOMMANDS
.TP
start\-cli\-net\-dns\-dump\-table(1)
Dump address resolution table
.TP
start\-cli\-net\-dns\-query(1)
Test DNS configuration for a domain
.TP
start\-cli\-net\-dns\-set\-static(1)
Set static DNS servers

Some files were not shown because too many files have changed in this diff Show More